gpt4 book ai didi

audio - wasapi:检测到没有播放任何内容(设备未在使用中)

转载 作者:行者123 更新时间:2023-12-02 23:07:50 26 4
gpt4 key购买 nike

我用 wasapi用于环回捕获。之后的所有数据都保存到wav文件。
当它开始捕获时,它一直在传递数据,直到我停止捕获过程,即使没有应用程序使用音频设备,因此没有人产生音乐。结果,我写入文件不是有值(value)的数据 - 只是沉默。

那么有没有办法在当前播放的音乐和设备完全不使用的情况下区分静音。在以后的情况下,我想中断将数据记录到文件中的过程,并在再次通过音频设备播放 smth 时创建新文件。

PS AudioCaptureClinet 方法GetBuffer带有输出参数 flag这似乎可以有值(value)AUDCLNT_BUFFERFLAGS_SILENT == 0x1在某些情况下,但在我的情况下它返回 flag==0每次

最佳答案

好的,事实证明没有可靠的方法可以从环回流本身推断出没有任何内容播放到相应的输出设备。但是,可以在输出设备本身上查询 Audio Session ,并且对于每个 session ,检查其状态是否处于事件状态。还可以在向设备添加/删除 session 时收到通知,并在 session (取消)激活时收到通知。这样,您可以在设备上的第一个 session 激活时启动环回流,并在最后一个 session 停用时停止它。

