//----------------------------------------------------------------------------- // Name: CSoundManager::Initialize() // Desc: Initializes the IDirectSound object and also sets the primary buffer // format. This function must be called before any others. //----------------------------------------------------------------------------- HRESULT CSoundManager::Initialize( HWND hWnd, DWORD dwCoopLevel, DWORD dwPrimaryChannels, DWORD dwPrimaryFreq, DWORD dwPrimaryBitRate ) { HRESULT hr; SAFE_RELEASE( m_pDS ); // Create IDirectSound using the primary sound device if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) ) return DXTRACE_ERR( TEXT("DirectSoundCreate8"), hr ); // Set DirectSound coop level if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) ) return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr ); // Set primary buffer format if( FAILED( hr = SetPrimaryBufferFormat( dwPrimaryChannels, dwPrimaryFreq, dwPrimaryBitRate ) ) ) return DXTRACE_ERR( TEXT("SetPrimaryBufferFormat"), hr ); m_dwPrimaryChannels = dwPrimaryChannels; m_dwPrimaryFreq = dwPrimaryFreq; m_dwPrimaryBitRate = dwPrimaryBitRate; return S_OK; }
// //////////////////////////////////////////////////////////////////// // // //////////////////////////////////////////////////////////////////// bool DirectSound8Audio::VInitialize() { if(Audio::IsInitialized()) { return (true); } Audio::SetInitialized(false); Release(m_pDS); HRESULT hr; // Create IDirectSound using the primary sound device if(FAILED(hr = DirectSoundCreate8(NULL, &m_pDS, NULL))) { GF_LOG_TRACE_ERR("DirectSound8Audio::VInitialize()", "Failed to initialized the DirectSound interface"); return (false); } if(FAILED(hr = m_pDS->SetCooperativeLevel(m_hWnd, DSSCL_PRIORITY))) { GF_LOG_TRACE_ERR("DirectSound8Audio::VInitialize()", "Failed to set the coop level of the DirectSound interface"); return (false); } if(FAILED(hr = SetPrimaryBufferFormat(8, 44100, 16))) { GF_LOG_TRACE_ERR("DirectSound8Audio::VInitialize()", "Failed to set the primary buffer format of the DirectSound interface"); return (false); } Audio::SetInitialized(true); m_AllSamples.clear(); return (true); }
/* =============== idAudioHardwareWIN32::Initialize =============== */ bool idAudioHardwareWIN32::Initialize( void ) { int hr; bufferSize = 0; numSpeakers = 0; blockAlign = 0; SAFE_RELEASE( m_pDS ); // Create IDirectSound using the primary sound device if( FAILED( hr = DirectSoundCreate( NULL, &m_pDS, NULL ) )) { return false; } // Set primary buffer format SetPrimaryBufferFormat( PRIMARYFREQ, 16, idSoundSystemLocal::s_numberOfSpeakers.GetInteger() ); return true; }
bool CSoundManager::init(HWND hWnd) { // Set coop level to DSSCL_PRIORITY, if( FAILED( Initialize( hWnd, DSSCL_PRIORITY) ) ) { MessageBox( hWnd, L"Error initializing DirectSound. Sample will now exit.", L"DirectSound Sample", MB_OK | MB_ICONERROR ); return false; } // set primary buffer format to stereo, 22kHz and 16-bit output. if( FAILED( SetPrimaryBufferFormat( 2, 22050, 16 ) ) ) { MessageBox( hWnd, L"Error initializing DirectSound. Sample will now exit.", L"DirectSound Sample", MB_OK | MB_ICONERROR ); return false; } return true; }
HX_RESULT CHXAudioDeviceDS::_DoOpen(const HXAudioFormat* pFormat) { HX_RESULT theErr = HXR_FAIL; if(!m_hwnd || !m_hSoundDll) return theErr; // close open resources InternalClose() ; /* Get the IDirectSound interface */ HXBOOL bUsingDS8 = TRUE; FPDIRECTSOUNDCREATE fpCreateDS = (FPDIRECTSOUNDCREATE) ::GetProcAddress(m_hSoundDll, TEXT("DirectSoundCreate8") ); if(!fpCreateDS) { bUsingDS8 = FALSE; fpCreateDS = (FPDIRECTSOUNDCREATE) ::GetProcAddress(m_hSoundDll, TEXT("DirectSoundCreate")); if(!fpCreateDS) return theErr; } theErr = fpCreateDS(NULL, &m_pDSDev, NULL); if (FAILED(theErr)) return theErr; /* set the cooperative level. Because we want control over the format of the primary buffer (16 bit, multichannel!), we need DSSCL_PRIORITY. */ m_pDSDev->SetCooperativeLevel(m_hwnd, DSSCL_PRIORITY ); /* set the format of the primary buffer. This will fail on WDM systems (because the kernel mixer termines the primary buffer format), but is important on non-WDM systems. This might change the m_WaveFormat structure from a WAVE_FORMAT_EXTENSIBLE to a WAVEFORMATEX. Ignore the result. */ SetPrimaryBufferFormat() ; /* Now open a secondary buffer. */ DSBUFFERDESC bufferDesc; ::memset(&bufferDesc, 0, sizeof(DSBUFFERDESC)); bufferDesc.dwSize = sizeof(DSBUFFERDESC); bufferDesc.lpwfxFormat = m_pWaveFormat; // Manipulate the buffer size so that is is an exact multiple of the block size. // This will ensure that our write positions on the buffer are the same in every loop. // We need to do this so that we have fixed playback notification positions marking the end each write block. m_nBlocksPerBuffer = (m_pWaveFormat->nAvgBytesPerSec*BUFFER_TIME)/pFormat->uMaxBlockSize; m_ulTotalBuffer = pFormat->uMaxBlockSize*m_nBlocksPerBuffer; m_ulLoopTime = (double)m_ulTotalBuffer / (double)m_pWaveFormat->nAvgBytesPerSec; bufferDesc.dwBufferBytes = m_ulTotalBuffer ; bufferDesc.dwFlags = DSBCAPS_CTRLVOLUME | // so we can control the volume DSBCAPS_GETCURRENTPOSITION2 | // finer position reports DSBCAPS_CTRLPOSITIONNOTIFY | // have them reported here DSBCAPS_GLOBALFOCUS | // take control! DSBCAPS_STICKYFOCUS | #ifdef HELIX_FEATURE_AUDIO_DEVICE_HOOKS (bUsingDS8 && m_pWaveFormat->nChannels <= 2 && !m_bOpaqueFormat ? DSBCAPS_CTRLFX : 0); #else 0; #endif /* Again, try with WAVE_FORMAT_EXTENSIBLE first, but only if multichannel. */ theErr = !DS_OK ; if (m_pWaveFormat->nChannels > 2 || m_bOpaqueFormat) { if(!m_bOpaqueFormat) m_pWaveFormat->wFormatTag = WAVE_FORMAT_EXTENSIBLE; theErr = m_pDSDev->CreateSoundBuffer(&bufferDesc, &m_pSecondaryBuffer, NULL); } if (theErr != DS_OK && !m_bOpaqueFormat) { /* and if that fails, try WAVEFORMATEX */ m_pWaveFormat->wFormatTag = WAVE_FORMAT_PCM; theErr = m_pDSDev->CreateSoundBuffer(&bufferDesc, &m_pSecondaryBuffer, NULL); } /* call it a day and count our blessings. */ switch (theErr) { case DS_OK: theErr = HXR_OK; break; case DSERR_OUTOFMEMORY: theErr = HXR_OUTOFMEMORY; break; default: theErr = HXR_FAIL; break; } if (SUCCEEDED(theErr) && m_pSecondaryBuffer) { m_eState = E_DEV_OPENED; KillThreadAndEvent(); SetWindowLong(m_hwnd, GWL_USERDATA, (LONG)this); // Create the event to be signalled on playback position notifications and the thread to wait for those events to be signalled. m_hDSNotifyEvent = CreateEvent(NULL, TRUE, FALSE, kDSWaitEvent); // now set the notification positions for direct sound playback. IDirectSoundNotify* pNotify = NULL; m_pSecondaryBuffer->QueryInterface(IID_IDirectSoundNotify, (void**)&pNotify); if(pNotify && m_hDSNotifyEvent) { DSBPOSITIONNOTIFY* aPositionNotify = new DSBPOSITIONNOTIFY[m_nBlocksPerBuffer]; if(aPositionNotify) { for(int i = 0; i < m_nBlocksPerBuffer; i++) { aPositionNotify[i].dwOffset = i * pFormat->uMaxBlockSize; aPositionNotify[i].hEventNotify = m_hDSNotifyEvent; } } pNotify->SetNotificationPositions(m_nBlocksPerBuffer, aPositionNotify); delete[] aPositionNotify; DWORD dwWaitThreadID(0); m_hWaitThread = CreateThread(NULL, 0, EventThreadProc, (LPVOID)this, 0, &dwWaitThreadID); SetDebuggerThreadName(dwWaitThreadID, "DirectSound Audio Device Thread"); SetThreadPriority( m_hWaitThread, THREAD_PRIORITY_HIGHEST ); } HX_RELEASE(pNotify); m_pSecondaryBuffer->SetVolume(DSBVOLUME_MAX); m_pSecondaryBuffer->SetCurrentPosition(0); // detect whether we are playing remotely(via Remote Desktop) // disable audio device hook if it is to avoid poor audio quality int bRemoteSession = GetSystemMetrics(SM_REMOTESESSION); if(!bRemoteSession && bUsingDS8 && m_pWaveFormat->nChannels <= 2 && !m_bOpaqueFormat) { LoadDirectSoundFilter(); } } m_ulCurrPlayTime = 0; m_ulCurrLoopTime = 0; m_ulLoops = 0; // Setup converter to convert from samples/sec to milliseconds m_TSConverter.SetBase(m_pWaveFormat->nSamplesPerSec, 1000); return theErr; }
// Sets a general quality of playback (CPU time vs. fidelity) HRESULT DS3DSoundEngine::SetQuality(Quality quality) { HRESULT hr; // stop all playing sound buffers VirtualSoundList::iterator iterSound; for (iterSound = m_listActiveSounds.begin(); iterSound != m_listActiveSounds.end(); ++iterSound) { if ((*iterSound)->HasPlayingBuffer()) { hr = (*iterSound)->StopBuffer(); if (ZFailed(hr)) return hr; } } switch (quality) { case minQuality: hr = SetPrimaryBufferFormat(22050, 8, 1); if ((hr != DSERR_PRIOLEVELNEEDED) && ZFailed(hr)) return hr; m_nNumBuffersDesired = 8; m_nNumBuffersMax = 8; break; case midQuality: default: hr = SetPrimaryBufferFormat(22050, 16, 2); if ((hr != DSERR_PRIOLEVELNEEDED) && ZFailed(hr)) return hr; if (m_bAllowHardware) { m_nNumBuffersDesired = max(16, (int)m_dscaps.dwMaxHwMixingStreamingBuffers * 2 / 3); m_nNumBuffersMax = max(24, (int)m_dscaps.dwMaxHwMixingStreamingBuffers); } else { m_nNumBuffersDesired = 16; m_nNumBuffersMax = 24; } break; case maxQuality: hr = SetPrimaryBufferFormat(44100, 16, 2); if ((hr != DSERR_PRIOLEVELNEEDED) && ZFailed(hr)) return hr; if (m_bAllowHardware) { m_nNumBuffersDesired = max(24, (int)m_dscaps.dwMaxHwMixingStreamingBuffers - 8); m_nNumBuffersMax = max(32, (int)m_dscaps.dwMaxHwMixingStreamingBuffers); } else { m_nNumBuffersDesired = 24; m_nNumBuffersMax = 32; } break; } m_quality = quality; return S_OK; };