MCI で録音


MCI コマンドで音声を入力

前回は、徹底して低レベル API による音声の入力方法を解説しました
しかし、単純に音声を録音し、ファイルとして保存したいという目的であれば
MCI を使って、複雑な入力処理を Windows に任せるということもできます
ただし、この場合は入力された音声データをリアルタイムで操作することはできません

MCI コマンドを用いる場合 MCI_RECORD コマンドで録音を開始します
このコマンドでは、以下のフラグを指定することができます

定数解説
MCI_FROM 所定の構造体の dwFrom メンバに
現在の時間フォーマットで開始位置が格納されている
MCI_RECORD_INSERT 新規に記録した情報を既存のデータに挿入または貼りつける
デバイスによってはサポートされない
MCI_RECORD_OVERWRITE データは既存のデータを上書きする
MCI_TO 所定の構造体の dwTo メンバに
現在の時間フォーマットで終了位置が格納されている
デジタルビデオフラグ
MCI_DGV_RECORD_AUDIO_STREAM MCI_DGV_RECORD_PARMS 構造体の
dwAudioStream メンバにオーディオストリーム番号が含まれる
このフラグを省略した場合、データは最初の物理ストリームに記録される
MCI_DGV_RECORD_HOLD 記録を停止した時に、スクリーンは最初のイメージを保持し
MCI_MONITOR コマンドが発行されるまでイメージの表示を再開しない
MCI_DGV_RECORD_VIDEO_STREAM MCI_DGV_RECORD_PARMS 構造体の
dwVideoStream メンバにビデオストリーム番号が含まれる
このフラグを省略した場合、データは最初の物理ストリームに記録される
MCI_DGV_RECT 矩形を MCI_DGV_RECORD_PARMS 構造体の rc メンバで指定する
VCRフラグ
MCI_VCR_RECORD_AT MCI_VCR_RECORD_PARMS 構造体の dwAt メンバに
コマンド全体を開始する時間、またはデバイスにキューを出している場合は
デバイスが cue コマンドで指定された
開始位置に達する時間が格納されている
MCI_VCR_RECORD_INITIALIZE デバイスをメディアの開始にシークして
ブランクのビデオ及びオーディオの記録を開始し
可能な場合は時刻コードを記録する

このコマンドで使える、汎用的な構造体は MCI_RECORD_PARMS です
この構造体は、次のように定義されています
typedef struct {
    DWORD dwCallback; 
    DWORD dwFrom; 
    DWORD dwTo; 
} MCI_RECORD_PARMS;
dwCallback には、メッセージを受けるウィンドウのハンドルを
dwFrom は記録開始位置、dwTo は記録終了位置を指定します

デジタルビデオデバイスの場合は MCI_DGV_RECORD_PARMS を使えます
typedef struct  {
    DWORD dwCallback; 
    DWORD dwFrom; 
    DWORD dwTo; 
    RECT  rc; 
    DWORD dwAudioStream; 
    DWORD dwVideoStream; 
} MCI_DGV_RECORD_PARMS;
最初の3つのメンバは MCI_RECORD_PARMS 構造体と同じです
rc メンバは、圧縮状態で保存されたピクセルのソースとして使うフレームバッファの領域を
dwAudioStream にはオーディオストリーム、dwVideoStream にはビデオストリームを指定します

VCR デバイスの場合は MCI_VCR_RECORD_PARMS を使えます
これは、MCI_RECORD_PARMS に dwAt メンバが付け加えられただけです
typedef struct tagMCI_VCR_RECORD_PARMS {
    DWORD dwCallback; 
    DWORD dwFrom; 
    DWORD dwTo; 
    DWORD dwAt; 
} MCI_VCR_RECORD_PARMS;
dwAt メンバには、コマンドに影響を与える時間値を指定します
これは MCI_VCR_RECORD_AT フラグを指定した時に使われます

この場では、オーディオの記録しか扱わないため
他のデバイスでの記録方法、及び構造体やフラグについては省略します

再生や録音を中断するには MCI_STOP コマンドを送ります
フラグは、全てのコマンドが使える汎用的なフラグ (MCI_NOTIFY など) を指定できます
構造体は MCI_GENERIC_PARMS 構造体を渡すことができます

最後に、録音した音声データはディスクに保存しなければなりません
そうしなければ、データは記録されずにそのまま削除されてしまいます
保存するには MCI_SAVE コマンドを用いて行います
このコマンドにおいて、フラグは以下のものを組み合わせて指定することができます

定数解説
MCI_SAVE_FILE 所定の構造体の lpfilename メンバに
保存先のファイル名を示す文字列のポインタが格納されている
デジタルビデオフラグ
MCI_DGV_RECT MCI_DGV_SAVE_PARMS 構造体の rc メンバに
有効なフレームバッファ領域の矩形が格納されている
MCI_DGV_SAVE_ABORT 実行中の保存捜査を終了する
他のフラグと組み合わせることはできない
MCI_DGV_SAVE_KEEPRESERVE オリジナルの MCI_RESERVE コマンドで残された
未使用のディスクスペースを割り当て解除しない
ビデオオーバレイフラグ
MCI_OVLY_RECT MCI_OVLY_SAVE_PARMS 構造体の rc メンバに
保存するビデオバッファの領域を示す矩形が格納されている