这是如何做到的:

  • 实现 IAudioSessionNotification 和 IAudioSessionEvents
  • 设置 MTA 线程,STA 不工作
  • 检索要监控的输出的 IMMDevice 接口(interface)
  • 从 IMMDevice 获取 IAudioSessionManager2
  • 从 IAudioSessionManager2 获取 IAudioSessionEnumerator
  • 从 IAudioSessionEnumerator,枚举 IAudioSessionControls
  • 这是初始 session 的列表。它将在枚举器的生命周期内保持不变。
  • 在 IAudioSessionControl 中,使用 GetState 查看最初处于事件状态的内容
  • 使用 IAudioSessionControl::RegisterAudioSessionNotification 获得初始 session 激活(停用)的通知
  • 使用 IAudioSessionManager2::RegisterSessionNotification 注册您的自定义 session 通知
  • 这将在初始枚举
  • 之后创建的任何其他 session 中调用。
  • 从 IAudioSessionNotification::OnSessionCreated 中,使用 IAudioSessionControl::RegisterAudioSessionNotification 来获得有关(取消)激活其他 session 的通知
  • 如果任何 session 最初处于事件状态,则启动环回流
  • 当最后一个(初始或附加) session 被停用或断开时,停止环回流
  • 当然,当任何 session 再次激活时重新启动

  • 下面是一个工作示例。请注意,我没有:
  • 除了打印出什么问题之外,做任何彻底的错误处理
  • 实际上设置了环回流。示例仅在任何(停用)激活时打印。
  • 做任何 COM 接口(interface)的簿记! sample 到处都是泄漏接口(interface)句柄。要正确处理这些内容,您可能希望将 SessionNotifications/SessionEvents 对象存储在一些线程安全的集合中,并在 session 被破坏时取消注册/释放它们。


  • #include <windows.h>
    #include <atlbase.h>
    #include <atlcomcli.h>
    #include <mmdeviceapi.h>
    #include <audioclient.h>
    #include <audiopolicy.h>
    #include <iostream>
    #include <vector>
    #include <string>

    #define VERIFY(expr) do { \
    if(FAILED(hr = (expr))) { \
    std::cout << "Error: " << #expr << ": " << hr << "\n"; \
    goto error; \
    } \
    } while(0)

    static volatile ULONG sessionId = 0;

    class SessionEvents : public IAudioSessionEvents {

    private:
    LONG rc;
    ULONG id;
    ~SessionEvents() {}

    public:
    SessionEvents(ULONG id) :
    id(id), rc(1) {}

    ULONG STDMETHODCALLTYPE AddRef() {
    return InterlockedIncrement(&rc);
    }

    ULONG STDMETHODCALLTYPE Release() {
    ULONG rc = InterlockedDecrement(&this->rc);
    if(rc == 0) {
    delete this;
    }
    return rc;
    }

    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv) {
    if(IID_IUnknown == riid) {
    AddRef();
    *ppv = static_cast<IUnknown*>(this);
    return S_OK;
    }
    else if(__uuidof(IAudioSessionEvents) == riid) {
    AddRef();
    *ppv = static_cast<IAudioSessionEvents*>(this);
    return S_OK;
    }
    else {
    *ppv = nullptr;
    return E_NOINTERFACE;
    }
    }

    HRESULT STDMETHODCALLTYPE OnDisplayNameChanged(LPCWSTR NewDisplayName, LPCGUID EventContext) {
    return S_OK;
    }

    HRESULT STDMETHODCALLTYPE OnIconPathChanged(LPCWSTR NewIconPath, LPCGUID EventContext) {
    return S_OK;
    }

    HRESULT STDMETHODCALLTYPE OnSimpleVolumeChanged(float NewVolume, BOOL NewMute, LPCGUID EventContext) {
    return S_OK;
    }

    HRESULT STDMETHODCALLTYPE OnChannelVolumeChanged(DWORD ChannelCount, float NewChannelVolumeArray[], DWORD ChangedChannel, LPCGUID EventContext) {
    return S_OK;
    }

    HRESULT STDMETHODCALLTYPE OnGroupingParamChanged(LPCGUID NewGroupingParam, LPCGUID EventContext) {
    return S_OK;
    }

    HRESULT STDMETHODCALLTYPE OnStateChanged(AudioSessionState NewState) {
    switch(NewState) {
    case AudioSessionStateInactive: std::wcout << L"AudioSessionStateInactive session # " << id << L"\n"; break;
    case AudioSessionStateActive: std::wcout << L"AudioSessionStateActive session # " << id << L"\n"; break;
    case AudioSessionStateExpired: std::wcout << L"AudioSessionStateExpired session # " << id << L"\n"; break;
    }
    return S_OK;
    }

    HRESULT STDMETHODCALLTYPE OnSessionDisconnected(AudioSessionDisconnectReason DisconnectReason) {
    std::wcout << L"OnSessionDisconnected session # " << id << L"\n";
    return S_OK;
    }
    };

    class SessionNotification : public IAudioSessionNotification {

    private:
    LONG rc;
    ~SessionNotification() {}

    public:
    SessionNotification() : rc(1) {}

    ULONG STDMETHODCALLTYPE AddRef() {
    return InterlockedIncrement(&rc);
    }

    ULONG STDMETHODCALLTYPE Release() {
    ULONG rc = InterlockedDecrement(&this->rc);
    if(rc == 0)
    delete this;
    return rc;
    }

    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv) {
    if(IID_IUnknown == riid) {
    AddRef();
    *ppv = static_cast<IUnknown*>(this);
    return S_OK;
    }
    else if(__uuidof(IAudioSessionNotification) == riid) {
    AddRef();
    *ppv = static_cast<IAudioSessionNotification*>(this);
    return S_OK;
    }
    else {
    *ppv = nullptr;
    return E_NOINTERFACE;
    }
    }

    HRESULT OnSessionCreated(IAudioSessionControl *newSession) {
    HRESULT hr = S_OK;
    if(newSession) {
    newSession->AddRef();
    CComHeapPtr<WCHAR> name;
    ULONG id = InterlockedIncrement(&sessionId);
    VERIFY(newSession->GetDisplayName(&name));
    std::wcout << L"created session # " << id << L": " << name.m_pData << L"\n";
    VERIFY(newSession->RegisterAudioSessionNotification(new SessionEvents(id)));
    }
    error:
    return hr;
    }
    };

    int main(int argc, char** argv) {

    HRESULT hr = S_OK;
    VERIFY(CoInitializeEx(nullptr, COINIT_MULTITHREADED));

    {
    int count;
    std::wstring line;
    CComPtr<IMMDevice> defaultOutput;
    CComPtr<IMMDeviceEnumerator> devices;
    CComPtr<IAudioSessionManager2> manager;
    CComPtr<IAudioSessionEnumerator> sessions;
    SessionNotification* notification = new SessionNotification;

    VERIFY(devices.CoCreateInstance(__uuidof(MMDeviceEnumerator)));
    VERIFY(devices->GetDefaultAudioEndpoint(eRender, eMultimedia, &defaultOutput));
    VERIFY(defaultOutput->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, nullptr, reinterpret_cast<void**>(&manager)));
    VERIFY(manager->RegisterSessionNotification(notification));
    VERIFY(manager->GetSessionEnumerator(&sessions));
    VERIFY(sessions->GetCount(&count));
    std::wcout << L"Initial sessions: " << count << L"\n";
    for(int s = 0; s < count; s++) {
    AudioSessionState state;
    CComHeapPtr<WCHAR> name;
    CComPtr<IAudioSessionControl> control;
    VERIFY(sessions->GetSession(s, &control));
    VERIFY(control->GetDisplayName(&name));
    VERIFY(control->GetState(&state));
    std::wcout << L"Initial session name: " << name.m_pData << L", active = " << (state == AudioSessionStateActive) << L"\n";
    VERIFY(control->RegisterAudioSessionNotification(new SessionEvents(InterlockedIncrement(&sessionId))));
    }

    std::wcout << L"Press return to exit...\n";
    std::getline(std::wcin, line);
    VERIFY(manager->UnregisterSessionNotification(notification));
    }

    error:
    CoUninitialize();
    return 0;
    }

    关于audio - wasapi:检测到没有播放任何内容(设备未在使用中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38310477/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com