Piekmeters
Ter ondersteuning van Windows-toepassingen die piekmeters weergeven, bevat de EndpointVolume-API een interface voor IAudioMeterInformation. Deze interface vertegenwoordigt een piekmeter op een audio-eindpuntapparaat. Voor een renderingapparaat vertegenwoordigt de waarde die is opgehaald uit de piekmeter de maximale voorbeeldwaarde in de uitvoerstroom naar het apparaat tijdens de voorgaande meterperiode. Voor een capture-apparaat vertegenwoordigt de waarde die is opgehaald uit de piekmeter de maximale voorbeeldwaarde die is opgetreden in de invoerstroom van het apparaat.
De piekmeterwaarden die zijn verkregen uit de methoden in de interface IAudioMeterInformation zijn drijvendekommanummers in het genormaliseerde bereik van 0,0 tot 1,0. Als een PCM-stroom bijvoorbeeld 16-bits steekproeven bevat en de piekwaarde tijdens een bepaalde meetperiode 8914 is, is de absolute waarde die door de piekmeter is vastgelegd 8914 en is de genormaliseerde piekwaarde gerapporteerd door de interface IAudioMeterInformation interface 8914/32768 = 0,272.
Als het audio-eindpuntapparaat de piekmeter in hardware implementeert, gebruikt de interface IAudioMeterInformation de hardwarepiekmeter. Anders implementeert de interface de piekmeter in software.
Als een apparaat een hardwarepiekmeter heeft, is de piekmeter zowel actief in de gedeelde modus als in de exclusieve modus. Als een apparaat geen hardwarepiekmeter heeft, is de piekmeter actief in de gedeelde modus, maar niet in de exclusieve modus. In de exclusieve modus wisselen de toepassing en de audiohardware rechtstreeks audiogegevens uit, waarbij de softwarepiekmeter wordt overgeslagen (die altijd een piekwaarde van 0,0 rapporteert).
Het volgende C++-codevoorbeeld is een Windows-toepassing die een piekmeter weergeeft voor het standaardrenderingsapparaat:
// 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);
}
In het voorgaande codevoorbeeld, de functie WinMain roept de functie CoCreateInstance aan om een exemplaar van de IMMDeviceEnumerator interface te maken en roept de IMMDeviceEnumerator::GetDefaultAudioEndpoint methode aan om de IMMDevice-interface van het standaardweergaveapparaat te verkrijgen. WinMain roept de IMMDevice::Activate methode aan om de IAudioMeterInformation-interface van het apparaat te verkrijgen en er wordt een dialoogvenster geopend om een piekmeter voor het apparaat weer te geven. Zie de Windows SDK-documentatie voor meer informatie over WinMain en CoCreateInstance. Zie voor meer informatie over IMMDeviceEnumerator en IMMDeviceAudioapparaten inventariseren.
In het voorgaande codevoorbeeld geeft de functie DlgProc de piekmeter weer in het dialoogvenster. Tijdens de verwerking van het WM_INITDIALOG bericht roept DlgProc de functie SetTimer aan om een timer in te stellen waarmee WM_TIMER berichten met regelmatige tijdsintervallen worden gegenereerd. Wanneer DlgProc een WM_TIMER bericht ontvangt, wordt IAudioMeterInformation::GetPeakValue aanroepen om de meest recente piekmeterlezing voor de stream te verkrijgen. DlgProc roept vervolgens de functie DrawPeakMeter aan om de bijgewerkte piekmeter te tekenen in het dialoogvenster. Zie de Windows SDK-documentatie voor meer informatie over SetTimer- en de berichten WM_INITDIALOG en WM_TIMER.
U kunt het voorgaande codevoorbeeld eenvoudig wijzigen om een piekmeter weer te geven voor het standaardopnameapparaat. Wijzig in de functie WinMain de waarde van de eerste parameter in de aanroep naar de IMMDeviceEnumerator::GetDefaultAudioEndpoint van eRender in eCapture.
Het volgende codevoorbeeld is het resourcescript waarmee de besturingselementen worden gedefinieerd die worden weergegeven in het voorgaande codevoorbeeld:
// 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
Het volgende codevoorbeeld is het resourceheaderbestand dat de besturings-id's definieert die worden weergegeven in de voorgaande codevoorbeelden:
// Resource.h -- Control identifiers
#define IDC_STATIC_MINVOL 1001
#define IDC_STATIC_MAXVOL 1002
#define IDC_PEAK_METER 1003
Verwante onderwerpen