ピークメーター
ピーク メーターを表示する Windows アプリケーションをサポートするために、EndpointVolume API には、IAudioMeterInformation インターフェイスが含まれています。 このインターフェイスは、オーディオ エンドポイント デバイスののピーク メーターを表します。 レンダリング デバイスの場合、ピーク メーターから取得された値は、前の測定期間中にデバイスへの出力ストリームで検出された最大サンプル値を表します。 キャプチャ デバイスの場合、ピーク メーターから取得される値は、デバイスからの入力ストリームで検出された最大サンプル値を表します。
IAudioMeterInformation インターフェイスのメソッドから取得されるピークメーター値は、正規化された範囲の 0.0 から 1.0 までの浮動小数点数です。 たとえば、PCM ストリームに 16 ビット サンプルが含まれており、特定の測定期間中のピーク サンプル値が —8914 の場合、ピーク メーターによって記録される絶対値は 8914 で、IAudioMeterInformation インターフェイスによって報告される正規化されたピーク値は 8914/32768 = 0.272 になります。
オーディオ エンドポイント デバイスがハードウェアにピーク メーターを実装している場合、IAudioMeterInformation インターフェイスはハードウェア ピーク メーターを使用します。 それ以外の場合、インターフェイスはソフトウェアでピーク メーターを実装します。
デバイスにハードウェア ピーク メーターがある場合、ピーク メーターは共有モードと排他モードの両方でアクティブになります。 デバイスにハードウェア ピーク メーターがない場合、ピーク メーターは共有モードではアクティブですが、排他モードではアクティブになりません。 排他モードでは、アプリケーションとオーディオ ハードウェアは、ソフトウェアのピークメーター (常にピーク値 0.0 を報告) をバイパスして、オーディオ データを直接交換します。
次の C++ コード例は、既定のレンダリング デバイスのピークメーターを表示する Windows アプリケーションです。
// Peakmeter.cpp -- WinMain and dialog box functions
#include <windows.h>
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#include "resource.h"
static BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
static void DrawPeakMeter(HWND, float);
// Timer ID and period (in milliseconds)
#define ID_TIMER 1
#define TIMER_PERIOD 125
#define EXIT_ON_ERROR(hr) \
if (FAILED(hr)) { goto Exit; }
#define SAFE_RELEASE(punk) \
if ((punk) != NULL) \
{ (punk)->Release(); (punk) = NULL; }
//-----------------------------------------------------------
// WinMain -- Opens a dialog box that contains a peak meter.
// The peak meter displays the peak sample value that plays
// through the default rendering device.
//-----------------------------------------------------------
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HRESULT hr;
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDevice *pDevice = NULL;
IAudioMeterInformation *pMeterInfo = NULL;
if (hPrevInstance)
{
return 0;
}
CoInitialize(NULL);
// Get enumerator for audio endpoint devices.
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
NULL, CLSCTX_INPROC_SERVER,
__uuidof(IMMDeviceEnumerator),
(void**)&pEnumerator);
EXIT_ON_ERROR(hr)
// Get peak meter for default audio-rendering device.
hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
EXIT_ON_ERROR(hr)
hr = pDevice->Activate(__uuidof(IAudioMeterInformation),
CLSCTX_ALL, NULL, (void**)&pMeterInfo);
EXIT_ON_ERROR(hr)
DialogBoxParam(hInstance, L"PEAKMETER", NULL, (DLGPROC)DlgProc, (LPARAM)pMeterInfo);
Exit:
if (FAILED(hr))
{
MessageBox(NULL, TEXT("This program requires Windows Vista."),
TEXT("Error termination"), MB_OK);
}
SAFE_RELEASE(pEnumerator)
SAFE_RELEASE(pDevice)
SAFE_RELEASE(pMeterInfo)
CoUninitialize();
return 0;
}
//-----------------------------------------------------------
// DlgProc -- Dialog box procedure
//-----------------------------------------------------------
BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
static IAudioMeterInformation *pMeterInfo = NULL;
static HWND hPeakMeter = NULL;
static float peak = 0;
HRESULT hr;
switch (message)
{
case WM_INITDIALOG:
pMeterInfo = (IAudioMeterInformation*)lParam;
SetTimer(hDlg, ID_TIMER, TIMER_PERIOD, NULL);
hPeakMeter = GetDlgItem(hDlg, IDC_PEAK_METER);
return TRUE;
case WM_COMMAND:
switch ((int)LOWORD(wParam))
{
case IDCANCEL:
KillTimer(hDlg, ID_TIMER);
EndDialog(hDlg, TRUE);
return TRUE;
}
break;
case WM_TIMER:
switch ((int)wParam)
{
case ID_TIMER:
// Update the peak meter in the dialog box.
hr = pMeterInfo->GetPeakValue(&peak);
if (FAILED(hr))
{
MessageBox(hDlg, TEXT("The program will exit."),
TEXT("Fatal error"), MB_OK);
KillTimer(hDlg, ID_TIMER);
EndDialog(hDlg, TRUE);
return TRUE;
}
DrawPeakMeter(hPeakMeter, peak);
return TRUE;
}
break;
case WM_PAINT:
// Redraw the peak meter in the dialog box.
ValidateRect(hPeakMeter, NULL);
DrawPeakMeter(hPeakMeter, peak);
break;
}
return FALSE;
}
//-----------------------------------------------------------
// DrawPeakMeter -- Draws the peak meter in the dialog box.
//-----------------------------------------------------------
void DrawPeakMeter(HWND hPeakMeter, float peak)
{
HDC hdc;
RECT rect;
GetClientRect(hPeakMeter, &rect);
hdc = GetDC(hPeakMeter);
FillRect(hdc, &rect, (HBRUSH)(COLOR_3DSHADOW+1));
rect.left++;
rect.top++;
rect.right = rect.left +
max(0, (LONG)(peak*(rect.right-rect.left)-1.5));
rect.bottom--;
FillRect(hdc, &rect, (HBRUSH)(COLOR_3DHIGHLIGHT+1));
ReleaseDC(hPeakMeter, hdc);
}
前のコード例では、WinMain 関数は、CoCreateInstance 関数を呼び出して、IMMDeviceEnumerator インターフェイスのインスタンスを作成し、IMMDeviceEnumerator::GetDefaultAudioEndpoint メソッドを呼び出して、既定のレンダリング デバイスの IMMDevice インターフェイスを取得します。 WinMain は、IMMDevice::Activate メソッドを呼び出してデバイスの IAudioMeterInformation インターフェイスを取得し、デバイスのピーク メーターを表示するダイアログ ボックスを開きます。 WinMain と CoCreateInstance の詳細については、Windows SDK のドキュメントを参照してください。 IMMDeviceEnumerator と IMMDevice のの詳細については、「オーディオ デバイスの列挙」を参照してください。
前のコード例では、DlgProc 関数はダイアログ ボックスにピーク メーターを表示します。 WM_INITDIALOG メッセージの処理中に、DlgProc は SetTimer 関数を呼び出して、一定の時間間隔でWM_TIMERメッセージを生成するタイマーを設定します。 DlgProc は、WM_TIMER メッセージを受信すると、IAudioMeterInformation::GetPeakValue を呼び出して、ストリームの最新のピークメーター読み取り値を取得します。 次に、DlgProc は DrawPeakMeter 関数を呼び出して、ダイアログ ボックスで更新されたピーク メーターを描画します。 SetTimer とWM_INITDIALOGメッセージとWM_TIMERメッセージの詳細については、Windows SDK のドキュメントを参照してください。
前のコード例を簡単に変更して、既定のキャプチャ デバイスのピーク メーターを表示できます。 WinMain 関数で、IMMDeviceEnumerator::GetDefaultAudioEndpoint の呼び出しの最初のパラメーターの値を eRender から eCapture に変更します。
次のコード例は、前のコード例に表示されるコントロールを定義するリソース スクリプトです。
// Peakmeter.rc -- Resource script
#include "resource.h"
#include "windows.h"
//
// Dialog
//
PEAKMETER DIALOGEX 0, 0, 150, 34
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_SETFONT
CAPTION "Peak Meter"
FONT 8, "Arial Rounded MT Bold", 400, 0, 0x0
BEGIN
CTEXT "",IDC_PEAK_METER,34,14,82,5
LTEXT "Min",IDC_STATIC_MINVOL,10,12,20,12
RTEXT "Max",IDC_STATIC_MAXVOL,120,12,20,12
END
次のコード例は、前のコード例に表示されるコントロール識別子を定義するリソース ヘッダー ファイルです。
// Resource.h -- Control identifiers
#define IDC_STATIC_MINVOL 1001
#define IDC_STATIC_MAXVOL 1002
#define IDC_PEAK_METER 1003
関連トピック