ExylonFiber
Well-Known Member
- Joined
- Apr 25, 2020
- Messages
- 26
- Thread Author
- #1
Hello, I am developing a Winodws audio program that utilizes the built in Windows Core Audio API. I have an issue where the IAudioCaptureClient is sending a STARTING ADDRESS of an audio frame to pointer pData. I am trying to find out how to read the packet stored at that starting address by the capture client. Basically, I need to know how to iterate through the pointed to starting address through the size of the audio buffer which is 480 (frames) * 32 (bytes per frame, which is specified by the hr = pAudioClient->GetMixFormat(&pwfx); method) which means the framebuffer must be 480 * 32 = 15,360 bytes. however I dont know how to iterate through the starting address specified by pData, to the end address which is, the starting address + 15,360 bytes and then wrtie each individual byte at each address into the framebuffer, then finally write the whole audio frame to file. Can anybody give me the right direction in how to do something like this?
My code:
My code:
Code:
void RecordFromMic(MyAudioSink pMySink) {
std::fstream file;
file.open("data.wav", std::ios_base::out | std::ios_base::in); // will not create file
if (file.is_open())
{
std::cout << "Warning, file already exists: " << std::endl;
file.close();
remove("data.wav");
}
HRESULT hr;
REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;
REFERENCE_TIME hnsActualDuration;
UINT32 bufferFrameCount;
UINT32 speakerBufferFrameCount;
UINT32 numFramesAvailable;
UINT32 numFramesPadding;
IMMDeviceEnumerator* pEnumerator = NULL;
IMMDevice* pDevice = NULL;
IAudioClient* pAudioClient = NULL;
IAudioCaptureClient* pCaptureClient = NULL;
WAVEFORMATEX* pwfx = NULL;
UINT32 packetLength = 0;
BOOL bDone = FALSE;
BYTE* pData;
BYTE temp_buffer[100000];
DWORD flags;
UINT32 bytesToCapture = 0;
hr = CoCreateInstance(
CLSID_MMDeviceEnumerator, NULL,
CLSCTX_ALL, IID_IMMDeviceEnumerator,
(void**)&pEnumerator);
EXIT_ON_ERROR(hr)
pDevice = getDefaultInputAudioDevice();
hr = pDevice->Activate(
IID_IAudioClient, CLSCTX_ALL,
NULL, (void**)&pAudioClient);
EXIT_ON_ERROR(hr)
hr = pAudioClient->GetMixFormat(&pwfx);
EXIT_ON_ERROR(hr)
std::cout << "Wave Format Samples per second: " << pwfx->nSamplesPerSec << std::endl;
hr = pAudioClient->Initialize(
AUDCLNT_SHAREMODE_SHARED,
0,
hnsRequestedDuration,
0,
pwfx,
NULL);
EXIT_ON_ERROR(hr)
std::cout << "===================Output Wave Specs===================" << std::endl;
std::cout << "Wave Format: " << pwfx->wFormatTag << std::endl;
std::cout << "Wave Channels: " << pwfx->nChannels << std::endl;
std::cout << "Samples per second: " << pwfx->nSamplesPerSec << std::endl;
std::cout << "Average Bytes per Second: " << pwfx->nAvgBytesPerSec << std::endl;
std::cout << "cbSize: " << pwfx->cbSize << std::endl;
std::cout << "Bits per Sample: " << pwfx->wBitsPerSample << std::endl;
std::cout << "Block Align: " << pwfx->nBlockAlign << std::endl;
std::cout << "=======================================================" << std::endl;
//SetFormat(pwfx);
// Get the size of the allocated buffer.
hr = pAudioClient->GetBufferSize(&bufferFrameCount);
EXIT_ON_ERROR(hr)
std::cout << "microphone data buffer size: " << bufferFrameCount << std::endl;
hr = pAudioClient->GetService(
IID_IAudioCaptureClient,
(void**)&pCaptureClient);
EXIT_ON_ERROR(hr)
std::cout << "Capture Client Successfully Initialized: " << pCaptureClient << std::endl;
// Calculate the actual duration of the allocated buffer.
hnsActualDuration = (double)REFTIMES_PER_SEC *
bufferFrameCount / pwfx->nSamplesPerSec;
std::cout << "Buffer Frame Count: " << bufferFrameCount << std::endl;
std::cout << "Duration of Microphone's allocated Buffer: " << hnsActualDuration << std::endl;
std::cout << "pData mem address: " << &pData << std::endl;
hr = pAudioClient->Start(); // Start recording.
EXIT_ON_ERROR(hr)
while (bDone == FALSE) {
Sleep(hnsActualDuration / REFTIMES_PER_MILLISEC / 2);
hr = pCaptureClient->GetNextPacketSize(&packetLength); //get size of incoming audio data packet
EXIT_ON_ERROR(hr)
bytesToCapture = packetLength * pwfx->nBlockAlign;
while (packetLength != 0) //When we start receiving packets that are not of 0 value begin our loop of receiving incoming audio data
{
hr = pCaptureClient->GetBuffer(
&pData, /*pointer to starting address of audio frame data*/
&numFramesAvailable,
&flags, NULL, NULL); //Create a buffer based on the audio capture client's specifications (since every audio capture device is different in the way it provides audio data)
EXIT_ON_ERROR(hr)
if (packetLength != numFramesAvailable)
{
printf("packetlength = %d, numFramesAvailable = %d, does not match.\n", packetLength, numFramesAvailable);
bytesToCapture = numFramesAvailable * pwfx->nBlockAlign;
}
if (flags & AUDCLNT_BUFFERFLAGS_SILENT)
{
memset(pData, 0, (numFramesAvailable * pwfx->nBlockAlign));
}
if (bytesToCapture > sizeof(temp_buffer))
{
printf("bytesToCapture = %d, more than buffer size = %d\n.", bytesToCapture, sizeof(temp_buffer));
continue;
}
std::ofstream ofs("data.wav", std::ios::binary | std::ios::out | std::ios::app); //create a new file stream in which we can write recorded data to...
if (numFramesAvailable == 480) {
BYTE frameBuffer[15360];
int count = 0;
while (count < 15360) {
BYTE value = *reinterpret_cast<int*>(pData); //get value at pointed to memory address
/*memcpy(frameBuffer, value, sizeof(value);*/
ofs << value;
count++;
}
if (numFramesAvailable == 960) {
BYTE frameBuffer[30720];
int count = 0;
while (count < 30720) {
BYTE value = *reinterpret_cast<BYTE*>(pData); //get value at pointed to memory address
ofs << value;
count++;
}
}
ofs.close();
if (clock() > 6 * CLOCKS_PER_SEC) {
bDone = TRUE;
}
hr = pCaptureClient->ReleaseBuffer(numFramesAvailable);
EXIT_ON_ERROR(hr)
hr = pCaptureClient->GetNextPacketSize(&packetLength);
EXIT_ON_ERROR(hr)
}
}
hr = pAudioClient->Stop(); // Stop recording.
EXIT_ON_ERROR(hr)
Exit:
CoTaskMemFree(pwfx);
SAFE_RELEASE(pEnumerator)
SAFE_RELEASE(pDevice)
SAFE_RELEASE(pAudioClient)
SAFE_RELEASE(pCaptureClient)
}
}
- Joined
- Jul 4, 2015
- Messages
- 8,970
Really rusty on c++, but I think the best way is (assuming you have a type defined) for the whatever your trying to read you should be able to point another casted pointer to the base pointer and then do a for loop the ++ operator should increment the size of the cast type and then you can read that data where ever you need to
ExylonFiber
Well-Known Member
- Joined
- Apr 25, 2020
- Messages
- 26
- Thread Author
- #3
So, I need to create a pointer to the starting address returned byReally rusty on c++, but I think the best way is (assuming you have a type defined) for the whatever your trying to read you should be able to point another casted pointer to the base pointer and then do a for loop the ++ operator should increment the size of the cast type and then you can read that data where ever you need to
Code:
BYTE value = *reinterpret_cast<int*>(pData); //get value at pointed to memory address
But the memory address returned in value is not in proper format to create a new pointer pointing to that starting address so that I can finally read the first BYTE of packet data at that starting address
How can I get a pointer to point to that starting address of the audio frame?
Similar threads
- Replies
- 0
- Views
- 1K
- Replies
- 0
- Views
- 2K
- Replies
- 0
- Views
- 5K