DirectSound захватывает гигабайты кадров вместо мегабайт

Я использую DirectSound для захвата звука моего рабочего стола, используя учебник из MSDN https://msdn.microsoft.com/en-us/library/windows/desktop/ee416968(v=vs.85).aspx

Проблема в том, что когда я начинаю захватывать, мой WAV-файл за несколько секунд достигает сотен МБ и даже ГБ. Когда я воспроизводю WAV-файл, 5 секунд захвата звука становятся 30 минутами, и тот же кадр звука Дублируется как 1000 раз. Я заметил, что WAIT_OBJECT_0 + 1 и 2 никогда не запускаются. Спасибо заранее.

bool captureSound = false;
wav_header wavFile; // the wav file
UINT totalData = 0;
LPDIRECTSOUNDCAPTURE8 capturer = NULL;
GUID guid = DSDEVID_DefaultCapture;
HRESULT err;
DSCBUFFERDESC dscbd;
LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB8;
DWORD g_dwNextCaptureOffset = 0;
DWORD g_dwCaptureBufferSize = 0;
DWORD g_dwNotifySize = 0;

#define cEvents  3

WAVEFORMATEX         wfx;
HANDLE     rghEvent[cEvents] = {0,0,0};
DSBPOSITIONNOTIFY  rgdsbpn[cEvents];

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR    lpCmdLine,
_In_ int       nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
BOOL  bDone;

// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_WIN32PROJECT2, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32PROJECT2));bDone = FALSE;
// Main message loop:
while( !bDone ) {
dwResult = MsgWaitForMultipleObjects( 3, rghEvent,
FALSE, INFINITE, QS_ALLEVENTS );
switch( dwResult ) {
case WAIT_OBJECT_0 + 0:
if(FAILED(RecordCapturedData())) MessageBox(NULL,TEXT("Error!"), TEXT("Error"), MB_OK);
break;
case WAIT_OBJECT_0 + 1:
if(FAILED(RecordCapturedData())) MessageBox(NULL,TEXT("Error!"), TEXT("Error"), MB_OK);
break;
case WAIT_OBJECT_0 + 2:
if(FAILED(RecordCapturedData())) MessageBox(NULL,TEXT("Error!"), TEXT("Error"), MB_OK);
break;
case WAIT_OBJECT_0 + 3:
//MessageBox(NULL,TEXT("wait3"), TEXT("Error"), MB_OK);
// Windows messages are available
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if( msg.message == WM_QUIT )
bDone = TRUE;
}
break;
}
}

//CloseHandle(rghEvent);

return (int) msg.wParam;
}LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;

