概要

オーディオの低レベルAPIを使用してWaveOutデバイスの一覧およびサポートフォーマットおよびサポート機能の表示を行います。

使用するWAVEOUTCAPS構造体のszPnameメンバにデバイス名が格納されますが、配列の大きさが32文字ですので、デバイス名が途中で途切れます。

テスト環境

コンパイラ

Visual C++ 2008 Standard 32/64bit
Visual C++ 2013 Express 32/64bit

プロジェクトの作成

Win32プロジェクト Windowsアプリケーション

実行環境

Windows 8.1 Enterprise 64bit
Windows 7 EnterPrise Service Pack 1 64bit
Windows Vista Ultimate Service Pack 2 32bit
Windows XP Professional Service Pack 3 32bit

プログラムソースの概要

_tWinMain

Windowsから最初に_tWinMain関数が呼び出されます。
DialogBox APIよりメインダイアログボックスを作成します。

DlgProc1ダイアログボックスのプロシージャー

メインダイアログボックスのプロシージャーです。

case WM_INITDIALOG:

ダイアログボックスの初期化時に呼び出されます。
WaveOutGetNumDevs APIによりWaveOutデバイスの個数を取得します。
各デバイスに対してwaveOutGetDevCaps APIを実行しデバイス名を取得し、コンボボックスにCB_INSERTSTRINGメッセージを送信しデバイス名をコンボボックスに登録します。
WaveOutGetNumDevs APIにより最初のWaveOutデバイスの諸元を取得します。
WAVEOUTCAPS構造体のデバイス名とバージョン情報を_stprintf_関数で文字列に変換します。
SetWaveFormStr関数によりサポートしているサンプルレート・ビット数を文字列に変換します。
SetWaveSupportStr関数によりサポートしている機能を文字列に変換します。
SetWindowText APIによりエディットボックスに文字列を設定します。

case WM_COMMAND:

ダイアログボックスの子ウィンドウ(ダイアログボックスに張り付けられているエディットボックスやプッシュボタン等)から発生したメッセージが届きます。
ダイアログボックスプロシージャーの第3引数であるWPARAMの下位16bitがコントロールのID番号、その上位16bitには通知内容が格納されています。
LOWORDマクロによりWPARAMの下位16bitを取り出し、switchステートメントによりコントロールごとに処理を振り分けます
case IDC_COMBOBOX:
コンボボックスからのメッセージが届きます。メッセージのうちアイテムが選択されたときに発生するCBN_SELCHANGEの場合は以下の処理を行います。
コンボボックスにCB_GETCURSELメッセージを送信し選択されているアイテムの番号を取得します。
WaveOutGetNumDevs APIにより選択アイテムのWaveOutデバイスの諸元を取得します。
WAVEOUTCAPS構造体のデバイス名とバージョン情報を_stprintf_関数で文字列に変換します。
SetWaveFormStr関数によりサポートしているサンプルレート・ビット数を文字列に変換します。
SetWaveSupportStr関数によりサポートしている機能を文字列に変換します。
SetWindowText APIによりエディットボックスに文字列を設定します。
case IDCANCEL:
ESCキーまたは閉じるボタンをクリックするとこのメッセージが発生します。
OUT_WAVE::close関数によりWaveOutデバイスを閉じます。
EndDialog APIを呼び出し、ダイアログボックスを終了させます。 このAPIの第2引数は、ダイアログボックスが終了し、DialogBox APIが返す値となります。

SetWaveFormStr

WAVEOUTCAPS構造体のdwFormatsメンバーを引数として渡すとサポートしているサンプルレートとチャンネル数・ビット数を文字列化します。
サンプルレートとチャンネル数・ビット数の一覧はWAVE_FORM_TYPE構造体の配列に保存していますので、引数とWAVE_FORM_TYPE構造体のflagsをAND演算してビットが立っていればサポートされていることになりますので文字列化します。全ての配列要素についてサポートの有無を確認します。

SetWaveSupportStr

WAVEOUTCAPS構造体のdwFormatsメンバーを引数として渡すと機能が有効であるか無効であるかをを文字列化します。
サポートしている機能の一覧はWAVE_SUPPORT_TBL構造体の配列に保存していますので、引数とWAVE_SUPPORT_TBL構造体のflagsメンバーをAND演算してビットが立っていればサポートされていることになります。全ての配列要素についてサポートの有無を確認します。

プログラムソース

mmedev.cpp

//	WaveOutデバイスの一覧およびサポートフォーマットを表示
//	Visual C++ 2008/2013

#include <windows.h>
#include <shlobj.h>
#include <commctrl.h>
#include <stdio.h>
#include <tchar.h>
#include <mmsystem.h>
#include "resource.h"

