Share via


Verwalten der Audiositzung

[MFPlay ist für die Verwendung in den im Abschnitt Anforderungen angegebenen Betriebssystemen verfügbar. Es kann in nachfolgenden Versionen geändert oder entfernt werden. ]

In diesem Thema wird beschrieben, wie Sie die Audiolautstärke bei Verwendung von MFPlay für die Audio-/Videowiedergabe steuern.

MFPlay bietet die folgenden Methoden zum Steuern der Audiolautstärke während der Wiedergabe.

Methode BESCHREIBUNG
IMFPMediaPlayer::SetBalance Legt das Gleichgewicht zwischen dem linken und dem rechten Kanal fest.
IMFPMediaPlayer::SetMute Schaltet die Stummschaltung des Audios auf oder hebt die Stummschaltung auf.
IMFPMediaPlayer::SetVolume Legt die Lautstärkeebene fest.

 

Um das Verhalten dieser Methoden zu verstehen, müssen Sie einige Terminologie aus der Windows-Audiositzungs-API (WASAPI) kennen, die die von MFPlay verwendete Low-Level-Audiofunktionalität implementiert.

In WASAPI gehört jeder Audiostream zu genau einer Audiositzung, bei der es sich um eine Gruppe verwandter Audiostreams handelt. In der Regel verwaltet eine Anwendung eine einzelne Audiositzung, obwohl Anwendungen mehrere Sitzungen erstellen können. Das System-Volume-Control-Programm (Sndvol) zeigt eine Lautstärkeregelung für jede Audiositzung an. Über Sndvol kann ein Benutzer die Lautstärke einer Audiositzung von außerhalb der Anwendung anpassen. Die folgende Abbildung veranschaulicht diesen Vorgang.

Diagramm: Audiodatenströme, die auf dem Weg zu den Lautsprechern über die Lautstärkeregelung weitergeleitet werden; application und sndvol point to volume control

In MFPlay kann ein Medienelement einen oder mehrere aktive Audiostreams aufweisen (in der Regel nur einen). Intern verwendet MFPlay den Streaming Audio Renderer (SAR), um die Audiostreams zu rendern. Sofern Sie dies nicht anders konfigurieren, wird die SAR-Instanz der Standardaudiositzung der Anwendung beitreten.

Die MFPlay-Audiomethoden steuern nur die Streams, die zum aktuellen Medienelement gehören. Sie wirken sich nicht auf die Lautstärke für andere Streams aus, die zu derselben Audiositzung gehören. In Bezug auf WASAPI steuern die MFPlay-Methoden die Lautstärkestufen pro Kanal, nicht die master Lautstärke. Die folgende Abbildung veranschaulicht diesen Vorgang.

Diagramm ähnlich dem vorherigen, aber der zweite Stream beginnt am Medienelement, und die Anwendung verweist auf den zweiten Stream und auf die Lautstärkeregelung.

Es ist wichtig, einige Auswirkungen dieser Funktion von MFPlay zu verstehen. Zunächst kann eine Anwendung die Wiedergabelautstärke anpassen, ohne dass sich dies auf andere Audiodatenströme auswirkt. Sie können dieses Feature bei MFPlay verwenden, um Audio-Crossfading zu implementieren, indem Sie zwei Instanzen des MFPlay-Objekts erstellen und die Lautstärke separat anpassen.

Wenn Sie MFPlay-Methoden verwenden, um den Volume- oder Stummschaltungszustand zu ändern, werden die Änderungen nicht in Sndvol angezeigt. Beispielsweise können Sie SetMute aufrufen, um das Audio stummzuschalten, aber Sndvol zeigt die Sitzung nicht als stummgeschaltet an. Wenn dagegen SndVol zum Anpassen der Sitzungslautstärke verwendet wird, werden die Änderungen nicht in den Werten widergespiegelt, die von IMFPMediaPlayer::GetVolume oder IMFPMediaPlayer::GetMute zurückgegeben werden.

Für jede instance des MFPlay-Playerobjekts entspricht die effektive Lautstärkeebene fPlayerVolume × fSessionVolume, wobei fPlayerVolume der von GetVolume zurückgegebene Wert und fSessionVolume das master Volume für die Sitzung ist.

Für einfache Wiedergabeszenarien ist es möglicherweise besser, die WASAPI zu verwenden, um die Audiolautstärke für die gesamte Sitzung zu steuern, anstatt die MFPlay-Methoden zu verwenden.

Beispielcode

Es folgt eine C++-Klasse, die die grundlegenden Aufgaben in WASAPI verarbeitet:

  • Steuern der Lautstärke und des Stummschaltungszustands für die Sitzung.
  • Erhalten von Benachrichtigungen, wenn sich der Volume- oder Stummschaltungszustand ändert.

