You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 15:44:56