MCIデバイスのMIDI再生の例

MCI(Media Control Interface:メディアコントロールインターフェイス)を用いてのMIDI音楽再生の例です。MCIはCDやWAVE等の再生にも利用できる非常に便利なインターフェースです。

cygwin/gcc でのコンパイル時にはWindows APIとMCIが利用可能になるよう、"windows.h"と"mmsystem.h"のインクルードと、libwinmm.aへのリンクが必要になります。

 Gami[84]% gcc -o list_59 list_59.c -lwinmm 

例題では、MIDIの再生部を子プロセスの中とし、親プロセスが終了してもMIDIの再生が続行されるようになっています。子プロセス中では、MIDIの再生時間を読取り、再生が終了すれば自動的に子プロセスを終了するようになっています。

(list_59.c)
//-----------------------------------------------------------------
// list_59.c:
//     MCIデバイスのMIDI再生の例
//                  Last Update: <2004/11/19 02:38:07 murakami>
//-----------------------------------------------------------------
#include <stdio.h>
#include <windows.h>
#include <mmsystem.h>

//-----------------------------------------------------------------
int InitMciDev(char* mid_file);
void TermMciDev();
int PlayMciDev();
int MIDILength();
// MIDI 再生用子プロセス
void MidiPlay(char* mid_file);
//-----------------------------------------------------------------

int main()
{
    int pid;
    char mid_file[] = "samp.mid";
    // プロセスの実行
    if((pid=fork()) == -1){
        perror("fork");
        return -1;
    } else if(pid == 0){
        // 子プロセス
        MidiPlay(mid_file);
    }
    return 0;
}

//-----------------------------------------------------------------
// MIDI再生用子プロセス
//-----------------------------------------------------------------
void MidiPlay(char* mid_file)
{
    int mLen;
    // MIDIの指定
    if(InitMciDev(mid_file)){
        fprintf(stderr,"MCIデバイスオープン失敗\n");
        return ;
    }
    // 演奏時間の取得
    mLen = MIDILength();
    if(mLen <= 0){
        fprintf(stderr,"演奏時間取得失敗\n");
    }
    // 演奏開始
    if(PlayMciDev()){
        fprintf(stderr,"再生にエラーが発生しました\n");
        return ;
    }
    // 演奏時間の間停止。
    printf("**%s:\n",mid_file);
    printf("  演奏時間[%d]秒\n",mLen);
    sleep(mLen);
    printf("**演奏終了\n");
    // 終了
    TermMciDev();
}

//-----------------------------------------------------------------
// MCIデバイスのオープン
//-----------------------------------------------------------------
int InitMciDev(char* mid_file)
{
    char cmd[256];
    memset(cmd,0,sizeof(char)*256);
    sprintf(cmd,"open %s type sequencer alias mid1",mid_file);
    return mciSendString(cmd,NULL,0,0);
}
/*-----------------------------------------------------------------
 * MCIデバイスを閉じる
 *-----------------------------------------------------------------*/
void TermMciDev()
{
    mciSendString("stop mid1",NULL,0,0);
}
//-----------------------------------------------------------------
// MCIデバイスを再生する
//-----------------------------------------------------------------
int PlayMciDev()
{
    return mciSendString("play mid1",NULL,0,0);
}
//-----------------------------------------------------------------
// 演奏時間の取得
//-----------------------------------------------------------------
int MIDILength()
{
    int ret;
    char status[30];
    mciSendString("set mid1 time format milliseconds",NULL,0,0);
    ret = mciSendString("status mid1 length",status,30,0);
    if(ret) return 0;
    return atoi(status)/1000;
}

実行結果
Gami[85]% ./midi_p4.exe
Gami[86]% **samp.mid:
  演奏時間[314]秒
**演奏終了
inserted by FC2 system