MIDI を演奏

MCI(Media Control Interface)で MIDI を演奏します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プログラムの説明

  1. Win32 API の MCI(Media Control Interface)を使って MIDI を演奏します。
    MIDI FILE は音符(楽譜)を記録したファイルで、演奏するには音源(楽器)が必要です。
    以前は音源から用意していたのですが、最近ではその必要は無いようです。
    WAVE FILE に比べて MIDI FILE のサイズは、ずいぶん小さいでしょう。
    WAVE は音の波形が記録されるのに対して、MIDI は楽譜だからです。
    その代わり複数の楽器を楽譜どおりに演奏するのは相当な苦労です。
    MCI を使えばその辺の所は全て面倒をみてくれます。
  2. 空のプロジェクトから作成した Windows Mode のソースコードです。
    マウスの左ボタンをクリックすると midi の演奏が開始され、右ボタンで停止します。
    C:\\data\\test\\aki.mid が MIDI FILE です。
    適当なファイルを調達してきて下さい。
    /******************************************************/
    /*★ MCI(Media Control Interface)で midi を演奏する ★*/
    /******************************************************/
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;  // for DllImport
    
    public class MyForm : Form
    {
        [DllImport("winmm.dll", CharSet=CharSet.Auto)]
        private static extern int mciSendString(string command,
            System.Text.StringBuilder buffer, int bufferSize, IntPtr hwndCallback);
    
        public MyForm()
        {
            this.Text = "midi Play";
        }
    
        protected override void OnMouseDown(MouseEventArgs e)
        {
            string cmd;
            if (e.Button == MouseButtons.Left)  //マウスの左ボタン
            {
                //ファイルを開く
                cmd = "open C:\\data\\test\\aki.mid type sequencer alias MediaFile";
                //cmd = "open c:\\data\\test\\Chimes.wav type waveaudio alias MediaFile";
                if (mciSendString(cmd, null, 0, IntPtr.Zero) != 0) return;
                //再生する
                cmd = "play MediaFile";
                mciSendString(cmd, null, 0, IntPtr.Zero);
            }
    
            if (e.Button == MouseButtons.Right) //マウスの右ボタン
            {   //再生を停止する
                cmd = "stop MediaFile";
                mciSendString(cmd, null, 0, IntPtr.Zero);
                //閉じる
                cmd = "close MediaFile";
                mciSendString(cmd, null, 0, IntPtr.Zero);
            }
        }
    }
    
    class form01
    {
        public static void Main()
        {
            MyForm mf = new MyForm();
            Application.Run(mf);
        }
    }
    
  3. MCI(Media Control Interface) のコマンドは TEXT 文字で指示します。
    マウスの左ボタンでファイルをオープして演奏を開始します。
    再び演奏を始める時は、右ボタンをクリックしてから左ボタンをクリックして下さい。
        if (e.Button == MouseButtons.Left)  //マウスの左ボタン
        {
            //ファイルを開く
            cmd = "open C:\\data\\test\\aki.mid type sequencer alias MediaFile";
            if (mciSendString(cmd, null, 0, IntPtr.Zero) != 0) return;
            //再生する
            cmd = "play MediaFile";
            mciSendString(cmd, null, 0, IntPtr.Zero);
        }
        
  4. マウスの右ボタンで演奏を停止します。
        if (e.Button == MouseButtons.Right) //マウスの右ボタン
        {   //再生を停止する
            cmd = "stop MediaFile";
            mciSendString(cmd, null, 0, IntPtr.Zero);
            //閉じる
            cmd = "close MediaFile";
            mciSendString(cmd, null, 0, IntPtr.Zero);
        }
        
  5. MCI を使うと MIDI だけで無く WAVE も演奏出来ます。
    Win32 では MP3 も演奏出来たのですが、C# では何故か演奏出来ませんでした。
    Win32 の MCI は MCI で WAVE を演奏する を参照して下さい。
        //cmd = "open C:\\data\\test\\aki.mid type sequencer alias MediaFile";
        cmd = "open c:\\data\\test\\Chimes.wav type waveaudio alias MediaFile";
        

