MIDI音源による演奏

  1. 目的
    midi音源による楽譜の演奏方法を紹介します。

  2. MIDIとは
    1. MIDI
      Musical Instrument Digital interfaceで楽器の演奏情報をMIDIケーブルを通して送るための標準規格です。
      詳細な日本語の説明は
       http://www.b-sharp.com/midi/index.html
      にあります。

    2. シーケンサ、音源
      シーケンサはMIDIメッセージを音源に送る制御装置で多くはアプリケーションソフトウエアです。MIDI音源はMIDIメッセージに指定されたチャンネル番号、音の高さ、強さ、で演奏します。
       1本のMIDIケーブルで16チャンネルの指定が可能で、同時に16種の音を出すことができます。シーケンサによっては、複数(多くは2本)のMIDIケーブルを利用して、同時32の音源を制御できます。

    3. チャンネル、音色
       MIDIには16のチャンネルがあり、各チャンネルにピアノやフルートなどの音色を割り当てることができます。MIDI規格には、チャンネルと音色の対応が規定されていませんが、GM音源では、標準的な音色が定められています。たとえば、チャンネル0はピアノ、10は打楽器です。
       
    4. サウンドバンク、インスツルメント
       音色は、通常、サウンドバンクと呼ばれる、各楽器の音をサンプリングしたファイルを利用して合成されます。合成手法をインスツルメントと呼んでいます。

    5. ノート番号、ベロシティ
       ノート番号は、ピアノ鍵盤の中央のドを60とし、半音単位で番号を付けます。#は半音高い音を意味しピアノの黒鍵に対応します。ノート番号の最大値は127です。

      ド# レ# ファ ソ# ラ#
      60 61 62 63 64 65 66 67 68 89 70 71

       MIDIでは音の強さを「ベロシティ」で表現します。ベロシティは「速さ」の意味で、演奏するときの操作の速さを表現します。「ベロシティ」が強いほど、大きな音が出ます。

    6. MIDIメッセージ
       midiメッセージには、ノートオンとノートオフメッセージがあります。ノートオンメッセージは
       midiチャンネル、ノート番号、ベロシティ
      を指定します。これを受けた音源は指定の音色、高さ、強さ、で音を出し始めます。複数の音を続けて出すと和音の演奏ができます。
       音を終了するには、ノートオフメッセージを利用します。ノートオフメッセージは
       midiチャンネル、ノート番号、ベロシティ
      を指定します。ノートオフメッセージは、ベロシティ0のノートオンメッセージで代用することがあります。

  3. 利用法

    1. MIDIデバイスを開く
       MIDIで演奏するには、以下のように、MIDIデバイスを開く必要があります。MIDIデバイスは Synthesizer クラスとして提供されます。

       Synthesizer synthesizer=null;
       synthesizer = MidiSystem.getSynthesizer();
       synthesizer.open();

       この処理は、try-catch によるエラー処理を必要とします。

    2. サウンドバンク、インスツルメントを取得
      synthesizerから、サウンドバンクとインスルツメンツを取得し、loadInstrument() で0番のインスツルメンツを取り込みます。ただし、getDefaultSoundbank() で soundbank を取得できない場合があります。このばあい、loadInstrument(instruments[0]); を省略できます。
       Soundbank soundbank = synthesizer.getDefaultSoundbank();
       System.out.println("getbank:"+soundbank);
       Instrument[] instruments =soundbank.getInstruments();
       synthesizer.loadInstrument(instruments[0]);
      さらに、synthesizer から、最大16のMidiChannelクラスを取得します。

       MidiChannel[] channel=new MidiChannel[16];
       channel = synthesizer.getChannels();

    3. MIDIメッセージを送る
       特定のチャンネルに対し、ノート番号とベロシティを指定して、ノートオンメッセージを送ると音が出ます。

       channel[0].noteOn( 60, 80);

      channel[0]はGM音源ではピアノに相当します。この例では、ピアノを60(中央のド)を80の強さで演奏します。

  4. プログラム
    1. ボタンの作成
       init() で play ボタンを作成します。playボタンを押すと、play() が実行されます。

    2. 準備
       strat() で、MIDI 演奏の準備をします。

    3. play:簡単な演奏
       channel[0]とchannel[7]に対し、0.5秒間隔で以下の音符を演奏します。

       int note1[]={60,64,67,64,60};
       int note2[]={64,60,60,64,64};

       note1[]が、channel[0] の「楽譜」になります。Thread.sleep(500); で、500ミリ秒休止してから音を止めます。

    4. プログラム
      import javax.sound.midi.*;
      
      import java.applet.Applet;
      import java.awt.*;
      import java.awt.event.ActionEvent;
      
      
      public class midi extends Applet{
          
          MidiChannel[] channel=new MidiChannel[16];
          Synthesizer synthesizer=null;
          private Button playB=new Button();
          
          public void init(){
              playB.setLabel("play");
              playB.setBounds(new Rectangle(60, 80, 80, 30));
              this.setLayout(null);
              this.add(playB, null);
      
              playB.addActionListener(new java.awt.event.ActionListener() {
              public void actionPerformed(ActionEvent e) {
              play_actionPerformed(e); } });  
          }
          
          public void start() {
      
              try {
                  synthesizer = MidiSystem.getSynthesizer();
                  synthesizer.open();
                  System.out.println("open:" + synthesizer);
      
                  Soundbank soundbank = synthesizer.getDefaultSoundbank();
                  System.out.println("getbank:" + soundbank);
      
                  if (soundbank != null) {
                      Instrument[] instruments = soundbank.getInstruments();
                      System.out.println(
                          "get instrument" + synthesizer.getAvailableInstruments());
                      synthesizer.loadInstrument(instruments[0]);
                  }
      
                  //SynsesizerからChannelを得る。
                  channel = synthesizer.getChannels();
      
              } catch (Exception e) {
                  if (synthesizer == null)
                      System.out.println("fail to open midi");
              }
      
          }
          
          
          public void playMidi(){
              int note1[]={60,64,67,64,60};
              int note2[]={64,60,60,64,64};
                      
              for(int i=0;i<5;i++){
      
                  channel[0].noteOn( note1[i], 127);
                  channel[7].noteOn( note2[i], 127);
                  
                  try{
                     Thread.sleep(500); //0.5秒間休止する
      
                  }catch(Exception e){
                     System.out.println("fail to sleep");
                  }
                  
                  channel[0].noteOff(note1[i], 128); //音を停止
                  channel[7].noteOff(note2[i], 128); 
                  //System.out.println("1:" + );          
              }           
          }
          
          void play_actionPerformed(ActionEvent e){
              playMidi();
          }
          
      }

    5. 実行結果
       playボタンを押すと演奏します。演奏しない場合、音量の設定やmidiの設定をチェックしてください。