人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

シーケンサとシンセサイザー

Java Sound APIを用いてMIDIデータ(MIDIシーケンスと呼びます)を鳴らす手法です。シーケンサとシンセサイザを用います。曲はTAM MUSIC FACTORYさんから。

midi_engine.jar

シーケンサとシンセサイザの関係図

f:id:aidiary:20100529215821j:plain

シーケンサは指揮者、シンセサイザは演奏者と考えるとわかりやすいかも。シーケンサは楽譜(MIDIファイル)を見ながらデータの流れの指揮を取り、シンセサイザは実際に音を鳴らして演奏します。MIDIデータはSequenceと呼ばれます。

シーケンサの初期化

    // シーケンサー
    private Sequencer sequencer;
    // シンセサイザー
    private Synthesizer synthesizer;

    private void initSequencer() {
        try {
            // シーケンサを開く
            sequencer = MidiSystem.getSequencer();
            sequencer.open();
            // メタイベントリスナーを登録
            sequencer.addMetaEventListener(this);
            // シーケンサとシンセサイザーの接続
            if (!(sequencer instanceof Synthesizer)) { // J2SE 5.0用
                // シンセサイザーを開く
                synthesizer = MidiSystem.getSynthesizer();
                synthesizer.open();
                Receiver synthReceiver = synthesizer.getReceiver();
                Transmitter seqTransmitter = sequencer.getTransmitter();
                seqTransmitter.setReceiver(synthReceiver);
            } else { // J2SE 1.4.2以前
                // シーケンサとシンセサイザーは同じ
                synthesizer = (Synthesizer) sequencer;
            }
        } catch (MidiUnavailableException e) {
            e.printStackTrace();
        }
    }

MIDIシーケンスのロード

    // MIDIファイルデータ(名前->Sequence)
    private HashMap<String, Sequence> midiMap;

    public void load(String name, String filename) {
        ・・・
        try {
            // MIDIファイルをロード
            Sequence seq = MidiSystem.getSequence(
                getClass().getResource(filename));
            // 登録
            midiMap.put(name, seq);
        } catch (InvalidMidiDataException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

MIDIシーケンスの再生

    public void play(String name) {
        ・・・

        // 現在再生中のシーケンスを停止する
        stop();

        // 名前に対応するMIDIを取得
        Sequence seq = midiMap.get(name);  // MIDIシーケンス
        if (sequencer != null && seq != null) {
            try {
                sequencer.setSequence(seq);  // シーケンサにセット
                sequencer.start();  // 再生開始!
                currentSequenceName = name;
            } catch (InvalidMidiDataException e) {
                e.printStackTrace();
            }
        }
    }

ループ処理

    // 再生終了メタイベント
    private static final int END_OF_TRACK = 47;

    public void meta(MetaMessage meta) {
        // 再生が終了した場合
        if (meta.getType() == END_OF_TRACK) {
            if (sequencer != null && sequencer.isOpen()) {
                // MIDIシーケンス再生位置に戻す
                sequencer.setMicrosecondPosition(0);
                // 最初から再生
                sequencer.start();
            }
        }
    }