IAudioClient 剪切声音的开头

IAudioClient cuts the beginning of sounds

提问人:Pavel Dubsky 提问时间:5/24/2023 更新时间:5/24/2023 访问量:80

问:

如果我尝试使用声音来播放声音,我会在一开始就被剪掉声音。但是,如果我在调用后添加延迟并将实际数据加载到缓冲区中,则一切正常。我知道设备需要一些时间来初始化,但无法确切知道它何时准备就绪。IAudioClientStart

有没有办法知道音频引擎已完全初始化,所有数据都将在不剪切的情况下播放?这种情况有什么解决办法吗?我试图在应用程序启动期间创建一些未使用的设备并使其保持播放(无),以便所有随后创建的设备从一开始就工作并且它工作,但还有其他任何(正确)

HRESULT hr = S_OK;

hr = CoInitialize(nullptr);
EXIT_ON_ERROR(hr)

IMMDeviceEnumerator* deviceEnumerator = nullptr;
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&deviceEnumerator);
EXIT_ON_ERROR(hr)

IMMDevice* device = nullptr;
hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device);
EXIT_ON_ERROR(hr)

IAudioClient* audioClient = nullptr;
hr = device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, (void**)&audioClient);
EXIT_ON_ERROR(hr)

WAVEFORMATEX* waveFormat = nullptr;
hr = audioClient->GetMixFormat(&waveFormat);
EXIT_ON_ERROR(hr)

const REFERENCE_TIME requestedDuration = ReftimesPerSecond;
hr = audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, requestedDuration, 0, waveFormat, nullptr);
EXIT_ON_ERROR(hr)

AudioSource audioSource;
hr = audioSource.Read("../short1.wav", *waveFormat);
EXIT_ON_ERROR(hr)

// Get the actual size of the allocated buffer.
UINT32 bufferFrameCount = 0;
hr = audioClient->GetBufferSize(&bufferFrameCount);
EXIT_ON_ERROR(hr)

IAudioRenderClient* renderClient = nullptr;
hr = audioClient->GetService(__uuidof(IAudioRenderClient), (void**)&renderClient);
EXIT_ON_ERROR(hr)

// Start playing.
hr = audioClient->Start();
EXIT_ON_ERROR(hr)

// If uncomment everything works.
//Sleep(500);

// Calculate the actual duration of the allocated buffer.
const REFERENCE_TIME actualDuration = ReftimesPerSecond * bufferFrameCount / waveFormat->nSamplesPerSec;
const REFERENCE_TIME halfActualDurationInMilliseconds = actualDuration / ReftimesPerMillisecond / 2;

DWORD flags = 0;

// Each loop fills about half of the shared buffer.
do
{
    // See how much buffer space is available.
    UINT32 paddingFrameCount = 0;
    hr = audioClient->GetCurrentPadding(&paddingFrameCount);
    EXIT_ON_ERROR(hr)

    const UINT32 availableFrameCount = bufferFrameCount - paddingFrameCount;

    // Grab all the available space in the shared buffer.
    BYTE* data = nullptr;
    hr = renderClient->GetBuffer(availableFrameCount, &data);
    EXIT_ON_ERROR(hr)

    // Get next 1/2-second of data from the audio source.
    hr = audioSource.LoadData(availableFrameCount, data, &flags, *waveFormat);
    EXIT_ON_ERROR(hr)

    hr = renderClient->ReleaseBuffer(availableFrameCount, flags);
    EXIT_ON_ERROR(hr)

    // Sleep for half the buffer duration.
    Sleep((DWORD)halfActualDurationInMilliseconds);
} while (flags != AUDCLNT_BUFFERFLAGS_SILENT);

// Wait for last data in buffer to play before stopping.
Sleep((DWORD)halfActualDurationInMilliseconds);

// Stop playing.
hr = audioClient->Stop();
EXIT_ON_ERROR(hr)
C++ Windows 音频 音频流

评论


答:

0赞 Chewbacca 5/24/2023 #1

我会使用 IAudioClient2,它里面有一个 GetBufferSizeLimit 方法:IAudioClient2