#pragma comment(lib,"winmm.lib")

struct WAVE_FORM_TYPE{
	int flags;
	int samples;
	int channels;
	int bits;
};

static WAVE_FORM_TYPE wave_form_type_tbl[]={
	{ WAVE_FORMAT_1M08 , 11025, 1,  8 }, // 0x00001 
	{ WAVE_FORMAT_1S08 , 11025, 2,  8 }, // 0x00002 
	{ WAVE_FORMAT_1M16 , 11025, 1, 16 }, // 0x00004 
	{ WAVE_FORMAT_1S16 , 11025, 2, 16 }, // 0x00008 
	{ WAVE_FORMAT_2M08 , 22050, 1,  8 }, // 0x00010 
	{ WAVE_FORMAT_2S08 , 22050, 2,  8 }, // 0x00020 
	{ WAVE_FORMAT_2M16 , 22050, 1, 16 }, // 0x00040 
	{ WAVE_FORMAT_2S16 , 22050, 2, 16 }, // 0x00080 
	{ WAVE_FORMAT_4M08 , 44100, 1,  8 }, // 0x00100 
	{ WAVE_FORMAT_4S08 , 44100, 2,  8 }, // 0x00200 
	{ WAVE_FORMAT_4M16 , 44100, 1, 16 }, // 0x00400 
	{ WAVE_FORMAT_4S16 , 44100, 2, 16 }, // 0x00800 
	{ WAVE_FORMAT_44M08, 44100, 1,  8 }, // 0x00100 
	{ WAVE_FORMAT_44S08, 44100, 2,  8 }, // 0x00200 
	{ WAVE_FORMAT_44M16, 44100, 1, 16 }, // 0x00400 
	{ WAVE_FORMAT_44S16, 44100, 2, 16 }, // 0x00800 
	{ WAVE_FORMAT_48M08, 48000, 1,  8 }, // 0x01000 
	{ WAVE_FORMAT_48S08, 48000, 2,  8 }, // 0x02000 
	{ WAVE_FORMAT_48M16, 48000, 1, 16 }, // 0x04000 
	{ WAVE_FORMAT_48S16, 48000, 2, 16 }, // 0x08000 
	{ WAVE_FORMAT_96M08, 96000, 1,  8 }, // 0x10000 
	{ WAVE_FORMAT_96S08, 96000, 2,  8 }, // 0x20000 
	{ WAVE_FORMAT_96M16, 96000, 1, 16 }, // 0x40000 
	{ WAVE_FORMAT_96S16, 96000, 2, 16 }, // 0x80000 
{ 0, 0, 0, 0 } };

struct WAVE_SUPPORT_TBL{
	unsigned flags;
	TCHAR* str;
};

WAVE_SUPPORT_TBL wave_support_tbl[]={
{ WAVECAPS_LRVOLUME, _TEXT("WAVECAPS_LRVOLUME") },//左右独立した音量コントロール
{ WAVECAPS_PITCH, _TEXT("WAVECAPS_PITCH") },//ピッチ・コントロール
{ WAVECAPS_PLAYBACKRATE, _TEXT("WAVECAPS_PLAYBACKRATE") },//プレーバック・レート・コントロール
{ WAVECAPS_SYNC, _TEXT("WAVECAPS_SYNC") },//このドライバは同期型で、再生中はブロックする
{ WAVECAPS_VOLUME, _TEXT("WAVECAPS_VOLUME") },//音量コントロール
{ WAVECAPS_SAMPLEACCURATE, _TEXT("WAVECAPS_SAMPLEACCURATE") },//再生位置表示機能
{ 0, 0 }};

//	サポートしているWaveフォーマットを文字列化する
void SetWaveFormStr(TCHAR* buf, int sz, unsigned flags);

//	WaveOutデバイスがサポートしている機能を文字列化する
void SetWaveSupportStr(TCHAR* buf, int sz, unsigned support);

//	ダイアログボックスプロシージャー
LRESULT CALLBACK DlgProc1(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);

int WINAPI _tWinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, TCHAR* lpsCmdLine, int nCmdShow){
	DialogBox(hCurInst, TEXT("DLG1"), 0, (DLGPROC)DlgProc1);
	return (int)0;
}

//	ダイアログボックスプロシージャー