この MCI コマンドに送信できる汎用的な構造体は
MCI_SAVE_PARMS 構造体で、これは次のように定義されています
typedef struct {
    DWORD  dwCallback; 
    LPCSTR lpfilename; 
} MCI_SAVE_PARMS;
dwCallback には、通知メッセージを受けるウィンドウのハンドルを
lpfilename には保存先のファイル名をあらわす文字列へのポインタを指定します

この他に、デジタルビデオデバイスの場合は MCI_DGV_SAVE_PARMS
ビデオオーバレイデバイスであれば MCI_OVLY_SAVE_PARMS を指定できます
typedef struct  {
    DWORD dwCallback; 
    DWORD lpstrFileName; 
    RECT  rc; 
} MCI_DGV_SAVE_PARMS;

typedef struct {
    DWORD  dwCallback; 
    LPCSTR lpfilename; 
    RECT   rc; 
} MCI_OVLY_SAVE_PARMS;
最初の2つのメンバは MCI_SAVE_PARMS 構造体と同じです
rc メンバには、それぞれ有効な矩形情報を指定します
//resource.h
#define IDB_REC 0x100
#define IDB_REC_END 0x101
//リソーススクリプト
#include "resource.h"

KITTY DIALOG 10 , 10 , 100 , 20
FONT 12 , "MS Serif"
STYLE WS_VISIBLE | WS_POPUPWINDOW
CLASS "KITTY"
CAPTION "Kitty on your lap" {
	PUSHBUTTON "Record" , IDB_REC , 5 , 5 , 40 , 10
	PUSHBUTTON "End" , IDB_REC_END , 50 , 5 , 40 , 10
}
#include <windows.h>
#include "resource.h"
#define TITLE 	TEXT("Kitty on your lap")

PSTR strFile;

LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) {
	static MCI_OPEN_PARMS mop;
	static MCI_SAVE_PARMS msp;

	switch (msg) {
	case WM_DESTROY:
		mciSendCommand(mop.wDeviceID , MCI_CLOSE , 0 , 0);
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		mop.dwCallback = (DWORD)hWnd;
		mop.lpstrDeviceType = (LPCSTR)MCI_DEVTYPE_WAVEFORM_AUDIO;
		mop.lpstrElementName = TEXT("");

		mciSendCommand(0 , MCI_OPEN , 
			MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID |
			MCI_OPEN_ELEMENT , (DWORD)&mop);
		return 0;
	case WM_COMMAND:
		switch(LOWORD(wp)) {
		case IDB_REC:
			mciSendCommand(mop.wDeviceID , MCI_RECORD , 0 , 0);

			EnableWindow(GetDlgItem(hWnd , IDB_REC) , FALSE);
			EnableWindow(GetDlgItem(hWnd , IDB_REC_END) , TRUE);
			break;
		case IDB_REC_END:
			msp.dwCallback = (DWORD)hWnd;
			msp.lpfilename = strFile;

			mciSendCommand(mop.wDeviceID , MCI_STOP , MCI_WAIT , 0);
			mciSendCommand(mop.wDeviceID , MCI_SAVE ,
				MCI_WAIT | MCI_SAVE_FILE , (DWORD)&msp);

			EnableWindow(GetDlgItem(hWnd , IDB_REC) , TRUE);
			EnableWindow(GetDlgItem(hWnd , IDB_REC_END) , FALSE);
			break;
		}
		return 0;
	}
	return DefWindowProc(hWnd , msg , wp , lp);
}


int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow ) {
	HWND hwnd;
	MSG msg;
	WNDCLASS winc;

	if (*lpCmdLine == 0) {
		MessageBox(NULL , TEXT("Input file name.") , NULL , MB_OK);
		return 0;
	}
	strFile = lpCmdLine;

	winc.style		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc	= WndProc;
	winc.cbClsExtra		= 0;
	winc.cbWndExtra		= DLGWINDOWEXTRA;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= CreateSolidBrush(GetSysColor(COLOR_MENU));
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

	if (!RegisterClass(&winc)) return -1;

	hwnd = CreateDialog(hInstance , TEXT("KITTY") , 0 , NULL);

	if (hwnd == NULL) return -1;

	while(GetMessage(&msg , NULL , 0 , 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}
このプログラムは、コマンドライン引数で保存する WAVE 形式ファイル名を指定し
Record ボタンを押して録音を開始し、End ボタンで録音を終了します
録音を終了すれば、自動的に指定したファイル名でディスクに保存されます
続けて Record ボタンを押すと、ファイルの続きからさらに録音されます

End ボタンを押すと、プログラムは録音を終了し MCI_SAVE コマンドを送信してます
これによって、MCI は録音したデータを指定された名前でディスクに保存しています



前のページへ戻る次のページへ