一時停止/再生

  1. 次の機能を網羅して、極力解り易くプログラムしてみました。
  2. ソースコードです。
    /******************************************/
    /*★ MCI で「一時停止/再生継続」をする ★*/
    /******************************************/
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;  // for DllImport
    
    public class MyForm : Form
    {
        [DllImport("winmm.dll", CharSet=CharSet.Auto)]
        private static extern int mciSendString(string command,
            System.Text.StringBuilder buffer, int bufferSize, IntPtr hwndCallback);
        string cmd;
    
        public MyForm()
        {
            this.Text = "midi Play";
            //ファイルを開く
            cmd = "open C:\\data\\test\\aki.mid type sequencer alias MediaFile";
            //cmd = "open c:\\data\\test\\Chimes.wav type waveaudio alias MediaFile";
            if (mciSendString(cmd, null, 0, IntPtr.Zero) != 0)
            {   MessageBox.Show("Open Error");  }
        }
        ~MyForm()
        {    //閉じる
             cmd = "close MediaFile";
             mciSendString(cmd, null, 0, IntPtr.Zero);
        }
    
        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)  //マウスの左ボタン
            {
                //先頭から再生する(そのままでは続きから)
                mciSendString("seek MediaFile to start", null, 0, IntPtr.Zero);
                mciSendString("play MediaFile", null, 0, IntPtr.Zero);
            }
    
            if (e.Button == MouseButtons.Right) //マウスの右ボタン
            {   //再生を停止する
                cmd = "stop MediaFile";
                mciSendString(cmd, null, 0, IntPtr.Zero);
            }
        }
    }
    
    class form01
    {
        public static void Main()
        {
            MyForm mf = new MyForm();
            Application.Run(mf);
        }
    }
    
  3. MyForm() の Constructor で MCI をオープンします。
        public MyForm()
        {     ・・・
            cmd = "open C:\\data\\test\\aki.mid type sequencer alias MediaFile";
            if (mciSendString(cmd, null, 0, IntPtr.Zero) != 0)
            {   MessageBox.Show("Open Error");  }
        }
        
  4. MyForm() の Destructor で MCI をクローズします。
        ~MyForm()
        {    //閉じる
             cmd = "close MediaFile";
             mciSendString(cmd, null, 0, IntPtr.Zero);
        }
        
  5. マウスの左ボタンで再生します。
    "seek MediaFile to start" は巻き戻しで、ファイルの先頭から再生します。
    巻き戻さないと停止した続きから再生されるので、試してみて下さい。
        if (e.Button == MouseButtons.Left)  //マウスの左ボタン
        {
            //先頭から再生する(そのままでは続きから)
            mciSendString("seek MediaFile to start", null, 0, IntPtr.Zero);
            mciSendString("play MediaFile", null, 0, IntPtr.Zero);
        }
        
  6. マウスの右ボタンで停止します。
    停止しても MCI をクローズしていないので、すぐ再生が可能です。
    また左ボタンを続けてクリックしても先頭から再生されます。
        if (e.Button == MouseButtons.Right) //マウスの右ボタン
        {   //再生を停止する
            cmd = "stop MediaFile";
            mciSendString(cmd, null, 0, IntPtr.Zero);
        }
        

メソッド

  1. MCI の機能をメソッドとして定義してみました。
    ソースコードです。
    /**********************************/
    /*★ MCI の Function を定義する ★*/
    /**********************************/
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;  // for DllImport
    using System.Text;                     // for StringBuilder
    
    public class MyForm : Form
    {
        [DllImport("winmm.dll")]
        extern static int mciSendString(string s1, StringBuilder s2, int i1, int i2) ;
        // 返り値 = 0 @正常終了
        // s1     = Command String
        // s2     = Return String
        // i1     = Return String Size
        // i2     = Callback Hwnd
    
        public MyForm()
        {
            this.Text = "MCI Function";
        }
    
        protected override void OnMouseDown(MouseEventArgs e)
        {
            int ret;
    
            if (e.Button == MouseButtons.Left)  //マウスの左ボタンで再生する
            {
                //ret = sound_open(@"C:\DATA\Test\Chimes.wav");
                ret = sound_open(@"C:\DATA\Test\aki.mid");
                Console.WriteLine(ret);
                sound_play();
            }
            if (e.Button == MouseButtons.Right) //マウスの右ボタンで停止する
            {
                sound_stop() ;
                sound_close() ;
            }
        }
    
        // ファイルを open
        private int sound_open(string file_name)
        {   return mciSendString("open \"" + file_name + "\" alias my_sound", null, 0, 0);  }
    
        // ファイルを close
        private void sound_close()
        {   mciSendString("close  my_sound", null, 0, 0);  }
    
        // 再生を開始
        private void sound_play()
        {   mciSendString("play   my_sound", null, 0, 0);  }
    
        // 停止
        private void sound_stop()
        {   mciSendString("stop   my_sound", null, 0, 0);  }
    
        // 一時停止
        private void sound_pause()
        {   mciSendString("pause  my_sound", null, 0, 0);  }
    
        // 一時停止解除
        private void sound_resume()
        {   mciSendString("resume my_sound", null, 0, 0);  }
    
        StringBuilder sb = new StringBuilder(32) ;  // mciSendString() の Return String 格納用
        // 状態を取得
        private string sound_get_mode()
        {   //   返り値: 再生中          = "playing"
            //           停止中/再生終了 = "stopped"
            //           一時停止中      = "paused"
            mciSendString("status my_sound mode", sb, sb.Capacity,0);
            return sb.ToString() ;
        }
    
        // play 中のファイルの位置を ms単位 で返す
        private int sound_get_position()
        {   mciSendString("status my_sound position", sb, sb.Capacity, 0);
            return int.Parse(sb.ToString()) ;
        }
    
        // open 中のファイルの曲長を ms単位 で返す
        private int sound_get_length()
        {   mciSendString("status my_sound length", sb, sb.Capacity, 0);
            return int.Parse(sb.ToString()) ;
        }
    }
    
    class form01
    {
        public static void Main()
        {
            MyForm mf = new MyForm();
            Application.Run(mf);
        }
    }
    
  2. 曲の長さを調べたり、play 中のファイルの位置を知ることも出来ます。
    また位置を指定して再生することも出来ます。
    超初心者のC言語(Windows) から 「Audio(Sound) の基礎/MCI のページ」も参照して下さい。

前田稔(Maeda Minoru)の超初心者のプログラム入門