共用方式為


尖峰計量

為了支持顯示尖峰計量的 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 介面,並開啟對話框以顯示裝置的尖峰計量。 如需 WinMainCoCreateInstance 的詳細資訊,請參閱 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 函式中,將呼叫中第一個參數的值從 eRender 變更為 eCapture。IMMDeviceEnumerator::GetDefaultAudioEndpoint

下列程式代碼範例是資源腳本,可定義上述程式代碼範例中顯示的控件:

// 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

音量控件