hnsbufferduration parameter in iaudioclient:: initialize method

哲敏 陈 86 Reputation points
2022-01-07T12:31:01.637+00:00

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://learn.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 API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,582 questions
Windows Hardware Performance
Windows Hardware Performance
Windows: A family of Microsoft operating systems that run across personal computers, tablets, laptops, phones, internet of things devices, self-contained mixed reality headsets, large collaboration screens, and other devices.Hardware Performance: Delivering / providing hardware or hardware systems or adjusting / adapting hardware or hardware systems.
1,607 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Junjie Zhu - MSFT 17,386 Reputation points Microsoft Vendor
    2022-01-26T07:35:36.63+00:00

    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.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.