switch (message)
{
case WM_COMMAND:
wmId    = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_CAPTURESOUND:
captureSound = true;
if (FAILED(createWav(&wavFile)))
{
closeWav(wavFile.pFile);
MessageBox(NULL,TEXT("Error creating the sound file!"), TEXT("Error"), MB_OK);
}

// add the WAV header
for(int i = 0; i < 4; i++) {
fputc(wavFile.riff_header[i], wavFile.pFile);
}
fwrite((char*)&wavFile.wav_size,sizeof(int),1,wavFile.pFile);
for(int i = 0; i < 4; i++) {
fputc(wavFile.wave_header[i], wavFile.pFile);
}
for(int i = 0; i < 4; i++) {
fputc(wavFile.fmt_header[i], wavFile.pFile);
}
fwrite((const char*)&wavFile.fmt_chunk_size,4,1,wavFile.pFile);
fwrite((const char*)&wavFile.audio_format,2,1,wavFile.pFile);
fwrite((const char*)&wavFile.num_channels,2,1,wavFile.pFile);
fwrite((const char*)&wavFile.sample_rate,4,1,wavFile.pFile);
fwrite((const char*)&wavFile.byte_rate,4,1,wavFile.pFile);
fwrite((const char*)&wavFile.sample_alignment,2,1,wavFile.pFile);
fwrite((const char*)&wavFile.bit_depth,2,1,wavFile.pFile);
for(int i = 0; i < 4; i++) {
fputc(wavFile.data_header[i], wavFile.pFile);
}
fwrite((const char*)&wavFile.data_bytes,4,1,wavFile.pFile);

/* Use DirectSoundCaptureCreate8() to create and initialize an object and get the pointer (pDSC8) to IDirectSoundCapture8 */
if(FAILED(DirectSoundCaptureCreate8(&guid, &capturer, NULL))) {
ErrorExit(TEXT("DirectSoundCaptureCreate8"));
}

/* Use the method CreateCaptureBuffer() of IDirectSoundCapture8(pDSC8->CreateSoundBuffer()) to create
and initialize an object and get the  pointer (pDSCB) to IDirectSoundCaptureBuffer. */
if(FAILED(CreateCaptureBuffer(capturer,&pDSCB8))) {
ErrorExit(TEXT("CreateCaptureBuffer"));
}

/* Use the method QueryInterface of  IDirectSoundCaptureBuffer8(pDSCB8->QueryInterface()) to get a pointer(lpDsNotify) to the interface IDirectSoundNotify8. */
if(FAILED(SetCaptureNotifications(pDSCB8))) {
ErrorExit(TEXT("SetCaptureNotifications"));
}

/* Start capturing */
if(FAILED(pDSCB8->Start( DSCBSTART_LOOPING ) ) )
ErrorExit(TEXT("Start"));
else MessageBox(NULL,TEXT("Started capturing!"), TEXT("Good"), MB_OK);
break;
case IDM_OPRESTE:
captureSound = false;

// Stop the buffer, and read any data that was not
// caught by a notification

if( FAILED(pDSCB8->Stop() ) )
ErrorExit(TEXT("Stop"));

if(FAILED(RecordCapturedData())) MessageBox(NULL,TEXT("ERROR "), TEXT("Error"), MB_OK);/* Update the fields in the WAV header and close the file */
fseek (wavFile.pFile, 4 , SEEK_SET );
wavFile.wav_size += totalData;
fwrite((char*)&wavFile.wav_size,sizeof(int),1,wavFile.pFile);

wavFile.data_bytes += totalData;
fseek (wavFile.pFile, 40 , SEEK_SET );
fwrite((char*)&wavFile.data_bytes,sizeof(int),1,wavFile.pFile);

closeWav(wavFile.pFile);
break;
case IDM_EXIT:
DestroyWindow(hWnd); // POSTS THE MESSAGE WM_DESTROY TO DESTROY THE CREATED WINDOW.
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_CREATE:
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

HRESULT CreateCaptureBuffer(LPDIRECTSOUNDCAPTURE8 pDSC,
LPDIRECTSOUNDCAPTUREBUFFER8* ppDSCB8)
{
HRESULT hr;
DSCBUFFERDESC               dscbd;
LPDIRECTSOUNDCAPTUREBUFFER  pDSCB;

// Set up WAVEFORMATEX for 44.1 kHz 16-bit stereo.
WAVEFORMATEX                wfx =
{WAVE_FORMAT_PCM, wavFile.num_channels, wavFile.sample_rate, wavFile.byte_rate, wavFile.sample_alignment, wavFile.bit_depth, 0};
// wFormatTag, nChannels, nSamplesPerSec, mAvgBytesPerSec,
// nBlockAlign, wBitsPerSample, cbSize

if ((NULL == pDSC) || (NULL == ppDSCB8)) return E_INVALIDARG;
dscbd.dwSize = sizeof(DSCBUFFERDESC);
dscbd.dwFlags = 0;
dscbd.dwBufferBytes = wfx.nAvgBytesPerSec;
dscbd.dwReserved = 0;
dscbd.lpwfxFormat = &wfx;
dscbd.dwFXCount = 0;
dscbd.lpDSCFXDesc = NULL;

g_dwNotifySize = MAX( 1024, wavFile.byte_rate / 8 );
g_dwNotifySize -= g_dwNotifySize % wavFile.sample_alignment;
g_dwCaptureBufferSize = g_dwNotifySize * 3;

if (SUCCEEDED(hr = pDSC->CreateCaptureBuffer(&dscbd, &pDSCB, NULL)))
{
/* Use the method QueryInterface of  IDirectSoundCaptureBuffer(pDSCB->QueryInterface()) to get a
pointer(pDSCB8) to the interface IDirectSoundCaptureBuffer8 */
hr = pDSCB->QueryInterface(IID_IDirectSoundCaptureBuffer8, (LPVOID*)ppDSCB8);
pDSCB->Release();}
return hr;
}

HRESULT SetCaptureNotifications(LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB)
{
LPDIRECTSOUNDNOTIFY8 pDSNotify;
HRESULT    hr;

if (NULL == pDSCB) return E_INVALIDARG;
if (FAILED(hr = pDSCB->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&pDSNotify)))
{
return hr;
}
if (FAILED(hr = pDSCB->GetFormat(&wfx, sizeof(WAVEFORMATEX), NULL)))
{
return hr;
}

// Create events.
for (int i = 0; i < cEvents; ++i)
{
rghEvent[i] = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == rghEvent[i])
{
hr = GetLastError();
return hr;
}
}

// Describe notifications.

rgdsbpn[0].dwOffset = (wfx.nAvgBytesPerSec/2) -1;
rgdsbpn[0].hEventNotify = rghEvent[0];

rgdsbpn[1].dwOffset = wfx.nAvgBytesPerSec - 1;
rgdsbpn[1].hEventNotify = rghEvent[1];