LRESULT CALLBACK DlgProc1(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam){
	int num;
	static int max = 0;
	TCHAR buf[2048];
	WAVEOUTCAPS dev;
	switch (msg) {
	case WM_INITDIALOG:{
		int n;
		max=waveOutGetNumDevs();
		for (n = 0; n < max; n++){
			waveOutGetDevCaps(n,&dev,sizeof(dev));
			SendMessage(GetDlgItem(hDlg, IDC_COMBOBOX), CB_INSERTSTRING, n, (LPARAM)dev.szPname);	//コンボボックスにアイテムの設定
		}
		SendMessage(GetDlgItem(hDlg, IDC_COMBOBOX), CB_SETCURSEL, 0, (LPARAM)0);	//	初期時に選択されるアイテムを選択
		num = 0;
		waveOutGetDevCaps(num, &dev, sizeof(dev));
		buf[0] = _T('¥0');
		_stprintf_s(buf, sizeof(buf) / sizeof(TCHAR), _TEXT("%s¥r¥nVersion %d.%d¥r¥n"), dev.szPname, dev.vDriverVersion / 256, dev.vDriverVersion & 0xff);
		SetWaveFormStr(buf, sizeof(buf) / sizeof(TCHAR), dev.dwFormats);
		SetWaveSupportStr(buf, sizeof(buf) / sizeof(TCHAR), dev.dwFormats);
		SetWindowText(GetDlgItem(hDlg, IDC_EDIT), buf);
		return TRUE;
	}
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDC_COMBOBOX:
			if (HIWORD(wParam) == CBN_SELCHANGE){	//	コンボボックスのアイテムが選択されたときに呼び出される
				num = (int)SendMessage(GetDlgItem(hDlg, IDC_COMBOBOX), CB_GETCURSEL, 0, 0);	//	カーソル位置のアイテムを取得
				waveOutGetDevCaps(num, &dev, sizeof(dev));
				buf[0] = _T('¥0');
				_stprintf_s(buf, sizeof(buf) / sizeof(TCHAR), _TEXT("%s¥r¥nVersion %d.%d¥r¥n"), dev.szPname,dev.vDriverVersion / 256, dev.vDriverVersion & 0xff);
				SetWaveFormStr(buf, sizeof(buf) / sizeof(TCHAR), dev.dwFormats);
				SetWaveSupportStr(buf, sizeof(buf) / sizeof(TCHAR), dev.dwFormats);
				SetWindowText(GetDlgItem(hDlg, IDC_EDIT), buf);
			}
			break;
		case IDCANCEL:
			EndDialog(hDlg, FALSE);
			return FALSE;
		default:
			return FALSE;
		}
	default:
		return FALSE;
	}
	return TRUE;
}

//	サポートしているWaveフォーマットを文字列化する

void SetWaveFormStr(TCHAR* buf, int sz, unsigned flags){
	TCHAR temp[32];
	WAVE_FORM_TYPE* tbl = wave_form_type_tbl;

	int n = 0;
	while (tbl[n].flags){
		if (tbl[n].flags & flags){
			_stprintf_s(temp, sizeof(temp) / sizeof(TCHAR), TEXT("%dHz %dチャネル %dビット¥r¥n"), tbl[n].samples, tbl[n].channels, tbl[n].bits);
			_tcscat_s(buf, sz, temp);
		}
		++n;
	}
}

//	WaveOutデバイスがサポートしている機能を文字列化する

void SetWaveSupportStr(TCHAR* buf, int sz, unsigned support){
	WAVE_SUPPORT_TBL* tbl = wave_support_tbl;
	TCHAR temp[64];
	int n = 0;
	while (tbl[n].flags){
		_stprintf_s(temp, sizeof(temp) / sizeof(TCHAR), _TEXT("%s %s¥r¥n"), tbl[n].str, (tbl[n].flags & support) ? _TEXT("サポート") : _TEXT("未サポート"));
		_tcscat_s(buf, sz, temp);
		++n;
	}
}

resource.h

#define IDC_COMBOBOX 100
#define IDC_LABEL	110
#define IDC_EDIT	110

resource.rc

#include <windows.h>
#include "resource.h"

DLG1 DIALOG DISCARDABLE 0, 0, 194, 321
EXSTYLE WS_EX_DLGMODALFRAME
STYLE WS_POPUP  | WS_CAPTION | WS_SYSMENU |  DS_SETFONT
CAPTION "WaveOutデバイス一覧"
FONT 9, "MS 明朝"
{
 CONTROL "", IDC_COMBOBOX, "COMBOBOX", WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST, 7, 7, 180, 100
 EDITTEXT IDC_EDIT, 7, 28, 180, 256, ES_AUTOHSCROLL | ES_MULTILINE

 CONTROL "終了", IDCANCEL, "BUTTON", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 67, 300, 54, 14
}

ソースファイルと実行ファイルのダウンロード

ダウンロード mmedev.zip(42.4kByte)
ZIPファイルに含まれるファイル
mmedev.cpp
resource.h
resource.rc
mmedev.exe