question

75905375 avatar image
0 Votes"
75905375 asked JunjieZhu-MSFT commented

hnsbufferduration parameter in iaudioclient:: initialize method

In the iaudioclient:: initialize method, the third parameter is hnsbufferduration. In the explanation of Microsoft documents, this parameter contains the buffer size requested by the caller. If the iaudioclient:: initialize method is called successfully, the system will allocate a buffer of at least this size.(https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-initialize

For capture and render, I have the following two questions:

  1. For the rendering device, when calling the iaudioclient:: initialize method, set the hnsbufferduration to 100 * 10000 (i.e. the buffer size is 100ms), and set the hnsperiodicity parameter to 0 (which means that the default period is 10ms). Does that mean that I must fill the 100ms buffer to play the sound from the speaker? Or does the system play the data in the rendering buffer from the speaker device every 10ms?Because I will receive the system event notification every 10ms. At this time, I will call the iaudiorenderclient:: getbuffer method to insert 10ms of data into the buffer. So I want to know when the speaker will really play sound? Do you need to fill all the buffers set by hnsbufferduration (or reach a certain amount) before playing through the speaker device.

  2. For the capture device, when calling the iaudioclient:: initialize method, set the hnsbufferduration to 100 * 10000 (i.e. the buffer size is 100ms), and set the hnsperiodicity parameter to 0 (which means that the default period is 10ms). Does it mean that this buffer can help me cache the next 100ms of data at most?For example, under normal circumstances, I should have received the system event notification for each 10ms, then called IAudioCaptureClient:: GetBuffer to get the data collected by the microphone. If my thread gets stuck during this period and calls iaudiocaptureclient:: getbuffer after 60ms, does the capture buffer help me save all the data in the past 60ms?

Look forward to your professional answer, thank you

windows-apiwindows-hardware-code-audio
· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

There seems to be no explanation for this two question in the official documentation, this needs to be systematically tested, please wait.

0 Votes 0 ·
75905375 avatar image 75905375 JunjieZhu-MSFT ·

thank you,I have searched many Microsoft documents, but I haven't found relevant information. I look forward to your answer

0 Votes 0 ·

It has been a long time. Have you solved your problem?

0 Votes 0 ·
Show more comments

1 Answer

JunjieZhu-MSFT avatar image
0 Votes"
JunjieZhu-MSFT answered JunjieZhu-MSFT commented

Hello,
Welcome to Microsoft Q&A!

Sorry to keep you waiting. Since I didn't have a rendering device with me, I could only do capture tests.
When I did my tests, I found that the buffer could read incomplete data by CopyMemory, but for C++ memory safety, I recommend using WaitForSingleObject(AudioSamplesReadyEvent, INFINITE) in the thread to prevent memory problems.

 //InitializeAudioEngine
     hr = _AudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST, 100* 10000, 0, _MixFormat, NULL);
    
     if (FAILED(hr))
     {
         printf("Unable to initialize audio client: %x.\n", hr);
         return false;
     }
    
     //
     //  Retrieve the buffer size for the audio client.
     //
     hr = _AudioClient->GetBufferSize(&_BufferSize);
     //printf(" get audio client buffer: %d \n", _BufferSize);
     if (FAILED(hr))
     {
         printf("Unable to get audio client buffer: %x. \n", hr);
         return false;
     }
     hr = _AudioClient->SetEventHandle(_AudioSamplesReadyEvent);
     if (FAILED(hr))
     {
         printf("Unable to set ready event: %x.\n", hr);
         return false;
     }
    
     hr = _AudioClient->GetService(IID_PPV_ARGS(&_CaptureClient));
     if (FAILED(hr))
     {
         printf("Unable to get new capture client: %x.\n", hr);
         return false;
     }
    
     //start capture
    
     hr = _AudioClient->Start();
     if (FAILED(hr))
     {
         printf("Unable to get new capture client: %x.\n", hr);
         return false;
     }
    
     bool stillPlaying = true;
     while (stillPlaying)
     {
         DWORD waitResult = WaitForSingleObject(_AudioSamplesReadyEvent, INFINITE);
    
         BYTE* pData, * pBuffer;
         INT nBufferLenght;
         UINT32 framesAvailable;
         DWORD  flags;
         pBuffer = new BYTE[MAX_AUDIO_FRAME_SIZE];
         hr = _CaptureClient->GetBuffer(&pData, &framesAvailable, &flags, NULL, NULL);
         if (SUCCEEDED(hr))
         {
             if (framesAvailable != 0)
             {
                 if (flags & AUDCLNT_BUFFERFLAGS_SILENT)
                 {
                     //
                     //  Fill 0s from the capture buffer to the output buffer.
                     //
                 }
                 else
                 {
                     //
                     //  Copy data from the audio engine buffer to the output buffer.
                     //
    
                     CopyMemory(pBuffer, pData, framesAvailable * _FrameSize);
                     printf("get capture frames: %d!\n", framesAvailable);
                 }
             }
             delete[] pBuffer;
             hr = _CaptureClient->ReleaseBuffer(framesAvailable);
             if (FAILED(hr))
             {
                 printf("Unable to release capture buffer: %x!\n", hr);
             }
         }
     }

Thank you.


If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thank you for your answer, but it doesn't seem to have much to do with my question. What I want to know more is that forWhether the [100 * 10000] parameter in _audioclient - > initialize can cache data. More detailed consultation contents have been described in my question, thank you very much for your answer in my question

0 Votes 0 ·

I'm not looking for how to collect audio data, but I'm confused about the role of data buffer length

0 Votes 0 ·

Hope this sentence in the official documentation is helpful to you.
https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-initialize#remarks

The endpoint buffer that is shared between the client and audio engine must be large enough to prevent glitches from occurring in the audio stream between processing passes by the client and audio engine. For a rendering endpoint, the client thread periodically writes data to the buffer, and the audio engine thread periodically reads data from the buffer. For a capture endpoint, the engine thread periodically writes to the buffer, and the client thread periodically reads from the buffer. In either case, if the periods of the client thread and engine thread are not equal, the buffer must be large enough to accommodate the longer of the two periods without allowing glitches to occur.

0 Votes 0 ·