Windows API中ISimpleAudioVolume::GetMasterVolume返回0.00问题求助
问题分析与修复
你的代码中调用ISimpleAudioVolume::GetMasterVolume始终返回0.00的核心原因是参数传递错误,同时还有几处资源管理和错误检查的问题,以下是具体分析和修复方案:
1. 核心错误:GetMasterVolume的参数未正确初始化
你在代码中写了:
float* pfLevel = NULL; pSimpleAudioVolume->GetMasterVolume(pfLevel);
GetMasterVolume需要传入一个有效的float类型指针,用来存储读取到的音量值。但你传入的是NULL指针,函数无法将音量值写入有效的内存地址,导致你读取到的是无效的内存内容(表现为0.00)。
修复方式:声明一个float变量,传入它的地址:
float fLevel = 0.0f; pSimpleAudioVolume->GetMasterVolume(&fLevel);
2. 未检查QueryInterface的返回结果
在获取IAudioSessionControl2和ISimpleAudioVolume接口时,你没有检查QueryInterface的HRESULT返回值,如果接口获取失败,后续调用会导致未定义行为。
修复方式:每次调用QueryInterface后都检查HRESULT:
hr = pSessionControl->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&pSessionControl2); EXIT_ON_ERROR(hr, __LINE__); hr = pSessionControl2->QueryInterface(__uuidof(ISimpleAudioVolume), (void**)&pSimpleAudioVolume); EXIT_ON_ERROR(hr, __LINE__);
3. 资源未正确释放
循环中获取的pSessionControl2、pSimpleAudioVolume没有调用Release(),会造成COM对象内存泄漏。
修复方式:在循环末尾释放这些资源:
SAFE_RELEASE(pSimpleAudioVolume); SAFE_RELEASE(pSessionControl2); SAFE_RELEASE(pSessionControl);
4. 变量初始化不规范
比如float volume = NULL;、float pflVolumeMindB = NULL;等,NULL是指针常量,给float变量赋值应该使用浮点型常量(如0.0f),虽然部分编译器兼容,但这是不规范的写法,可能引发潜在问题。
修正后的完整代码
void PrintEndpointNames() { HRESULT hr = S_OK; IMMDeviceEnumerator* pEnumerator = NULL; IMMDeviceCollection* pCollection = NULL; IMMDevice* pEndpoint = NULL; IPropertyStore* pProps = NULL; IAudioSessionManager2* pAudioSessionManager = NULL; IAudioSessionEnumerator* pSessionEnumerator = NULL; IAudioEndpointVolume* ppInterface = NULL; float volume = 0.0f; // 修正初始化 PROPVARIANT id; PROPVARIANT varName; float pflVolumeMindB = 0.0f; // 修正初始化 float pflVolumeMaxdB = 0.0f; // 修正初始化 float pflVolumeIncrementdB = 0.0f; // 修正初始化 hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator); EXIT_ON_ERROR(hr, __LINE__); // Get the default audio endpoint hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pEndpoint); EXIT_ON_ERROR(hr, __LINE__); hr = pEndpoint->OpenPropertyStore( STGM_READ, &pProps); EXIT_ON_ERROR(hr, __LINE__); PropVariantInit(&varName); // Get the endpoint's friendly-name property. hr = pProps->GetValue( PKEY_Device_FriendlyName, &varName); EXIT_ON_ERROR(hr, __LINE__); // GetValue succeeds and returns S_OK if PKEY_Device_FriendlyName is not found. // In this case vartName.vt is set to VT_EMPTY. if (varName.vt != VT_EMPTY) { // Print endpoint friendly name and endpoint ID. printf("Endpoint : \"%S\"\n", varName.pwszVal); } //Get audio endpoint volume hr = pEndpoint->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&ppInterface); EXIT_ON_ERROR(hr, __LINE__); ppInterface->GetVolumeRange(&pflVolumeMindB, &pflVolumeMaxdB, &pflVolumeIncrementdB); std::cout << " Volume range : min:" << pflVolumeMindB << "dB, max:" << pflVolumeMaxdB << "dB increment:" << pflVolumeIncrementdB << "dB" << std::endl; ppInterface->GetMasterVolumeLevel(&volume); printf(" CurrentVolume %f\n", volume); // Get the IAudioSessionManager2 interface hr = pEndpoint->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (void**)&pAudioSessionManager); EXIT_ON_ERROR(hr, __LINE__); // Enumerate audio sessions hr = pAudioSessionManager->GetSessionEnumerator(&pSessionEnumerator); EXIT_ON_ERROR(hr, __LINE__); int sessionCount; hr = pSessionEnumerator->GetCount(&sessionCount); EXIT_ON_ERROR(hr, __LINE__); // 新增错误检查 std::cout << " " << sessionCount << " sessions :" << std::endl; // Looping over the sessions for (int i = 0; i < sessionCount; i++) { IAudioSessionControl* pSessionControl = NULL; hr = pSessionEnumerator->GetSession(i, &pSessionControl); EXIT_ON_ERROR(hr, __LINE__); IAudioSessionControl2* pSessionControl2 = NULL; hr = pSessionControl->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&pSessionControl2); EXIT_ON_ERROR(hr, __LINE__); float fLevel = 0.0f; // 替换原NULL指针 ISimpleAudioVolume* pSimpleAudioVolume = NULL; hr = pSessionControl2->QueryInterface(__uuidof(ISimpleAudioVolume), (void**)&pSimpleAudioVolume); EXIT_ON_ERROR(hr, __LINE__); hr = pSimpleAudioVolume->GetMasterVolume(&fLevel); // 传入有效地址 EXIT_ON_ERROR(hr, __LINE__); // 新增错误检查 printf(" ----[%d] Vol:%f\n", i+1, fLevel); // 释放资源 SAFE_RELEASE(pSimpleAudioVolume); SAFE_RELEASE(pSessionControl2); SAFE_RELEASE(pSessionControl); } PropVariantClear(&varName); SAFE_RELEASE(ppInterface); // 新增释放 SAFE_RELEASE(pAudioSessionManager); // 新增释放 SAFE_RELEASE(pSessionEnumerator); // 新增释放 SAFE_RELEASE(pProps); SAFE_RELEASE(pEndpoint); SAFE_RELEASE(pEnumerator); SAFE_RELEASE(pCollection); return; Exit: printf("Error!\n"); SAFE_RELEASE(ppInterface); SAFE_RELEASE(pAudioSessionManager); SAFE_RELEASE(pSessionEnumerator); SAFE_RELEASE(pEnumerator); SAFE_RELEASE(pCollection); SAFE_RELEASE(pEndpoint); SAFE_RELEASE(pProps); } int main() { CoInitialize(NULL); PrintEndpointNames(); CoUninitialize(); // 新增COM库卸载 return 0; }
另外,注意在main函数末尾调用CoUninitialize(),完成COM库的清理工作。
内容的提问来源于stack exchange,提问作者l_KarmaKat
相关产品推荐
相关产品推荐

