LoginSignup
1
0

More than 5 years have passed since last update.

Java Sound APIを使ってMIDIファイルを再生する方法(使用するMIDIデバイスを指定する)

Posted at

はじめに

前回の記事の続きです。

概要

前回のMIDIファイル再生サンプルに、使用するMIDIシンセサイザー選択機能を実装します。
以下、実際の実行画面です。

[0] Gervill
[1] LoopBe Internal MIDI
[2] Microsoft MIDI Mapper
[3] CoolSoft MIDIMapper
[4] Microsoft GS Wavetable Synth
[5] VirtualMIDISynth #1
[6] LoopBe Internal MIDI
[7] Real Time Sequencer

使用するMIDIデバイスの番号を入力 >> 4
[Microsoft GS Wavetable Synth]を開いています...

MIDIファイルのパス >> sample.mid
再生中...
適当に文字列を入力すると終了します。
>>a
停止

ちなみに、
0番目の「Gervill」というデバイスがJavaのライブラリが提供するMIDIシンセサイザーです。
デフォルトでは、こちらのデバイスが指定されます。

今回使用している「Microsoft GS Wavetable Synth」は、Windowsで標準搭載されているシンセサイザーです。

サンプルコード

SamplePlayer.java
import java.io.File;
import java.io.IOException;
import java.util.Scanner;

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;

public class SamplePlayer {

    public static void main(String[] args) {
        // MIDIデータを再生するハードウェア/ソフトウェア・デバイスのインスタンス。
        Sequencer sequencer = null;

        Scanner scanner = new Scanner(System.in);

        try {
            // Sequencerインスタンスを取得する。
            sequencer = MidiSystem.getSequencer(false);

            // デバイスを開き、リソースを獲得する。
            sequencer.open();

            // 使用可能なMIDIデバイスの一覧を取得する。
            MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
            for (int i=0; i<infos.length; i++) {
                String line = String.format("[%s] %s", i, infos[i].getName());
                System.out.println(line);
            }
            System.out.println();

            int index = 0;
            while (true) {
                // コンソール入力から使用するMIDIデバイスのインデックスを取得する。
                System.out.print("使用するMIDIデバイスの番号を入力 >> ");
                String str = scanner.next();

                try {
                    index = Integer.parseInt(str);
                }
                catch (NumberFormatException nfe) {
                    continue;
                }
                break;
            }

            // システムに目的のデバイスを表すデバイス情報を持った、MIDIデバイスを要求する。
            MidiDevice device = MidiSystem.getMidiDevice(infos[index]);

            System.out.println("[" + device.getDeviceInfo().getName() + "]を開いています...");

            // MIDIデバイスを開く。
            if (device.isOpen() == false) {
                device.open();
            }

            // シーケンサのMIDI OUTとMIDIデバイスのMIDI INを接続する。
            Receiver receiver = device.getReceiver();
            sequencer.getTransmitter().setReceiver(receiver);
        }
        catch (MidiUnavailableException e) {
            e.printStackTrace();
        }
        System.out.println();

        // コンソール入力からMIDIファイルのパスを取得する。
        System.out.print("MIDIファイルのパス >> ");
        String path = scanner.next();

        try {
            // MIDIファイルからMIDIデータ(Sequenceオブジェクト)を取得。
            File file = new File(path);
            Sequence sequence = MidiSystem.getSequence(file);

            // 取得したMIDIデータをシーケンサに設定する。
            sequencer.setSequence(sequence);
        }
        catch (InvalidMidiDataException e) {
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }

        // シーケンサー再生
        sequencer.start();
        System.out.println("再生中...");

        // キー入力待ち
        System.out.println("適当に文字列を入力すると終了します。");
        System.out.print(">>");
        scanner.next();
        scanner.close();

        // シーケンサー停止
        sequencer.stop();
        System.out.println("停止");

        // シーケンサーを閉じ、使用していたリソース解放する。
        sequencer.close();
    }
}

解説

使用可能なデバイス情報一覧を取得

使用可能な全MIDIデバイス情報のオブジェクト配列を取得します。

// 使用可能なMIDIデバイスの一覧を取得する。
MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();

デバイスのオブジェクト取得

取得したデバイス情報のオブジェクトを使用して、getMidiDeviceを呼び出すことにより、対応するデバイスを取得できます。
取得したデバイスで、openを呼び出すことで操作可能にします。

// システムに目的のデバイスを表すデバイス情報を持った、MIDIデバイスを要求する。
MidiDevice device = MidiSystem.getMidiDevice(infos[index]);

// MIDIデバイスを開く。
if (device.isOpen() == false) {
   device.open();
}

シーケンサーとデバイスを接続

MIDIデバイスのクラスが提供するインターフェースには、以下の2つがあります。

インターフェース名 概要 一般的に使用されているもの
Transmitter MIDIデータの送信を行う。 シーケンサー・MIDI入力機器等
Receiver MIDIデータの受信を行う。 シンセサイザー・MIDI出力機器

今回は、シーケンサのMIDI送信ポート(Transmitter)に、指定したMIDIデバイスのMIDI受信ポート(Receiver)を接続します。

// シーケンサのMIDI OUTとMIDIデバイスのMIDI INを接続する。
Receiver receiver = device.getReceiver();
sequencer.getTransmitter().setReceiver(receiver);

そうすると、だいたいこのような構成イメージになります。デバイス構成.png

以上で、デバイスの接続は完了です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0