int DSoundAudioBackend::RunThread() { if (FAILED(DirectSoundCreate8(0, &ds_, 0))) { ds_ = NULL; threadData_ = 2; return 1; } ds_->SetCooperativeLevel(window_, DSSCL_PRIORITY); if (!CreateBuffer()) { ds_->Release(); ds_ = NULL; threadData_ = 2; return 1; } soundSyncEvent_ = CreateEvent(0, false, false, 0); InitializeCriticalSection(&soundCriticalSection); DWORD num1; short *p1; dsBuffer_->Lock(0, bufferSize_, (void **)&p1, &num1, 0, 0, 0); memset(p1, 0, num1); dsBuffer_->Unlock(p1, num1, 0, 0); totalRenderedBytes_ = -bufferSize_; setCurrentThreadName("DSound"); currentPos_ = 0; lastPos_ = 0; dsBuffer_->Play(0,0,DSBPLAY_LOOPING); while (!threadData_) { EnterCriticalSection(&soundCriticalSection); dsBuffer_->GetCurrentPosition((DWORD *)¤tPos_, 0); int numBytesToRender = RoundDown128(ModBufferSize(currentPos_ - lastPos_)); if (numBytesToRender >= 256) { int numBytesRendered = 4 * (*callback_)(realtimeBuffer_, numBytesToRender >> 2, 16, 44100, 2); //We need to copy the full buffer, regardless of what the mixer claims to have filled //If we don't do this then the sound will loop if the sound stops and the mixer writes only zeroes numBytesRendered = numBytesToRender; WriteDataToBuffer(lastPos_, (char *) realtimeBuffer_, numBytesRendered); currentPos_ = ModBufferSize(lastPos_ + numBytesRendered); totalRenderedBytes_ += numBytesRendered; lastPos_ = currentPos_; } LeaveCriticalSection(&soundCriticalSection); WaitForSingleObject(soundSyncEvent_, MAXWAIT); }
bool VDAudioOutputDirectSoundW32::InitDirectSound() { mDSBufferSize = mBufferSize * 2; mDSBufferSizeHalf = mBufferSize; // attempt to load DirectSound library mhmodDS = LoadLibraryA("dsound"); if (!mhmodDS) return false; typedef HRESULT (WINAPI *tpDirectSoundCreate8)(LPCGUID, LPDIRECTSOUND8 *, LPUNKNOWN); tpDirectSoundCreate8 pDirectSoundCreate8 = (tpDirectSoundCreate8)GetProcAddress(mhmodDS, "DirectSoundCreate8"); if (!pDirectSoundCreate8) { VDDEBUG("VDAudioOutputDirectSound: Cannot find DirectSoundCreate8 entry point!\n"); return false; } // attempt to create DirectSound object HRESULT hr = pDirectSoundCreate8(NULL, &mpDS8, NULL); if (FAILED(hr)) { VDDEBUG("VDAudioOutputDirectSound: Failed to create DirectSound object! hr=%08x\n", hr); return false; } // Set cooperative level. // // From microsoft.public.win32.programmer.directx.audio, by an SDE on the Windows AV team: // // "I can't speak for all DirectX components but DirectSound does not // subclass the window procedure. It simply uses the window handle to // determine (every 1/2 second, in a seperate thread) if the window that // corresponds to the handle has the focus (Actually, it is slightly more // complicated than that, but that is close enough for this discussion). // You can feel free to use the desktop window or console window for the // window handle if you are going to create GLOBAL_FOCUS buffers." // // Alright, you guys said we could do it! // hr = mpDS8->SetCooperativeLevel(GetDesktopWindow(), DSSCL_PRIORITY); if (FAILED(hr)) { VDDEBUG("VDAudioOutputDirectSound: Failed to set cooperative level! hr=%08x\n", hr); return false; } return true; }
s32 Init() { CoInitializeEx( NULL, COINIT_MULTITHREADED ); // // Initialize DSound // GUID cGuid; try { if( m_Device.empty() ) throw std::runtime_error( "screw it" ); // Convert from unicode to ANSI: char guid[256]; sprintf_s( guid, "%S", m_Device.c_str() ); if( (FAILED(GUIDFromString( guid, &cGuid ))) || FAILED( DirectSoundCreate8(&cGuid,&dsound,NULL) ) ) throw std::runtime_error( "try again?" ); } catch( std::runtime_error& ) { // if the GUID failed, just open up the default dsound driver: if( FAILED(DirectSoundCreate8(NULL,&dsound,NULL) ) ) throw std::runtime_error( "DirectSound failed to initialize!" ); } if( FAILED(dsound->SetCooperativeLevel(GetDesktopWindow(),DSSCL_PRIORITY)) ) throw std::runtime_error( "DirectSound Error: Cooperative level could not be set." ); // Determine the user's speaker configuration, and select an expansion option as needed. // FAIL : Directsound doesn't appear to support audio expansion >_< DWORD speakerConfig = 2; //dsound->GetSpeakerConfig( &speakerConfig ); IDirectSoundBuffer* buffer_; DSBUFFERDESC desc; // Set up WAV format structure. memset(&wfx, 0, sizeof(WAVEFORMATEX)); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nSamplesPerSec = SampleRate; wfx.nChannels = (WORD)speakerConfig; wfx.wBitsPerSample = 16; wfx.nBlockAlign = 2*(WORD)speakerConfig; wfx.nAvgBytesPerSec = SampleRate * wfx.nBlockAlign; wfx.cbSize = 0; uint BufferSizeBytes = BufferSize * wfx.nBlockAlign; // Set up DSBUFFERDESC structure. memset(&desc, 0, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY; desc.dwBufferBytes = BufferSizeBytes * m_NumBuffers; desc.lpwfxFormat = &wfx; // Try a hardware buffer first, and then fall back on a software buffer if // that one fails. desc.dwFlags |= m_UseHardware ? DSBCAPS_LOCHARDWARE : DSBCAPS_LOCSOFTWARE; desc.dwFlags |= m_DisableGlobalFocus ? DSBCAPS_STICKYFOCUS : DSBCAPS_GLOBALFOCUS; if( FAILED(dsound->CreateSoundBuffer(&desc, &buffer_, 0) ) ) { if( m_UseHardware ) { desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE; desc.dwFlags |= m_DisableGlobalFocus ? DSBCAPS_STICKYFOCUS : DSBCAPS_GLOBALFOCUS; if( FAILED(dsound->CreateSoundBuffer(&desc, &buffer_, 0) ) ) throw std::runtime_error( "DirectSound Error: Buffer could not be created." ); } throw std::runtime_error( "DirectSound Error: Buffer could not be created." ); } if( FAILED(buffer_->QueryInterface(IID_IDirectSoundBuffer8,(void**)&buffer)) || buffer == NULL ) throw std::runtime_error( "DirectSound Error: Interface could not be queried." ); buffer_->Release(); verifyc( buffer->QueryInterface(IID_IDirectSoundNotify8,(void**)&buffer_notify) ); DSBPOSITIONNOTIFY not[MAX_BUFFER_COUNT]; for(uint i=0;i<m_NumBuffers;i++) { buffer_events[i] = CreateEvent(NULL,FALSE,FALSE,NULL); not[i].dwOffset = (wfx.nBlockAlign + BufferSizeBytes*(i+1)) % desc.dwBufferBytes; not[i].hEventNotify = buffer_events[i]; } buffer_notify->SetNotificationPositions(m_NumBuffers,not); LPVOID p1=0,p2=0; DWORD s1=0,s2=0; verifyc(buffer->Lock(0,desc.dwBufferBytes,&p1,&s1,&p2,&s2,0)); assert(p2==0); memset(p1,0,s1); verifyc(buffer->Unlock(p1,s1,p2,s2)); //Play the buffer ! verifyc(buffer->Play(0,0,DSBPLAY_LOOPING)); // Start Thread myLastWrite = 0; dsound_running = true; thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RThread<StereoOut16>,this,0,&tid); SetThreadPriority(thread,THREAD_PRIORITY_ABOVE_NORMAL); return 0; }
s32 Init() { numBuffers = Config_DSoundOut.NumBuffers; // // Initialize DSound // GUID cGuid; try { if( Config_DSoundOut.Device.empty() ) throw std::runtime_error( "screw it" ); // Convert from unicode to ANSI: char guid[256]; sprintf_s( guid, "%S", Config_DSoundOut.Device.c_str() ); if( (FAILED(GUIDFromString( guid, &cGuid ))) || FAILED( DirectSoundCreate8(&cGuid,&dsound,NULL) ) ) throw std::runtime_error( "try again?" ); } catch( std::runtime_error& ) { // if the GUID failed, just open up the default dsound driver: if( FAILED(DirectSoundCreate8(NULL,&dsound,NULL) ) ) throw std::runtime_error( "DirectSound failed to initialize!" ); } if( FAILED(dsound->SetCooperativeLevel(GetDesktopWindow(),DSSCL_PRIORITY)) ) throw std::runtime_error( "DirectSound Error: Cooperative level could not be set." ); // Determine the user's speaker configuration, and select an expansion option as needed. // FAIL : Directsound doesn't appear to support audio expansion >_< DWORD speakerConfig = 2; //dsound->GetSpeakerConfig( &speakerConfig ); IDirectSoundBuffer* buffer_; DSBUFFERDESC desc; // Set up WAV format structure. memset(&wfx, 0, sizeof(WAVEFORMATEX)); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nSamplesPerSec = SampleRate; wfx.nChannels = (WORD)speakerConfig; wfx.wBitsPerSample = 16; wfx.nBlockAlign = 2*(WORD)speakerConfig; wfx.nAvgBytesPerSec = SampleRate * wfx.nBlockAlign; wfx.cbSize = 0; uint BufferSizeBytes = BufferSize * wfx.nBlockAlign; // Set up DSBUFFERDESC structure. memset(&desc, 0, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;// _CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; desc.dwBufferBytes = BufferSizeBytes * numBuffers; desc.lpwfxFormat = &wfx; desc.dwFlags |= DSBCAPS_LOCSOFTWARE; desc.dwFlags |= DSBCAPS_GLOBALFOCUS; if( FAILED(dsound->CreateSoundBuffer(&desc,&buffer_,0) ) ) throw std::runtime_error( "DirectSound Error: Interface could not be queried." ); if( FAILED(buffer_->QueryInterface(IID_IDirectSoundBuffer8,(void**)&buffer)) ) throw std::runtime_error( "DirectSound Error: Interface could not be queried." ); buffer_->Release(); verifyc( buffer->QueryInterface(IID_IDirectSoundNotify8,(void**)&buffer_notify) ); DSBPOSITIONNOTIFY not[MAX_BUFFER_COUNT]; for(u32 i=0;i<numBuffers;i++) { // [Air] note: wfx.nBlockAlign modifier was *10 -- seems excessive to me but maybe // it was needed for some quirky driver? Theoretically we want the notification as soon // as possible after the buffer has finished playing. buffer_events[i] = CreateEvent(NULL,FALSE,FALSE,NULL); not[i].dwOffset = (wfx.nBlockAlign + BufferSizeBytes*(i+1)) % desc.dwBufferBytes; not[i].hEventNotify = buffer_events[i]; } buffer_notify->SetNotificationPositions(numBuffers,not); LPVOID p1=0,p2=0; DWORD s1=0,s2=0; verifyc(buffer->Lock(0,desc.dwBufferBytes,&p1,&s1,&p2,&s2,0)); assert(p2==0); memset(p1,0,s1); verifyc(buffer->Unlock(p1,s1,p2,s2)); //Play the buffer ! verifyc(buffer->Play(0,0,DSBPLAY_LOOPING)); // Start Thread myLastWrite = 0; dsound_running = true; thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RThread<StereoOut16>,this,0,&tid); SetThreadPriority(thread,THREAD_PRIORITY_ABOVE_NORMAL); return 0; }
HRESULT DemoApp::Initialize() { HRESULT hr; //register window class WNDCLASSEX wcex = { sizeof(WNDCLASSEX) }; wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = DemoApp::WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = sizeof(LONG_PTR); wcex.hInstance = HINST_THISCOMPONENT; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = NULL; wcex.lpszMenuName = NULL; wcex.lpszClassName = L"App"; RegisterClassEx(&wcex); hr = CreateDeviceIndependentResources(); if (SUCCEEDED(hr)) { // Create the application window. m_hwnd = CreateWindow( L"App", L"달걀 채색 공장(201001622 이진용)", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1200, 600, NULL, NULL, HINST_THISCOMPONENT, this ); hr = m_hwnd ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { float length = 0; hr = m_wheelPath->ComputeLength( NULL, //no transform &length ); if (SUCCEEDED(hr) ) { m_Animation.SetStart(0); //start at beginning of path m_Animation.SetEnd(length); //length at end of path m_Animation.SetDuration(5.f ); //seconds ZeroMemory(&m_DwmTimingInfo, sizeof(m_DwmTimingInfo)); m_DwmTimingInfo.cbSize = sizeof(m_DwmTimingInfo); // Get the composition refresh rate. If the DWM isn't running, // get the refresh rate from GDI -- probably going to be 60Hz if (FAILED(DwmGetCompositionTimingInfo(NULL, &m_DwmTimingInfo))) { HDC hdc = GetDC(m_hwnd); m_DwmTimingInfo.rateCompose.uiDenominator = 1; m_DwmTimingInfo.rateCompose.uiNumerator = GetDeviceCaps(hdc, VREFRESH); ReleaseDC(m_hwnd, hdc); } ShowWindow(m_hwnd, SW_SHOWNORMAL); UpdateWindow(m_hwnd); } } if (SUCCEEDED(hr)) { float pLength = 0; hr = m_flyPath->ComputeLength( NULL, //no transform &pLength ); if (SUCCEEDED(hr) ) { m_linearAnimation.SetStart(0); //start at beginning of path m_linearAnimation.SetEnd(pLength); //length at end of path m_linearAnimation.SetDuration(10.f); //seconds ZeroMemory(&m_DwmTimingInfo, sizeof(m_DwmTimingInfo)); m_DwmTimingInfo.cbSize = sizeof(m_DwmTimingInfo); // Get the composition refresh rate. If the DWM isn't running, // get the refresh rate from GDI -- probably going to be 60Hz if (FAILED(DwmGetCompositionTimingInfo(NULL, &m_DwmTimingInfo))) { HDC hdc = GetDC(m_hwnd); m_DwmTimingInfo.rateCompose.uiDenominator = 1; m_DwmTimingInfo.rateCompose.uiNumerator = GetDeviceCaps(hdc, VREFRESH); ReleaseDC(m_hwnd, hdc); } ShowWindow(m_hwnd, SW_SHOWNORMAL); UpdateWindow(m_hwnd); } } } //장치 객체 생성 IDirectSound8* directSound; DirectSoundCreate8(NULL,&directSound, NULL); //협력레벨 지정 directSound->SetCooperativeLevel(m_hwnd,DSSCL_PRIORITY); //주버퍼 포맷 지정 DSBUFFERDESC dsbd; ZeroMemory(&dsbd,sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME; dsbd.dwBufferBytes = 0; dsbd.lpwfxFormat = NULL; //IDirectSoundBuffer* pDSBPrimary = NULL; directSound->CreateSoundBuffer(&dsbd, &pDSBPrimary, NULL); WAVEFORMATEX wfx; ZeroMemory(&wfx, sizeof(WAVEFORMATEX) ); wfx.wFormatTag = (WORD)WAVE_FORMAT_PCM; wfx.nChannels =(WORD)2; wfx.nSamplesPerSec = (DWORD)22050; wfx.wBitsPerSample = (WORD)16; wfx.nBlockAlign = (WORD)(wfx.wBitsPerSample / 8 * wfx.nChannels ); wfx.nAvgBytesPerSec = (DWORD)(wfx.nSamplesPerSec * wfx.nBlockAlign ); pDSBPrimary->SetFormat(&wfx); pDSBPrimary->Release(); //2차 버퍼 생성 BGM CWaveFile* pWaveFile = NULL; pWaveFile = new CWaveFile(); pWaveFile->Open( L".\\pokemonCenter.wav", NULL, WAVEFILE_READ ); //DSBUFFERDESC dsbd; ZeroMemory(&dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = DSBCAPS_CTRLVOLUME; dsbd.guid3DAlgorithm = GUID_NULL; dsbd.lpwfxFormat = pWaveFile->m_pwfx; dsbd.dwBufferBytes = pWaveFile->GetSize(); directSound->CreateSoundBuffer(&dsbd, &pDSBuffer, NULL); //이차버퍼에 데이터 채우기 sound = new CSound(&pDSBuffer, dsbd.dwBufferBytes, 1 , pWaveFile, 0 ); // pDSBuffer 위에 전역변수임 pDSBPrimary->SetVolume(scaledVolume); sound->Play(0,DSBPLAY_LOOPING); soundManager = new CSoundManager; if( ! soundManager->init(m_hwnd) ) return FALSE; int id; if (! soundManager->add(L".\\boss.wav", &id)) //id=0부터 시작함. return FALSE; if (! soundManager->add(L".\\storm.wav",&id)); return hr; }