Klassendeklaration

Die CAudioSessionVolume Klassendeklaration implementiert die IAudioSessionEvents-Schnittstelle , die die Rückrufschnittstelle für Audiositzungsereignisse ist.

class CAudioSessionVolume : public IAudioSessionEvents
{
public:
    // Static method to create an instance of the object.
    static HRESULT CreateInstance(
        UINT uNotificationMessage,
        HWND hwndNotification,
        CAudioSessionVolume **ppAudioSessionVolume
    );

    // IUnknown methods.
    STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
    STDMETHODIMP_(ULONG) AddRef();
    STDMETHODIMP_(ULONG) Release();

    // IAudioSessionEvents methods.

    STDMETHODIMP OnSimpleVolumeChanged(
        float NewVolume,
        BOOL NewMute,
        LPCGUID EventContext
        );

    // The remaining audio session events do not require any action.
    STDMETHODIMP OnDisplayNameChanged(LPCWSTR,LPCGUID)
    {
        return S_OK;
    }

    STDMETHODIMP OnIconPathChanged(LPCWSTR,LPCGUID)
    {
        return S_OK;
    }

    STDMETHODIMP OnChannelVolumeChanged(DWORD,float[],DWORD,LPCGUID)
    {
        return S_OK;
    }

    STDMETHODIMP OnGroupingParamChanged(LPCGUID,LPCGUID)
    {
        return S_OK;
    }

    STDMETHODIMP OnStateChanged(AudioSessionState)
    {
        return S_OK;
    }

    STDMETHODIMP OnSessionDisconnected(AudioSessionDisconnectReason)
    {
        return S_OK;
    }

    // Other methods
    HRESULT EnableNotifications(BOOL bEnable);
    HRESULT GetVolume(float *pflVolume);
    HRESULT SetVolume(float flVolume);
    HRESULT GetMute(BOOL *pbMute);
    HRESULT SetMute(BOOL bMute);
    HRESULT SetDisplayName(const WCHAR *wszName);

protected:
    CAudioSessionVolume(UINT uNotificationMessage, HWND hwndNotification);
    ~CAudioSessionVolume();

    HRESULT Initialize();

protected:
    LONG m_cRef;                        // Reference count.
    UINT m_uNotificationMessage;        // Window message to send when an audio event occurs.
    HWND m_hwndNotification;            // Window to receives messages.
    BOOL m_bNotificationsEnabled;       // Are audio notifications enabled?

    IAudioSessionControl    *m_pAudioSession;
    ISimpleAudioVolume      *m_pSimpleAudioVolume;
};

Wenn das CAudioSessionVolume Objekt ein Audiositzungsereignis empfängt, sendet es eine private Fensternachricht an die Anwendung. Das Fensterhandle und die Fenstermeldung werden als Parameter für die statische CAudioSessionVolume::CreateInstance Methode angegeben.

Abrufen der WASAPI-Schnittstellenzeiger

CAudioSessionVolumeverwendet zwei Standard WASAPI-Schnittstellen:

Um diese Schnittstellen zu erhalten, müssen Sie den Audioendpunkt auflisten, der von der SAR verwendet wird. Ein Audioendpunkt ist ein Hardwaregerät, das Audiodaten erfasst oder nutzt. Für die Audiowiedergabe ist ein Endpunkt einfach ein Lautsprecher oder eine andere Audioausgabe. Standardmäßig verwendet die SAR den Standardendpunkt für die Geräterolle eConsole . Eine Geräterolle ist eine zugewiesene Rolle für einen Endpunkt. Geräterollen werden durch die ERole-Enumeration angegeben, die in Core Audio-APIs dokumentiert ist.

Der folgende Code zeigt, wie Sie den Endpunkt auflisten und die WASAPI-Schnittstellen abrufen.

HRESULT CAudioSessionVolume::Initialize()
{
    HRESULT hr = S_OK;

    IMMDeviceEnumerator *pDeviceEnumerator = NULL;
    IMMDevice *pDevice = NULL;
    IAudioSessionManager *pAudioSessionManager = NULL;

    // Get the enumerator for the audio endpoint devices.
    hr = CoCreateInstance(
        __uuidof(MMDeviceEnumerator),
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_PPV_ARGS(&pDeviceEnumerator)
        );

    if (FAILED(hr))
    {
        goto done;
    }

    // Get the default audio endpoint that the SAR will use.
    hr = pDeviceEnumerator->GetDefaultAudioEndpoint(
        eRender,
        eConsole,   // The SAR uses 'eConsole' by default.
        &pDevice
        );

    if (FAILED(hr))
    {
        goto done;
    }

    // Get the session manager for this device.
    hr = pDevice->Activate(
        __uuidof(IAudioSessionManager),
        CLSCTX_INPROC_SERVER,
        NULL,
        (void**) &pAudioSessionManager
        );

    if (FAILED(hr))
    {
        goto done;
    }

    // Get the audio session.
    hr = pAudioSessionManager->GetAudioSessionControl(
        &GUID_NULL,     // Get the default audio session.
        FALSE,          // The session is not cross-process.
        &m_pAudioSession
        );


    if (FAILED(hr))
    {
        goto done;
    }

    hr = pAudioSessionManager->GetSimpleAudioVolume(
        &GUID_NULL, 0, &m_pSimpleAudioVolume
        );

done:
    SafeRelease(&pDeviceEnumerator);
    SafeRelease(&pDevice);
    SafeRelease(&pAudioSessionManager);
    return hr;
}

