2017-08-06 110 views
4

我目前正在研究「音量調音臺」來控制我的電腦(Windows 10)上每個程序的音量。如何從0到100獲得系統音量級別的標量?

如何從0到100以標量形式獲得每個節目/音頻會話的音量級別?如您所見,在下面的代碼中,我找到了GetPeakValue函數,但它返回的值如0.0812654或0.021352。

我確定這些值是每個音頻會話的標量從1.0到0.0的音量。但我想要的是音量限制,您可以在Windows音頻混音器中設置音量限制,而不是當前音量。所以如果我將節目音量設置爲50%,我想要一個0.5的值。

在第二個函數(getVolume)中,您會看到我已經獲得了一個0-100標量的主卷,但是那裏的端點設備已經具有標量級別的函數。所以我至少需要同樣的功能或計算才能爲每個音頻會話獲得這樣的標量。

void getSessions() { 
    CoInitialize(NULL); 

    IMMDeviceEnumerator *pDeviceEnumerator = NULL; 
    IMMDevice *pDevice = NULL; 
    IAudioSessionManager2 *pAudioSessionManager2 = NULL; 
    IAudioSessionEnumerator *pAudioSessionEnumerator = NULL; 

    CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&pDeviceEnumerator); 
    pDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice); 

    pDevice->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (void **) &pAudioSessionManager2); 
    pAudioSessionManager2->GetSessionEnumerator(&pAudioSessionEnumerator); 

    int nSessionCount; 
    pAudioSessionEnumerator->GetCount(&nSessionCount); 

    std::cout << "Session Count: " << nSessionCount << std::endl; 

    while (true) { 
     for (int nSessionIndex = 0; nSessionIndex < nSessionCount; nSessionIndex++) { 
      IAudioSessionControl *pSessionControl = NULL; 
      if (FAILED(pAudioSessionEnumerator->GetSession(nSessionIndex, &pSessionControl))) 
       continue; 

      IAudioMeterInformation *pAudioMeterInformation = NULL; 
      pSessionControl->QueryInterface(&pAudioMeterInformation); 

      float fPeak = NULL; 
      pAudioMeterInformation->GetPeakValue(&fPeak); 

      std::cout << "fPeak Value: " << fPeak << std::endl; 
     } 

     std::cout << "\n\n"; 
     Sleep(1000); 
    } 

    CoUninitialize(); 
} 

double getVolume() { 
    float currentVolume = 0; 

    CoInitialize(NULL); 
    IMMDeviceEnumerator *deviceEnumerator = NULL; 
    CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator); 
    IMMDevice *defaultDevice = NULL; 
    deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice); 
    deviceEnumerator->Release(); 
    deviceEnumerator = NULL; 

    IAudioEndpointVolume *endpointVolume = NULL; 
    defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume); 
    defaultDevice->Release(); 
    defaultDevice = NULL; 

    float fLevel; 
    endpointVolume->GetMasterVolumeLevel(&fLevel); 
    qDebug() << "FLevel: "; 
    qDebug() << fLevel; 

    endpointVolume->GetMasterVolumeLevelScalar(&currentVolume); 
    endpointVolume->Release(); 

    CoUninitialize(); 

    return (double)(currentVolume * 100); 
} 
+2

我什麼都不知道是什麼返回值的範圍是,但查找標準的「地圖系列」方程。它用於將數字從一個範圍(比如0-1)轉換爲另一個範圍(比如0-100)。不過,您需要知道它首先使用的範圍。另外請注意,如果它在0-1的範圍內那麼簡單,你總是可以將它乘以100. – Carcigenicate

+0

是的,我已經試着將值乘以100,但是你得到的值是像8.12或2.13(以上例子)。我的主音量是50%,程序也是這樣。所以值應該是50%或25%(導致主音量在50%)。當然,如果我不那麼愚蠢。 已經嘗試了一些其他計算,沒有按預期工作,這並不一定意味着這個值是錯誤的。 我已經試過沒有標量獲得主音量級別,但是我得到的值是-10.5467574,這也不是正確的。 但是,感謝您的評論 – CaptTaifun

+0

嗯...這幾乎就像音量衰減的deciBels,這是在音頻世界相當普遍。 -10是一個強烈的暗示。檢查你的值與dB浮點計算器... http://www.playdotsound.com/portfolio-item/decibel-db-to-float-value-calculator-making-sense-of-linear-values-in- audio-tools/ –

回答

0

好吧,夥計們,我找到了解決我的問題的方法!

我必須調用SessionControl上的QueryInterface才能訪問ISimpleAudioVolume,您可以在其中使用函數GetMasterVolume和SetMasterVolume。這是一個0-1的標量,但你可以將它乘以100得到一個0-100的標量。如果系統的主音量達到50%,如果程序音量也是50%,則輸出爲1,因此輸出基於系統的主音量!

感謝您的每一個評論和幫助!

這裏的工作代碼:

void getSessions() { 
    CoInitialize(NULL); 

    IMMDeviceEnumerator *pDeviceEnumerator; 
    IMMDevice *pDevice; 
    IAudioSessionManager2 *pAudioSessionManager2; 
    IAudioSessionEnumerator *pAudioSessionEnumerator; 

    CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&pDeviceEnumerator); 
    pDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice); 

    pDevice->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (void **) &pAudioSessionManager2); 
    pAudioSessionManager2->GetSessionEnumerator(&pAudioSessionEnumerator); 

    int nSessionCount; 
    pAudioSessionEnumerator->GetCount(&nSessionCount); 

    while (true) { 
     for (int nSessionIndex = 0; nSessionIndex < nSessionCount; nSessionIndex++) { 
      IAudioSessionControl *pSessionControl; 
      if (FAILED(pAudioSessionEnumerator->GetSession(nSessionIndex, &pSessionControl))) 
       continue; 

      ISimpleAudioVolume *pSimpleAudioVolume; 
      pSessionControl->QueryInterface(&pSimpleAudioVolume); 

      float fLevel; 
      pSimpleAudioVolume->GetMasterVolume(&fLevel); 

      std::cout << "fLevel Value: " << fLevel << std::endl; 
     } 

     Sleep(1000); 
    } 

    CoUninitialize(); 
}