基於OpenCV的視頻圖像組態 (14):音量控制

實現代碼

 編寫的播放軟件,慢慢地有了聲音控制的需求,在網上找了一下,用Core Audio APIS 音頻應用開發即可。入門稍慢,不過用起來很簡單。整理了一個類供調用。

 

class TCbwAudioEndpointVolumeCallback;

typedef void __fastcall (__closure * TOnVoiceNotifyEvent)(bool bMuted, int fMasterVolume);

class TCbwVolumeControl {

private:

    TCbwAudioEndpointVolumeCallback * EPVolEvents;

    TOnVoiceNotifyEvent FOnVoiceNotify;

    bool FValid;

    bool __fastcall HRStatus(HRESULT hr, UnicodeString info);

    void __fastcall Prework();

    void __fastcall AfterWork();

    int __fastcall GetMasterVolume();

    void __fastcall SetMasterVolume(int value);

    bool __fastcall GetMuted();

    void __fastcall SetMuted(bool value);

public:

    __fastcall TCbwVolumeControl();

    __fastcall ~TCbwVolumeControl();

    __property bool IsValid = { read = FValid };

 

    __property int MasterVolume = { read = GetMasterVolume, write = SetMasterVolume };

    __property bool Muted = { read = GetMuted, write = SetMuted };

    __property TOnVoiceNotifyEvent OnVoiceNotify = { read = FOnVoiceNotify, write = FOnVoiceNotify };

    void __fastcall OnNotifyFromCallback(bool bMuted, float fMasterVolume);

};

extern TCbwVolumeControl * GlobalVolumeControl;

 

 

TCbwVolumeControl * GlobalVolumeControl = NULL;

IMMDeviceEnumerator *pEnumerator = NULL;

IMMDevice *pDevice = NULL;

IAudioEndpointVolume *g_pEndptVol = NULL;

 

#define SAFE_RELEASE(punk) \

if ((punk) != NULL) \

{ (punk)->Release(); (punk) = NULL; }

#define EXIT_ON_ERROR(hr) \

if (FAILED(hr)) return;

 

__fastcall TCbwVolumeControl::TCbwVolumeControl() {

    EPVolEvents = new TCbwAudioEndpointVolumeCallback;

    FOnVoiceNotify = NULL;

    EPVolEvents->ParentControl = this;

    Prework();

}

 

__fastcall TCbwVolumeControl::~TCbwVolumeControl() {

    AfterWork();

    delete EPVolEvents;

}

 

bool __fastcall TCbwVolumeControl::HRStatus(HRESULT hr, UnicodeString info) {

    if (FAILED(hr)) {

        DRGRAPH_DEBUG(THelper::FormatString(L"CALL %s FAILED!", info));

        return false;

    }

    return true;

}

 

void __fastcall TCbwVolumeControl::Prework() {

    FValid = false;

    pEnumerator = NULL;

    pDevice = NULL;

    g_pEndptVol = NULL;

    GUID g_guidMyContext = GUID_NULL;

    CoInitialize(NULL);

    if (HRStatus(CoCreateGuid(&g_guidMyContext),

        L"CoCreateGuid(&g_guidMyContext)"))

        if (HRStatus(CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,

            CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator),

            (void**)&pEnumerator), L"CoCreateInstance"))

            if (HRStatus(pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole,

                &pDevice), L"pEnumerator->GetDefaultAudioEndpoint"))

                if (HRStatus(pDevice->Activate(__uuidof(IAudioEndpointVolume),

                    CLSCTX_ALL, NULL, (void**)&g_pEndptVol),

                    L"pDevice->Activate"))

                    if (HRStatus(g_pEndptVol->RegisterControlChangeNotify

                        ((IAudioEndpointVolumeCallback*)EPVolEvents),

                        L"g_pEndptVol->RegisterControlChangeNotify"))

                        FValid = true;

}

 

void __fastcall TCbwVolumeControl::AfterWork() {

    if (pEnumerator != NULL) {

        HRStatus(g_pEndptVol->UnregisterControlChangeNotify

            ((IAudioEndpointVolumeCallback*) EPVolEvents),

            L"g_pEndptVol->UnregisterControlChangeNotify");

    }

    SAFE_RELEASE(pEnumerator);

    SAFE_RELEASE(pDevice);

    SAFE_RELEASE(g_pEndptVol);

    CoUninitialize();

}

 

int __fastcall TCbwVolumeControl::GetMasterVolume() {

    float pfLevel = 0;

    HRStatus(g_pEndptVol->GetMasterVolumeLevelScalar(&pfLevel),

        L"g_pEndptVol->GetMasterVolumeLevel");

    return pfLevel * 100 + 0.5;

}

 

void __fastcall TCbwVolumeControl::SetMasterVolume(int value) {

    float fVolume = value / 100.0;

    HRStatus(g_pEndptVol->SetMasterVolumeLevelScalar(fVolume,

        &GUID_NULL), L"pAudioEndpointVolume->SetMasterVolumeLevelScalar");

}

 

void __fastcall TCbwVolumeControl::OnNotifyFromCallback(bool bMuted,

    float fMasterVolume) {

    if (FOnVoiceNotify)

        FOnVoiceNotify(bMuted, fMasterVolume * 100 + 0.5);

}

 

bool __fastcall TCbwVolumeControl::GetMuted() {

    int muted = false;

    g_pEndptVol->GetMute(&muted);

    return muted;

}

 

void __fastcall TCbwVolumeControl::SetMuted(bool value) {

    HRStatus(g_pEndptVol->SetMute(value,

        &GUID_NULL), L"pAudioEndpointVolume->SetMute");

}


演示效果

簡單做了一個測試界面。

void __fastcall TMainForm::OnVoiceNotify(bool bMuted, int fMasterVolume) {
    Button_Mute->EditValue = bMuted;
    Button_Volume->EditValue = fMasterVolume;
}

void __fastcall TMainForm::Button_MutePropertiesEditValueChanged(TObject *Sender) {
    bool muted = Button_Mute->CurEditValue;
    int volume = Button_Volume->CurEditValue;
    ShowStatus(THelper::FormatString(L"%d, %s", volume, muted ? L"Muted" : L"Sound"));
    FVolumeControl->MasterVolume = volume;
    FVolumeControl->Muted = muted;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章