Steuern der Lautstärke

Die CAudioSessionVolume Methoden, die die Audiolautstärke steuern, rufen die entsprechenden ISimpleAudioVolume-Methoden auf. Ruft beispielsweise CAudioSessionVolume::SetVolumeISimpleAudioVolume::SetMasterVolume auf, wie im folgenden Code gezeigt.

HRESULT CAudioSessionVolume::SetVolume(float flVolume)
{
    if (m_pSimpleAudioVolume == NULL)
    {
        return E_FAIL;
    }
    else
    {
        return m_pSimpleAudioVolume->SetMasterVolume(
            flVolume,
            &AudioSessionVolumeCtx  // Event context.
            );
    }
}

Vollständiger CAudioSessionVolume-Code

Hier ist die vollständige Auflistung der Methoden der CAudioSessionVolume -Klasse.

static const GUID AudioSessionVolumeCtx =
{ 0x2715279f, 0x4139, 0x4ba0, { 0x9c, 0xb1, 0xb3, 0x51, 0xf1, 0xb5, 0x8a, 0x4a } };


CAudioSessionVolume::CAudioSessionVolume(
    UINT uNotificationMessage,
    HWND hwndNotification
    )
    : m_cRef(1),
      m_uNotificationMessage(uNotificationMessage),
      m_hwndNotification(hwndNotification),
      m_bNotificationsEnabled(FALSE),
      m_pAudioSession(NULL),
      m_pSimpleAudioVolume(NULL)
{
}

CAudioSessionVolume::~CAudioSessionVolume()
{
    EnableNotifications(FALSE);

    SafeRelease(&m_pAudioSession);
    SafeRelease(&m_pSimpleAudioVolume);
};


//  Creates an instance of the CAudioSessionVolume object.

/* static */
HRESULT CAudioSessionVolume::CreateInstance(
    UINT uNotificationMessage,
    HWND hwndNotification,
    CAudioSessionVolume **ppAudioSessionVolume
    )
{

    CAudioSessionVolume *pAudioSessionVolume = new (std::nothrow)
        CAudioSessionVolume(uNotificationMessage, hwndNotification);

    if (pAudioSessionVolume == NULL)
    {
        return E_OUTOFMEMORY;
    }

    HRESULT hr = pAudioSessionVolume->Initialize();
    if (SUCCEEDED(hr))
    {
        *ppAudioSessionVolume = pAudioSessionVolume;
    }
    else
    {
        pAudioSessionVolume->Release();
    }

    return hr;
}


//  Initializes the CAudioSessionVolume object.

HRESULT CAudioSessionVolume::Initialize()
{
    HRESULT hr = S_OK;

    IMMDeviceEnumerator *pDeviceEnumerator = NULL;
    IMMDevice *pDevice = NULL;
    IAudioSessionManager *pAudioSessionManager = NULL;

    // Get the enumerator for the audio endpoint devices.
    hr = CoCreateInstance(
        __uuidof(MMDeviceEnumerator),
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_PPV_ARGS(&pDeviceEnumerator)
        );

    if (FAILED(hr))
    {
        goto done;
    }

    // Get the default audio endpoint that the SAR will use.
    hr = pDeviceEnumerator->GetDefaultAudioEndpoint(
        eRender,
        eConsole,   // The SAR uses 'eConsole' by default.
        &pDevice
        );

    if (FAILED(hr))
    {
        goto done;
    }

    // Get the session manager for this device.
    hr = pDevice->Activate(
        __uuidof(IAudioSessionManager),
        CLSCTX_INPROC_SERVER,
        NULL,
        (void**) &pAudioSessionManager
        );

    if (FAILED(hr))
    {
        goto done;
    }

    // Get the audio session.
    hr = pAudioSessionManager->GetAudioSessionControl(
        &GUID_NULL,     // Get the default audio session.
        FALSE,          // The session is not cross-process.
        &m_pAudioSession
        );


    if (FAILED(hr))
    {
        goto done;
    }

    hr = pAudioSessionManager->GetSimpleAudioVolume(
        &GUID_NULL, 0, &m_pSimpleAudioVolume
        );

done:
    SafeRelease(&pDeviceEnumerator);
    SafeRelease(&pDevice);
    SafeRelease(&pAudioSessionManager);
    return hr;
}

