HRESULT SetCapturenotification(LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB){ #define cEvent 3 LPDIRECTSOUNDNOTIFY8 pDSBNotify; WAVEFORMATEX wfx; HANDLE rghEvent[cEvent]; DSBPOSITIONNOTIFY rgdsbpn[cEvent]; HRESULT hr; if (NULL == pDSCB) return E_INVALIDARG; if (FAILED(hr = pDSCB->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&pDSBNotify))){ return hr; } if (FAILED(hr = pDSCB->GetFormat(&wfx, sizeof(WAVEFORMATEX), NULL))) return hr; for (int i = 0; i< cEvent; ++i){ rghEvent[i] = CreateEvent(NULL, TRUE, FALSE, NULL); if (rghEvent[i] == NULL){ hr = GetLastError(); return hr; } } 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]; hr = pDSBNotify->SetNotificationPositions(cEvent, rgdsbpn); pDSBNotify->Release(); return hr; }
//设置播放通知,一般用处有二: //1. 通知程序写入下一段声音数据 //2. 通知做某一个操作 HRESULT SetStopNotification(HANDLE hEvent, LPDIRECTSOUNDBUFFER8 lpDsbSecondary){ LPDIRECTSOUNDNOTIFY8 lpDsNotify; DSBPOSITIONNOTIFY PositionNotify; HRESULT hr; if (SUCCEEDED(hr = lpDsbSecondary->QueryInterface(IID_IDirectSoundNotify8, (LPVOID*)lpDsNotify) )){ PositionNotify.dwOffset = DSBPN_OFFSETSTOP; PositionNotify.hEventNotify = hEvent; hr = lpDsNotify->SetNotificationPositions(1, &PositionNotify); lpDsNotify->Release(); } return hr; }
bool DirectSound::init(long sampleRate) { HRESULT hr; DWORD freq; DSBUFFERDESC dsbdesc; int i; hr = CoCreateInstance( CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER, IID_IDirectSound8, (LPVOID *)&pDirectSound ); if( hr != S_OK ) { systemMessage( IDS_CANNOT_CREATE_DIRECTSOUND, NULL, hr ); return false; } pDirectSound->Initialize( &DSDEVID_DefaultPlayback ); if( hr != DS_OK ) { systemMessage( IDS_CANNOT_CREATE_DIRECTSOUND, NULL, hr ); return false; } if( FAILED( hr = pDirectSound->SetCooperativeLevel( theApp.m_pMainWnd->GetSafeHwnd(), DSSCL_EXCLUSIVE ) ) ) { systemMessage( IDS_CANNOT_SETCOOPERATIVELEVEL, _T("Cannot SetCooperativeLevel %08x"), hr ); return false; } // Create primary sound buffer ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; if( dsoundDisableHardwareAcceleration ) { dsbdesc.dwFlags |= DSBCAPS_LOCSOFTWARE; } if( FAILED( hr = pDirectSound->CreateSoundBuffer( &dsbdesc, &dsbPrimary, NULL ) ) ) { systemMessage(IDS_CANNOT_CREATESOUNDBUFFER, _T("Cannot CreateSoundBuffer %08x"), hr); return false; } freq = sampleRate; // calculate the number of samples per frame first // then multiply it with the size of a sample frame (16 bit * stereo) soundBufferLen = ( freq / 60 ) * 4; soundBufferTotalLen = soundBufferLen * 10; soundNextPosition = 0; ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = freq; wfx.wBitsPerSample = 16; wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; if( FAILED( hr = dsbPrimary->SetFormat( &wfx ) ) ) { systemMessage( IDS_CANNOT_SETFORMAT_PRIMARY, _T("CreateSoundBuffer(primary) failed %08x"), hr ); return false; } // Create secondary sound buffer ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS; if( dsoundDisableHardwareAcceleration ) { dsbdesc.dwFlags |= DSBCAPS_LOCSOFTWARE; } dsbdesc.dwBufferBytes = soundBufferTotalLen; dsbdesc.lpwfxFormat = &wfx; if( FAILED( hr = pDirectSound->CreateSoundBuffer( &dsbdesc, &dsbSecondary, NULL ) ) ) { systemMessage( IDS_CANNOT_CREATESOUNDBUFFER, _T("CreateSoundBuffer(secondary) failed %08x"), hr ); return false; } if( FAILED( hr = dsbSecondary->SetCurrentPosition( 0 ) ) ) { systemMessage( 0, _T("dsbSecondary->SetCurrentPosition failed %08x"), hr ); return false; } if( SUCCEEDED( hr = dsbSecondary->QueryInterface( IID_IDirectSoundNotify8, (LPVOID*)&dsbNotify ) ) ) { dsbEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); DSBPOSITIONNOTIFY notify[10]; for( i = 0; i < 10; i++ ) { notify[i].dwOffset = i * soundBufferLen; notify[i].hEventNotify = dsbEvent; } if( FAILED( dsbNotify->SetNotificationPositions( 10, notify ) ) ) { dsbNotify->Release(); dsbNotify = NULL; CloseHandle(dsbEvent); dsbEvent = NULL; } } // Play primary buffer if( FAILED( hr = dsbPrimary->Play( 0, 0, DSBPLAY_LOOPING ) ) ) { systemMessage( IDS_CANNOT_PLAY_PRIMARY, _T("Cannot Play primary %08x"), hr ); return false; } return true; }
bool SoundRecoder::createBuffer(LPGUID guid) { //デバイスの作成 HMODULE library = LoadLibraryA("dsound.dll"); if(!library) return false; HRESULT (WINAPI *DirectSoundCaptureCreate8)(LPCGUID,LPDIRECTSOUNDCAPTURE8*,LPUNKNOWN) = (HRESULT (WINAPI *)(LPCGUID,LPDIRECTSOUNDCAPTURE8*,LPUNKNOWN)) GetProcAddress(library,"DirectSoundCaptureCreate8"); DirectSoundCaptureCreate8(guid,&m_soundCapture,NULL); FreeLibrary(library); //デバイスが作成できなかったら終了 if(!m_soundCapture) return false; if(m_soundCaptureBuffer) { m_soundCaptureBuffer->Release(); m_soundCaptureBuffer = NULL; } DSCBUFFERDESC dscbd; WAVEFORMATEX wfx = { WAVE_FORMAT_PCM, m_bufferChannel, m_bufferRate, m_bufferRate*m_bufferChannel*m_bufferBit/8, m_bufferChannel*m_bufferBit/8, m_bufferBit, 0 }; m_bufferSize = wfx.nAvgBytesPerSec*m_bufferMSec/1000; dscbd.dwSize = sizeof(DSCBUFFERDESC); dscbd.dwFlags = 0; dscbd.dwBufferBytes = m_bufferSize; dscbd.dwReserved = 0; dscbd.lpwfxFormat = &wfx; dscbd.dwFXCount = 0; dscbd.lpDSCFXDesc = NULL; m_latency = m_bufferSize / m_notifyCount; LPDIRECTSOUNDCAPTUREBUFFER soundBuffer = NULL; m_soundCapture->CreateCaptureBuffer(&dscbd, &soundBuffer, NULL); if(!soundBuffer) return false; soundBuffer->QueryInterface(IID_IDirectSoundCaptureBuffer8,(LPVOID*)&m_soundCaptureBuffer); soundBuffer->Release(); if(!m_soundCaptureBuffer) return false; INT i; for(i=0;i<m_notifyCount;i++) { m_positionNotify[i].dwOffset = (dscbd.dwBufferBytes /m_notifyCount)*i ; } LPDIRECTSOUNDNOTIFY8 dsNotify; m_soundCaptureBuffer->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&dsNotify); dsNotify->SetNotificationPositions(m_notifyCount, m_positionNotify); dsNotify->Release(); return true; }
bool FVoiceCaptureWindows::CreateNotifications(uint32 BufferSize) { bool bSuccess = true; LPDIRECTSOUNDNOTIFY8 NotifyInt = NULL; HRESULT hr = CV->VoiceCaptureBuffer8->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&NotifyInt); if (SUCCEEDED(hr)) { DSBPOSITIONNOTIFY NotifyEvents[NUM_EVENTS]; // Create events. for (int i = 0; i < NUM_EVENTS; i++) { CV->Events[i] = CreateEvent(NULL, true, false, NULL); if (CV->Events[i] == INVALID_HANDLE_VALUE) { UE_LOG(LogVoiceCapture, Warning, TEXT("Error creating sync event")); bSuccess = false; } } if (bSuccess) { // Evenly distribute notifications throughout the buffer uint32 NumSegments = NUM_EVENTS - 1; uint32 BufferSegSize = BufferSize / NumSegments; for (uint32 i = 0; i < NumSegments; i++) { NotifyEvents[i].dwOffset = ((i + 1) * BufferSegSize) - 1; NotifyEvents[i].hEventNotify = CV->Events[i]; } // when buffer stops NotifyEvents[STOP_EVENT].dwOffset = DSBPN_OFFSETSTOP; NotifyEvents[STOP_EVENT].hEventNotify = CV->Events[STOP_EVENT]; hr = NotifyInt->SetNotificationPositions(NUM_EVENTS, NotifyEvents); if (FAILED(hr)) { UE_LOG(LogVoiceCapture, Warning, TEXT("Failed to set notifications 0x%08x"), hr); bSuccess = false; } float BufferSegMs = BufferSegSize / ((CV->WavFormat.nSamplesPerSec / 1000.0) * (CV->WavFormat.wBitsPerSample / 8.0)); UE_LOG(LogVoiceCapture, Display, TEXT("%d notifications, every %d bytes [%f ms]"), NumSegments, BufferSegSize, BufferSegMs); } NotifyInt->Release(); } else { UE_LOG(LogVoiceCapture, Warning, TEXT("Failed to create voice notification interface 0x%08x"), hr); } if (!bSuccess) { for (int i = 0; i < NUM_EVENTS; i++) { if (CV->Events[i] != INVALID_HANDLE_VALUE) { CloseHandle(CV->Events[i]); CV->Events[i] = INVALID_HANDLE_VALUE; } } } return bSuccess; }