Я пытаюсь захватить формы данных PCM с плавающей запятой с микрофона. Приложение запрашивает только небольшое количество выборок в каждом цикле (для частоты 20 000 Гц и размера кадра 0,003 с потребуется 60 выборок).
Я хотел бы установить размер буфера в зависимости от того, сколько мс интересует приложение, но кажется, что dwBufferBytes
должен быть определенного размера. Вместо этого я установил для него значение nAvgBytesPerSec и блокировал / копировал только 60 сэмплов каждый раз (даже если для чтения будет доступно гораздо больше данных)
Это правильный подход, или есть другой способ управления звуковым драйвером? Есть ли способ уменьшить размер буфера, чтобы дать мне столько данных, сколько запрашивает приложение? Я не хочу получить тонну звука
данные, если приложение хочет только 60 значений.
Используя этот подход, я, безусловно, столкнусь с проблемами, если буфер догонит мой (медленный) курсор чтения.
unsigned short channelNum = 2;
unsigned short bitsPerSample = 32;
unsigned long sampleRate = 20000;
unsigned short blockAlign = (channelNum * bitsPerSample) / 8;
unsigned long avgBytesPerSec = sampleRate * blockAlign;
WAVEFORMATEX wfx = { WAVE_FORMAT_IEEE_FLOAT, channelNum, sampleRate, avgBytesPerSec, blockAlign, bitsPerSample, 0 };
unsigned int mSampleBufferSize = 60; // 1400
DSCBUFFERDESC bufferDesc;
bufferDesc.dwSize = sizeof(DSCBUFFERDESC);
bufferDesc.dwFlags = 0;
bufferDesc.dwBufferBytes = wfx.nAvgBytesPerSec;
bufferDesc.dwReserved = 0;
bufferDesc.lpwfxFormat = &wfx;
bufferDesc.dwFXCount = 0;
bufferDesc.lpDSCFXDesc = NULL;
IDirectSoundCaptureBuffer *buffer = 0;
bool bufferRunning = false;
if (directSound && capture)
{
hr = capture->CreateCaptureBuffer(&bufferDesc, &buffer, NULL);
if (FAILED(hr))
std::cout << "SampleThread() -- Error creating DirectSoundCaptureBuffer " << endl;
else
{
hr = buffer->Start(DSCBSTART_LOOPING);
if (SUCCEEDED(hr)) {
bufferRunning = true;
}
}
}
void* primaryBuffer = NULL;
unsigned long primaryBufferSizeBytes = 0;
void* secondaryBuffer = NULL;
unsigned long secondaryBufferSize = 0;
bool mStopExecution = false;
unsigned long lastReadPosition = 0;if (directSound && capture && buffer)
{
while (!mStopExecution)
{
DWORD readPos;
WORD remainingSize = 0;
DWORD capturePos;
hr = buffer->GetCurrentPosition(&capturePos, &readPos);
if (FAILED(hr))
{
cout << "SampleThread() -- Error GetCurrentPosition" << endl;
return 0;
}buffer->Lock(lastReadPos, mSampleBufferSize, &primaryBuffer, &primaryBufferSizeBytes, &secondaryBuffer, &secondaryBufferSize, NULL);
memcpy(mBuffer, (float*)primaryBuffer, primaryBufferSizeBytes / sizeof(float));
// .... copy secondary buffer
hr = buffer->Unlock(primaryBuffer, primaryBufferSizeBytes, secondaryBuffer, secondaryBufferSize);
lastReadPosition = (lastReadPosition + mSampleBufferSize) % bufferDesc.dwBufferBytes;
}
}
Задача ещё не решена.
Других решений пока нет …