STDMETHODIMP CAudioSessionVolume::QueryInterface(REFIID riid, void **ppv)
{
    static const QITAB qit[] =
    {
        QITABENT(CAudioSessionVolume, IAudioSessionEvents),
        { 0 },
    };
    return QISearch(this, qit, riid, ppv);
}

STDMETHODIMP_(ULONG) CAudioSessionVolume::AddRef()
{
    return InterlockedIncrement(&m_cRef);
}

STDMETHODIMP_(ULONG) CAudioSessionVolume::Release()
{
    LONG cRef = InterlockedDecrement( &m_cRef );
    if (cRef == 0)
    {
        delete this;
    }
    return cRef;
}


// Enables or disables notifications from the audio session. For example, the
// application is notified if the user mutes the audio through the system
// volume-control program (Sndvol).

HRESULT CAudioSessionVolume::EnableNotifications(BOOL bEnable)
{
    HRESULT hr = S_OK;

    if (m_hwndNotification == NULL || m_pAudioSession == NULL)
    {
        return E_FAIL;
    }

    if (m_bNotificationsEnabled == bEnable)
    {
        // No change.
        return S_OK;
    }

    if (bEnable)
    {
        hr = m_pAudioSession->RegisterAudioSessionNotification(this);
    }
    else
    {
        hr = m_pAudioSession->UnregisterAudioSessionNotification(this);
    }

    if (SUCCEEDED(hr))
    {
        m_bNotificationsEnabled = bEnable;
    }

    return hr;
}


// Gets the session volume level.

HRESULT CAudioSessionVolume::GetVolume(float *pflVolume)
{
    if ( m_pSimpleAudioVolume == NULL)
    {
        return E_FAIL;
    }
    else
    {
        return m_pSimpleAudioVolume->GetMasterVolume(pflVolume);
    }
}

//  Sets the session volume level.
//
//  flVolume: Ranges from 0 (silent) to 1 (full volume)

HRESULT CAudioSessionVolume::SetVolume(float flVolume)
{
    if (m_pSimpleAudioVolume == NULL)
    {
        return E_FAIL;
    }
    else
    {
        return m_pSimpleAudioVolume->SetMasterVolume(
            flVolume,
            &AudioSessionVolumeCtx  // Event context.
            );
    }
}


//  Gets the muting state of the session.

HRESULT CAudioSessionVolume::GetMute(BOOL *pbMute)
{
    if (m_pSimpleAudioVolume == NULL)
    {
        return E_FAIL;
    }
    else
    {
        return m_pSimpleAudioVolume->GetMute(pbMute);
    }
}

//  Mutes or unmutes the session audio.

HRESULT CAudioSessionVolume::SetMute(BOOL bMute)
{
    if (m_pSimpleAudioVolume == NULL)
    {
        return E_FAIL;
    }
    else
    {
        return m_pSimpleAudioVolume->SetMute(
            bMute,
            &AudioSessionVolumeCtx  // Event context.
            );
    }
}

//  Sets the display name for the session audio.

HRESULT CAudioSessionVolume::SetDisplayName(const WCHAR *wszName)
{
    if (m_pAudioSession == NULL)
    {
        return E_FAIL;
    }
    else
    {
        return m_pAudioSession->SetDisplayName(wszName, NULL);
    }
}


//  Called when the session volume level or muting state changes.
//  (Implements IAudioSessionEvents::OnSimpleVolumeChanged.)

HRESULT CAudioSessionVolume::OnSimpleVolumeChanged(
    float NewVolume,
    BOOL NewMute,
    LPCGUID EventContext
    )
{
    // Check if we should post a message to the application.

    if ( m_bNotificationsEnabled &&
        (*EventContext != AudioSessionVolumeCtx) &&
        (m_hwndNotification != NULL)
        )
    {
        // Notifications are enabled, AND
        // We did not trigger the event ourselves, AND
        // We have a valid window handle.

        // Post the message.
        ::PostMessage(
            m_hwndNotification,
            m_uNotificationMessage,
            *((WPARAM*)(&NewVolume)),  // Coerce the float.
            (LPARAM)NewMute
            );
    }
    return S_OK;
}

Anforderungen

MFPlay erfordert Windows 7.

Verwenden von MFPlay für die Audio-/Videowiedergabe