rgdsbpn[2].dwOffset = DSBPN_OFFSETSTOP;
rgdsbpn[2].hEventNotify = rghEvent[2];

/* Use the SetNotificationPositions() of IDirectSoundNotify8(lpDsNotify->SetNotificationPositions())
to set the notification buffer positions */

hr = pDSNotify->SetNotificationPositions(cEvents, rgdsbpn);
pDSNotify->Release();
return hr;
}

HRESULT RecordCapturedData()
{
HRESULT hr;
VOID* pbCaptureData  = NULL;
DWORD dwCaptureLength;
VOID* pbCaptureData2 = NULL;
DWORD dwCaptureLength2;
VOID* pbPlayData   = NULL;
UINT  dwDataWrote;
DWORD dwReadPos;
LONG lLockSize;

if (NULL == pDSCB8)
MessageBox(NULL,TEXT("Empty buffer!"), TEXT("Error"), MB_OK);
if (NULL == wavFile.pFile)
MessageBox(NULL,TEXT("Empty .wav file!"), TEXT("Error"), MB_OK);

if (FAILED (hr = pDSCB8->GetCurrentPosition(
NULL, &dwReadPos)))
MessageBox(NULL,TEXT("Failed to get current position!"), TEXT("Error"), MB_OK);

// Lock everything between the private cursor
// and the read cursor, allowing for wraparound.

lLockSize = dwReadPos - g_dwNextCaptureOffset;
if( lLockSize < 0 ) lLockSize += g_dwCaptureBufferSize;

// Block align lock size so that we are always write on a boundary
//lLockSize -= (lLockSize % g_dwNotifySize);

if( lLockSize == 0 ) return S_FALSE;

if (FAILED(hr = pDSCB8->Lock(
g_dwNextCaptureOffset, lLockSize,
&pbCaptureData, &dwCaptureLength,
&pbCaptureData2, &dwCaptureLength2, 0L)))
MessageBox(NULL,TEXT("Lock failed!"), TEXT("Error"), MB_OK);

// Write the data. This is done in two steps
// to account for wraparound.

if (FAILED( addData(&wavFile, (BYTE*)pbCaptureData, dwCaptureLength, &dwDataWrote)))
MessageBox(NULL,TEXT("Error writting to the file!"), TEXT("Error"), MB_OK);

if (pbCaptureData2 != NULL)
{
if (FAILED( addData(&wavFile, (BYTE*)pbCaptureData2, dwCaptureLength2, &dwDataWrote)))
MessageBox(NULL,TEXT("Error writting to the file 2!"), TEXT("Error"), MB_OK);
}

// Unlock the capture buffer.

pDSCB8->Unlock( pbCaptureData, dwCaptureLength,
pbCaptureData2, dwCaptureLength2  );

// Move the capture offset forward.

g_dwNextCaptureOffset += dwCaptureLength;
g_dwNextCaptureOffset %= g_dwCaptureBufferSize;
g_dwNextCaptureOffset += dwCaptureLength2;
g_dwNextCaptureOffset %= g_dwCaptureBufferSize;

totalData += (dwCaptureLength + dwCaptureLength2);
return S_OK;
}

Wav Writer Утилита

#include "stdafx.h"#include "Wav.h"
HRESULT createWav(wav_header* pWav) {
pWav->pFile = fopen("sound.wav","w");
if(pWav->pFile == NULL) {
return 0;
}
strcpy(pWav->riff_header, "RIFF");
strcpy(pWav->wave_header, "WAVE");
strcpy(pWav->fmt_header, "fmt ");
pWav->fmt_chunk_size = 16;
pWav->audio_format = 1;
pWav->num_channels = 2;
pWav->sample_rate = 44100; // 44.1 KHz - CD-quality audio
pWav->bit_depth = 16; // Bits per Sample – The number of bits available for one sample.
pWav->sample_alignment = pWav->num_channels * (pWav->bit_depth)/8; // This is the number of bytes in a frame
pWav->byte_rate = pWav->sample_rate * pWav->sample_alignment; // number of bytes per second captured
strcpy(pWav->data_header, "data");
pWav->data_bytes = 0; // n * frames , n = 0 empty data default, to be updated each time new data is added
pWav->wav_size = 36 + pWav->data_bytes; // to be updated each time new data is added

return S_OK;
}

HRESULT closeWav(FILE * pFile) {
fclose(pFile);
return S_OK;
}

HRESULT addData(wav_header* pWav, VOID* data,UINT dataLength, UINT* dataWrote) {
// set the positon back at the end of the file
fseek (pWav->pFile, 0 , SEEK_END );
*dataWrote = fwrite((const char*)data,sizeof(byte),(size_t)dataLength, pWav->pFile);
return S_OK;
}

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector