//----------------------------------------------------------------------------- // Name: OnOpenSoundFile() // Desc: Called when the user requests to open a sound file //----------------------------------------------------------------------------- VOID OnOpenSoundFile( HWND hDlg ) { GUID guid3DAlgorithm = GUID_NULL; int nResult; HRESULT hr; static TCHAR strFileName[MAX_PATH] = TEXT(""); static TCHAR strPath[MAX_PATH] = TEXT(""); // Setup the OPENFILENAME structure OPENFILENAME ofn = { sizeof(OPENFILENAME), hDlg, NULL, TEXT("Wave Files\0*.wav\0All Files\0*.*\0\0"), NULL, 0, 1, strFileName, MAX_PATH, NULL, 0, strPath, TEXT("Open Sound File"), OFN_FILEMUSTEXIST|OFN_HIDEREADONLY, 0, 0, TEXT(".wav"), 0, NULL, NULL }; // Get the default media path (something like C:\WINDOWS\MEDIA) if( '\0' == strPath[0] ) { GetWindowsDirectory( strPath, MAX_PATH ); if( strcmp( &strPath[strlen(strPath)], TEXT("\\") ) ) strcat( strPath, TEXT("\\") ); strcat( strPath, TEXT("MEDIA") ); } if( g_pSound ) { g_pSound->Stop(); g_pSound->Reset(); } // Update the UI controls to show the sound as loading a file EnableWindow( GetDlgItem( hDlg, IDC_PLAY ), FALSE); EnableWindow( GetDlgItem( hDlg, IDC_STOP ), FALSE); SetDlgItemText( hDlg, IDC_STATUS, TEXT("Loading file...") ); // Stop the timer while dialogs are displayed g_bAllowMovementTimer = FALSE; // Display the OpenFileName dialog. Then, try to load the specified file if( TRUE != GetOpenFileName( &ofn ) ) { SetDlgItemText( hDlg, IDC_STATUS, TEXT("Load aborted.") ); g_bAllowMovementTimer = TRUE; return; } SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") ); // Free any previous sound, and make a new one SAFE_DELETE( g_pSound ); CWaveFile waveFile; waveFile.Open( strFileName, NULL, WAVEFILE_READ ); WAVEFORMATEX* pwfx = waveFile.GetFormat(); if( pwfx == NULL ) { SetDlgItemText( hDlg, IDC_STATUS, TEXT("Invalid wave file format.") ); return; } if( pwfx->nChannels > 1 ) { // Too many channels in wave. Sound must be mono when using DSBCAPS_CTRL3D SetDlgItemText( hDlg, IDC_STATUS, TEXT("Wave file must be mono for 3D control.") ); SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") ); return; } if( pwfx->wFormatTag != WAVE_FORMAT_PCM ) { // Sound must be PCM when using DSBCAPS_CTRL3D SetDlgItemText( hDlg, IDC_STATUS, TEXT("Wave file must be PCM for 3D control.") ); SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") ); return; } // Get the software DirectSound3D emulation algorithm to use // Ask the user for this sample, so display the algorithm dialog box. nResult = (int)DialogBox( NULL, MAKEINTRESOURCE(IDD_3D_ALGORITHM), NULL, AlgorithmDlgProc ); switch( nResult ) { case -1: // User canceled dialog box SetDlgItemText( hDlg, IDC_STATUS, TEXT("Load aborted.") ); SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") ); return; case 0: // User selected DS3DALG_NO_VIRTUALIZATION guid3DAlgorithm = DS3DALG_NO_VIRTUALIZATION; break; case 1: // User selected DS3DALG_HRTF_FULL guid3DAlgorithm = DS3DALG_HRTF_FULL; break; case 2: // User selected DS3DALG_HRTF_LIGHT guid3DAlgorithm = DS3DALG_HRTF_LIGHT; break; } // Load the wave file into a DirectSound buffer hr = g_pSoundManager->Create( &g_pSound, strFileName, DSBCAPS_CTRL3D, guid3DAlgorithm ); if( FAILED( hr ) || hr == DS_NO_VIRTUALIZATION ) { DXTRACE_ERR_NOMSGBOX( TEXT("Create"), hr ); if( DS_NO_VIRTUALIZATION == hr ) { MessageBox( hDlg, "The 3D virtualization algorithm requested is not supported under this " "operating system. It is available only on Windows 2000, Windows ME, and Windows 98 with WDM " "drivers and beyond. Creating buffer with no virtualization.", "DirectSound Sample", MB_OK ); } // Unknown error, but not a critical failure, so just update the status SetDlgItemText( hDlg, IDC_FILENAME, TEXT("Could not create sound buffer.") ); return; } // Get the 3D buffer from the secondary buffer if( FAILED( hr = g_pSound->Get3DBufferInterface( 0, &g_pDS3DBuffer ) ) ) { DXTRACE_ERR( TEXT("Get3DBufferInterface"), hr ); SetDlgItemText( hDlg, IDC_STATUS, TEXT("Could not get 3D buffer.") ); SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") ); return; } // Get the 3D buffer parameters g_dsBufferParams.dwSize = sizeof(DS3DBUFFER); g_pDS3DBuffer->GetAllParameters( &g_dsBufferParams ); // Set new 3D buffer parameters g_dsBufferParams.dwMode = DS3DMODE_HEADRELATIVE; g_pDS3DBuffer->SetAllParameters( &g_dsBufferParams, DS3D_IMMEDIATE ); DSBCAPS dsbcaps; ZeroMemory( &dsbcaps, sizeof(DSBCAPS) ); dsbcaps.dwSize = sizeof(DSBCAPS); LPDIRECTSOUNDBUFFER pDSB = g_pSound->GetBuffer( 0 ); pDSB->GetCaps( &dsbcaps ); if( ( dsbcaps.dwFlags & DSBCAPS_LOCHARDWARE ) != 0 ) SetDlgItemText( hDlg, IDC_STATUS, TEXT("File loaded using hardware mixing.") ); else SetDlgItemText( hDlg, IDC_STATUS, TEXT("File loaded using software mixing.") ); // Update the UI controls to show the sound as the file is loaded SetDlgItemText( hDlg, IDC_FILENAME, strFileName ); EnablePlayUI( hDlg, TRUE ); g_bAllowMovementTimer = TRUE; // Remember the path for next time strcpy( strPath, strFileName ); char* strLastSlash = strrchr( strPath, '\\' ); strLastSlash[0] = '\0'; // Set the slider positions SetSlidersPos( hDlg, 0.0f, 0.0f, ORBIT_MAX_RADIUS, ORBIT_MAX_RADIUS*2.0f ); OnSliderChanged( hDlg ); }
//----------------------------------------------------------------------------- // Name: OnPlaySound() // Desc: User hit the "Play" button //----------------------------------------------------------------------------- HRESULT OnPlaySound( HWND hDlg ) { HRESULT hr; DWORD dwCreationFlags; DWORD dwResults; LPDIRECTSOUNDBUFFER pDSB = NULL; LPDIRECTSOUNDBUFFER8 pDSB8 = NULL; BOOL bLooped = ( IsDlgButtonChecked( hDlg, IDC_LOOP_CHECK ) == BST_CHECKED ); // We would only use CTRLFX control on dsound buffer dwCreationFlags = DSBCAPS_CTRLFX; // Free any previous sound and FXs SAFE_RELEASE( g_pIGargle ); SAFE_DELETE( g_pSound ); // Since the user can change the focus before the sound is played, // we need to create the sound buffer every time the play button is pressed // Load the wave file into a DirectSound buffer if( FAILED( hr = g_pSoundManager->Create( &g_pSound, g_strWaveFileName, dwCreationFlags, GUID_NULL ) ) ) { // Not a critical failure, so just update the status DXTRACE_ERR_NOMSGBOX( TEXT("Create"), hr ); if( hr == DSERR_BUFFERTOOSMALL ) { // DSERR_BUFFERTOOSMALL will be returned if the buffer is // less than DSBSIZE_FX_MIN (100ms) and the buffer is created // with DSBCAPS_CTRLFX. SetDlgItemText( hDlg, IDC_STATUS, TEXT("Wave file is too short (less than 100ms) for effect processing.") ); } else { SetDlgItemText( hDlg, IDC_STATUS, TEXT("Could not create sound buffer.") ); } return S_FALSE; } // Query IDirectSoundBuffer8 interface pDSB = g_pSound->GetBuffer( 0 ); if( FAILED( hr = pDSB->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*) &pDSB8 ) ) ) return DXTRACE_ERR( TEXT("QueryInterface"), hr ); // Set gargle effect on the IDirectSoundBuffer8 DSEFFECTDESC dsed; ZeroMemory( &dsed, sizeof(DSEFFECTDESC) ); dsed.dwSize = sizeof(DSEFFECTDESC); dsed.dwFlags = 0; dsed.guidDSFXClass = GUID_DSFX_STANDARD_GARGLE; if( FAILED( hr = pDSB8->SetFX( 1, &dsed, &dwResults ) ) ) { // Not a critical failure, so just update the status DXTRACE_ERR( TEXT("SetFX"), hr ); SetDlgItemText( hDlg, IDC_STATUS, TEXT("Could not set gargle effect.") ); return S_FALSE; } // Get gargle effect friendly interface if( FAILED( hr = pDSB8->GetObjectInPath( GUID_DSFX_STANDARD_GARGLE, 0, IID_IDirectSoundFXGargle, (LPVOID*) &g_pIGargle ) ) ) return DXTRACE_ERR( TEXT("GetObjectInPath"), hr ); // Cleanup SAFE_RELEASE( pDSB8 ); // Set the buffer options to what the sliders are set to OnEffectChanged( hDlg ); // Play the sound DWORD dwLooped = bLooped ? DSBPLAY_LOOPING : 0L; if( FAILED( hr = g_pSound->Play( 0, dwLooped ) ) ) return DXTRACE_ERR( TEXT("Play"), hr ); // Update the UI controls to show the sound as playing EnablePlayUI( hDlg, FALSE ); SetDlgItemText( hDlg, IDC_STATUS, TEXT("Sound playing.") ); return S_OK; }
/* =============== idAudioHardwareWIN32::SetPrimaryBufferFormat Set primary buffer to a specified format For example, to set the primary buffer format to 22kHz stereo, 16-bit then: dwPrimaryChannels = 2 dwPrimaryFreq = 22050, dwPrimaryBitRate = 16 =============== */ void idAudioHardwareWIN32::SetPrimaryBufferFormat( dword dwPrimaryFreq, dword dwPrimaryBitRate, dword dwSpeakers ) { HRESULT hr; if( m_pDS == NULL ) { return; } ulong cfgSpeakers; m_pDS->GetSpeakerConfig( &cfgSpeakers ); DSCAPS dscaps; dscaps.dwSize = sizeof(DSCAPS); m_pDS->GetCaps(&dscaps); if (dscaps.dwFlags & DSCAPS_EMULDRIVER) { return; } // Get the primary buffer DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; dsbd.dwBufferBytes = 0; dsbd.lpwfxFormat = NULL; // Obtain write-primary cooperative level. if( FAILED( hr = m_pDS->SetCooperativeLevel(win32.hWnd, DSSCL_PRIORITY ) ) ) { DXTRACE_ERR( TEXT("SetPrimaryBufferFormat"), hr ); return; } if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) { return; } if ( dwSpeakers == 6 && (cfgSpeakers == DSSPEAKER_5POINT1 || cfgSpeakers == DSSPEAKER_SURROUND) ) { WAVEFORMATEXTENSIBLE waveFormatPCMEx; ZeroMemory( &waveFormatPCMEx, sizeof(WAVEFORMATEXTENSIBLE) ); waveFormatPCMEx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; waveFormatPCMEx.Format.nChannels = 6; waveFormatPCMEx.Format.nSamplesPerSec = dwPrimaryFreq; waveFormatPCMEx.Format.wBitsPerSample = (WORD) dwPrimaryBitRate; waveFormatPCMEx.Format.nBlockAlign = waveFormatPCMEx.Format.wBitsPerSample / 8 * waveFormatPCMEx.Format.nChannels; waveFormatPCMEx.Format.nAvgBytesPerSec = waveFormatPCMEx.Format.nSamplesPerSec * waveFormatPCMEx.Format.nBlockAlign; waveFormatPCMEx.dwChannelMask = KSAUDIO_SPEAKER_5POINT1; // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | // SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | // SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT waveFormatPCMEx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; // Specify PCM waveFormatPCMEx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE); waveFormatPCMEx.Samples.wValidBitsPerSample = 16; if( FAILED( hr = pDSBPrimary->SetFormat((WAVEFORMATEX*)&waveFormatPCMEx) ) ) { DXTRACE_ERR( TEXT("SetPrimaryBufferFormat"), hr ); return; } numSpeakers = 6; // force it to think 5.1 blockAlign = waveFormatPCMEx.Format.nBlockAlign; } else { if (dwSpeakers == 6) { common->Printf("sound: hardware reported unable to use multisound, defaulted to stereo\n"); } WAVEFORMATEX wfx; ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = dwPrimaryFreq; wfx.wBitsPerSample = (WORD) dwPrimaryBitRate; wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; wfx.cbSize = sizeof(WAVEFORMATEX); if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) { return; } numSpeakers = 2; // force it to think stereo blockAlign = wfx.nBlockAlign; } byte *speakerData; bufferSize = MIXBUFFER_SAMPLES * sizeof(word) * numSpeakers * ROOM_SLICES_IN_BUFFER; speakerData = (byte *)Mem_Alloc( bufferSize ); memset( speakerData, 0, bufferSize ); InitializeSpeakers( speakerData, bufferSize, dwPrimaryFreq, dwPrimaryBitRate, numSpeakers ); }
//----------------------------------------------------------------------------- // Name: CWaveFile::Open() // Desc: Opens a wave file for reading //----------------------------------------------------------------------------- HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) { HRESULT hr; m_dwFlags = dwFlags; m_bIsReadingFromMemory = FALSE; if( m_dwFlags == WAVEFILE_READ ) { if( strFileName == NULL ) return E_INVALIDARG; SAFE_DELETE_ARRAY( m_pwfx ); m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); if( NULL == m_hmmio ) { HRSRC hResInfo; HGLOBAL hResData; DWORD dwSize; VOID* pvRes; // Loading it as a file failed, so try it as a resource if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) ) { if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) ) return DXTRACE_ERR( TEXT("FindResource"), E_FAIL ); } if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) ) return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL ); if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL ); if( NULL == ( pvRes = LockResource( hResData ) ) ) return DXTRACE_ERR( TEXT("LockResource"), E_FAIL ); m_pResourceBuffer = new CHAR[ dwSize ]; memcpy( m_pResourceBuffer, pvRes, dwSize ); MMIOINFO mmioInfo; ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); mmioInfo.fccIOProc = FOURCC_MEM; mmioInfo.cchBuffer = dwSize; mmioInfo.pchBuffer = (CHAR*) m_pResourceBuffer; m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); } if( FAILED( hr = ReadMMIO() ) ) { // ReadMMIO will fail if its an not a wave file mmioClose( m_hmmio, 0 ); return DXTRACE_ERR( TEXT("ReadMMIO"), hr ); } if( FAILED( hr = ResetFile() ) ) return DXTRACE_ERR( TEXT("ResetFile"), hr ); // After the reset, the size of the wav file is m_ck.cksize so store it now m_dwSize = m_ck.cksize; } else { m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_CREATE ); if( NULL == m_hmmio ) return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL ); if( FAILED( hr = WriteMMIO( pwfx ) ) ) { mmioClose( m_hmmio, 0 ); return DXTRACE_ERR( TEXT("WriteMMIO"), hr ); } if( FAILED( hr = ResetFile() ) ) return DXTRACE_ERR( TEXT("ResetFile"), hr ); } return hr; }
//----------------------------------------------------------------------------- // Name: CWaveFile::Read() // Desc: Reads section of data from a wave file into pBuffer and returns // how much read in pdwSizeRead, reading not more than dwSizeToRead. // This uses m_ck to determine where to start reading from. So // subsequent calls will be continue where the last left off unless // Reset() is called. //----------------------------------------------------------------------------- HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) { if( m_bIsReadingFromMemory ) { if( m_pbDataCur == NULL ) return CO_E_NOTINITIALIZED; if( pdwSizeRead != NULL ) *pdwSizeRead = 0; if( (BYTE*)(m_pbDataCur + dwSizeToRead) > (BYTE*)(m_pbData + m_ulDataSize) ) { dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); } CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); if( pdwSizeRead != NULL ) *pdwSizeRead = dwSizeToRead; return S_OK; } else { MMIOINFO mmioinfoIn; // current status of m_hmmio if( m_hmmio == NULL ) return CO_E_NOTINITIALIZED; if( pBuffer == NULL || pdwSizeRead == NULL ) return E_INVALIDARG; if( pdwSizeRead != NULL ) *pdwSizeRead = 0; if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); UINT cbDataIn = dwSizeToRead; if( cbDataIn > m_ck.cksize ) cbDataIn = m_ck.cksize; m_ck.cksize -= cbDataIn; for( DWORD cT = 0; cT < cbDataIn; cT++ ) { // Copy the bytes from the io to the buffer. if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) { if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL ); } // Actual copy. *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); mmioinfoIn.pchNext++; } if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); if( pdwSizeRead != NULL ) *pdwSizeRead = cbDataIn; return S_OK; } }
//----------------------------------------------------------------------------- // Name: CWaveFile::Read() // Desc: Reads section of data from a wave file into pBuffer and returns // how much read in pdwSizeRead, reading not more than dwSizeToRead. // This uses m_ck to determine where to start reading from. So // subsequent calls will be continue where the last left off unless // Reset() is called. //----------------------------------------------------------------------------- HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) { if( m_bIsReadingFromMemory ) { if( m_pbDataCur == NULL ) return CO_E_NOTINITIALIZED; if( pdwSizeRead != NULL ) *pdwSizeRead = 0; if( (BYTE*)(m_pbDataCur + dwSizeToRead) > (BYTE*)(m_pbData + m_ulDataSize) ) { dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); } #pragma warning( disable: 4616 ) // disable warning about warning number '22104' being out of range #pragma warning( disable: 22104 ) // disable PREfast warning during static code analysis CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); #pragma warning( default: 22104 ) #pragma warning( default: 4616 ) if( pdwSizeRead != NULL ) *pdwSizeRead = dwSizeToRead; return S_OK; } else { MMIOINFO mmioinfoIn; // current status of m_hmmio if( m_hmmio == NULL ) return CO_E_NOTINITIALIZED; if( pBuffer == NULL || pdwSizeRead == NULL ) return E_INVALIDARG; *pdwSizeRead = 0; if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) return DXTRACE_ERR( "mmioGetInfo", E_FAIL ); UINT cbDataIn = dwSizeToRead; if( cbDataIn > m_ck.cksize ) cbDataIn = m_ck.cksize; m_ck.cksize -= cbDataIn; for( DWORD cT = 0; cT < cbDataIn; cT++ ) { // Copy the bytes from the io to the buffer. if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) { if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) return DXTRACE_ERR( "mmioAdvance", E_FAIL ); if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) return DXTRACE_ERR( "mmioinfoIn.pchNext", E_FAIL ); } // Actual copy. *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); mmioinfoIn.pchNext++; } if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) return DXTRACE_ERR( "mmioSetInfo", E_FAIL ); *pdwSizeRead = cbDataIn; return S_OK; } }
//----------------------------------------------------------------------------- // Name: CSoundManager::Create() // Desc: //----------------------------------------------------------------------------- HRESULT CSoundManager::Create( CSound** ppSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNumBuffers ) { HRESULT hr; HRESULT hrRet = S_OK; DWORD i; LPDIRECTSOUNDBUFFER* apDSBuffer = NULL; DWORD dwDSBufferSize = NULL; CWaveFile* pWaveFile = NULL; if( m_pDS == NULL ) return CO_E_NOTINITIALIZED; if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 ) return E_INVALIDARG; apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers]; if( apDSBuffer == NULL ) { hr = E_OUTOFMEMORY; goto LFail; } pWaveFile = new CWaveFile(); if( pWaveFile == NULL ) { hr = E_OUTOFMEMORY; goto LFail; } pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); if( pWaveFile->GetSize() == 0 ) { // Wave is blank, so don't create it. hr = E_FAIL; goto LFail; } // Make the DirectSound buffer the same size as the wav file dwDSBufferSize = pWaveFile->GetSize(); // Create the direct sound buffer, and only request the flags needed // since each requires some overhead and limits if the buffer can // be hardware accelerated DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = dwCreationFlags; dsbd.dwBufferBytes = dwDSBufferSize; dsbd.guid3DAlgorithm = guid3DAlgorithm; dsbd.lpwfxFormat = pWaveFile->m_pwfx; // DirectSound is only guarenteed to play PCM data. Other // formats may or may not work depending the sound card driver. hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ); // Be sure to return this error code if it occurs so the // callers knows this happened. if( hr == DS_NO_VIRTUALIZATION ) hrRet = DS_NO_VIRTUALIZATION; if( FAILED(hr) ) { // DSERR_BUFFERTOOSMALL will be returned if the buffer is // less than DSBSIZE_FX_MIN and the buffer is created // with DSBCAPS_CTRLFX. // It might also fail if hardware buffer mixing was requested // on a device that doesn't support it. DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); goto LFail; } // Default to use DuplicateSoundBuffer() when created extra buffers since always // create a buffer that uses the same memory however DuplicateSoundBuffer() will fail if // DSBCAPS_CTRLFX is used, so use CreateSoundBuffer() instead in this case. if( (dwCreationFlags & DSBCAPS_CTRLFX) == 0 ) { for( i=1; i<dwNumBuffers; i++ ) { if( FAILED( hr = m_pDS->DuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) { DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); goto LFail; } } } else { for( i=1; i<dwNumBuffers; i++ ) { hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[i], NULL ); if( FAILED(hr) ) { DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); goto LFail; } } } // Create the sound *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile, dwCreationFlags ); SAFE_DELETE_ARRAY( apDSBuffer ); return hrRet; LFail: // Cleanup SAFE_DELETE( pWaveFile ); SAFE_DELETE_ARRAY( apDSBuffer ); return hr; }
/*-------------------------------------------- 画面の描画処理 --------------------------------------------*/ HRESULT Render(void) { HRESULT hr; // 描画ターゲットのクリア g_pImmediateContext->ClearRenderTargetView( g_pRenderTargetView, // クリアする描画ターゲット g_ClearColor); // クリアする値 // 深度/ステンシルのクリア g_pImmediateContext->ClearDepthStencilView( g_pDepthStencilView, // クリアする深度/ステンシル・ビュー D3D11_CLEAR_DEPTH, // 深度値だけをクリアする 1.0f, // 深度バッファをクリアする値 0); // ステンシル・バッファをクリアする値(この場合、無関係) // *************************************** // 立方体の描画 // 定数バッファ�Aを更新 // ビュー変換行列 XMVECTORF32 eyePosition = { 0.0f, 5.0f, -5.0f, 1.0f }; // 視点(カメラの位置) XMVECTORF32 focusPosition = { 0.0f, 0.0f, 0.0f, 1.0f }; // 注視点 XMVECTORF32 upDirection = { 0.0f, 1.0f, 0.0f, 1.0f }; // カメラの上方向 XMMATRIX mat = XMMatrixLookAtLH(eyePosition, focusPosition, upDirection); XMStoreFloat4x4(&g_cbCBuffer.View, XMMatrixTranspose(mat)); // 点光源座標 XMVECTOR vec = XMVector3TransformCoord(XMLoadFloat3(&g_vLightPos), mat); XMStoreFloat3(&g_cbCBuffer.Light, vec); // ワールド変換行列 XMMATRIX matY, matX; FLOAT rotate = (FLOAT)(XM_PI * (timeGetTime() % 3000)) / 1500.0f; matY = XMMatrixRotationY(rotate); rotate = (FLOAT)(XM_PI * (timeGetTime() % 1500)) / 750.0f; matX = XMMatrixRotationX(rotate); XMStoreFloat4x4(&g_cbCBuffer.World, XMMatrixTranspose(matY * matX)); // 定数バッファのマップ取得 D3D11_MAPPED_SUBRESOURCE MappedResource; hr = g_pImmediateContext->Map( g_pCBuffer, // マップするリソース 0, // サブリソースのインデックス番号 D3D11_MAP_WRITE_DISCARD, // 書き込みアクセス 0, // &MappedResource); // データの書き込み先ポインタ if (FAILED(hr)) return DXTRACE_ERR(L"InitBackBuffer g_pImmediateContext->Map", hr); // 失敗 // データ書き込み CopyMemory(MappedResource.pData, &g_cbCBuffer, sizeof(cbCBuffer)); // マップ解除 g_pImmediateContext->Unmap(g_pCBuffer, 0); // *************************************** // IAに頂点バッファを設定 // IAに入力レイアウト・オブジェクトを設定(頂点バッファなし) g_pImmediateContext->IASetInputLayout(NULL); // IAにプリミティブの種類を設定 g_pImmediateContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // VSに頂点シェーダを設定 g_pImmediateContext->VSSetShader(g_pVertexShader, NULL, 0); // VSに定数バッファを設定 g_pImmediateContext->VSSetConstantBuffers(0, 1, &g_pCBuffer); // GSにジオメトリ・シェーダを設定 g_pImmediateContext->GSSetShader(g_pGeometryShader, NULL, 0); // GSに定数バッファを設定 g_pImmediateContext->GSSetConstantBuffers(0, 1, &g_pCBuffer); // RSにビューポートを設定 g_pImmediateContext->RSSetViewports(1, g_ViewPort); // RSにラスタライザ・ステート・オブジェクトを設定 g_pImmediateContext->RSSetState(g_pRasterizerState); // PSにピクセル・シェーダを設定 g_pImmediateContext->PSSetShader(g_pPixelShader, NULL, 0); // PSに定数バッファを設定 g_pImmediateContext->PSSetConstantBuffers(0, 1, &g_pCBuffer); // PSにシェーダ・リソース・ビューを設定 g_pImmediateContext->PSSetShaderResources( 0, // 設定する最初のスロット番号 1, // 設定するシェーダ・リソース・ビューの数 &g_pTextureSRV); // 設定するシェーダ・リソース・ビューの配列 // PSにサンプラーを設定 g_pImmediateContext->PSSetSamplers(0, 1, &g_pTextureSampler); // OMに描画ターゲット ビューと深度/ステンシル・ビューを設定 g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, g_bDepthMode ? g_pDepthStencilView : NULL); // OMにブレンド・ステート・オブジェクトを設定 FLOAT BlendFactor[4] = {0.0f, 0.0f, 0.0f, 0.0f}; g_pImmediateContext->OMSetBlendState(g_pBlendState, BlendFactor, 0xffffffff); // OMに深度/ステンシル・ステート・オブジェクトを設定 g_pImmediateContext->OMSetDepthStencilState(g_pDepthStencilState, 0); // *************************************** // 頂点バッファとインデックス・バッファを使わずに描画する g_pImmediateContext->Draw( 36, // 描画する頂点数 0); // 最初の頂点ID // *************************************** // バック バッファの表示 hr = g_pSwapChain->Present( 0, // 画面を直ぐに更新する 0); // 画面を実際に更新する return hr; }
/*------------------------------------------- Direct3D初期化 --------------------------------------------*/ HRESULT InitDirect3D(void) { // ウインドウのクライアント エリア RECT rc; GetClientRect(g_hWindow, &rc); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; // デバイスとスワップ チェインの作成 DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); // 構造体の値を初期化 sd.BufferCount = 3; // バック バッファ数 sd.BufferDesc.Width = width; // バック バッファの幅 sd.BufferDesc.Height = height; // バック バッファの高さ sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // フォーマット sd.BufferDesc.RefreshRate.Numerator = 60; // リフレッシュ レート(分子) sd.BufferDesc.RefreshRate.Denominator = 1; // リフレッシュ レート(分母) sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; // スキャンライン sd.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED; // スケーリング sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // バック バッファの使用法 sd.OutputWindow = g_hWindow; // 関連付けるウインドウ sd.SampleDesc.Count = 1; // マルチ サンプルの数 sd.SampleDesc.Quality = 0; // マルチ サンプルのクオリティ sd.Windowed = TRUE; // ウインドウ モード sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // モード自動切り替え #if defined(DEBUG) || defined(_DEBUG) UINT createDeviceFlags = D3D11_CREATE_DEVICE_DEBUG; #else UINT createDeviceFlags = 0; #endif // ハードウェア・デバイスを作成 HRESULT hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, g_pFeatureLevels, g_FeatureLevels, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pD3DDevice, &g_FeatureLevelsSupported, &g_pImmediateContext); if(FAILED(hr)) { // WARPデバイスを作成 hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_WARP, NULL, createDeviceFlags, g_pFeatureLevels, g_FeatureLevels, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pD3DDevice, &g_FeatureLevelsSupported, &g_pImmediateContext); if(FAILED(hr)) { // リファレンス・デバイスを作成 hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, createDeviceFlags, g_pFeatureLevels, g_FeatureLevels, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pD3DDevice, &g_FeatureLevelsSupported, &g_pImmediateContext); if(FAILED(hr)) { return DXTRACE_ERR(L"InitDirect3D D3D11CreateDeviceAndSwapChain", hr); } } } // ********************************************************** // シェーダのコンパイル hr = CreateShaderObj(); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D CreateShaderObj", hr); hr = CreateShaderShadowVolume(); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D CreateShaderShadowVolume", hr); hr = CreateShaderShadow(); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D CreateShaderShadow", hr); // ********************************************************** // 定数バッファの定義 D3D11_BUFFER_DESC cBufferDesc; cBufferDesc.Usage = D3D11_USAGE_DYNAMIC; // 動的(ダイナミック)使用法 cBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; // 定数バッファ cBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // CPUから書き込む cBufferDesc.MiscFlags = 0; cBufferDesc.StructureByteStride = 0; // 定数バッファの作成 cBufferDesc.ByteWidth = sizeof(cbCBuffer); // バッファ・サイズ hr = g_pD3DDevice->CreateBuffer(&cBufferDesc, NULL, &g_pCBuffer); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateBuffer", hr); // ********************************************************** // Waveform OBJファイルの読み込み char mtlFileName[80]; if (g_wfObjKuma.Load(g_pD3DDevice, g_pImmediateContext, "..\\misc\\kuma.obj",mtlFileName, sizeof(mtlFileName)) == false) return DXTRACE_ERR(L"InitDirect3D g_wfObjKuma.Load", E_FAIL); // MTLファイルの読み込み if (g_wfMtl.Load(g_pD3DDevice, mtlFileName, "..\\misc\\default.bmp") == false) return DXTRACE_ERR(L"InitDirect3D g_wfMtl.Load", E_FAIL); // ********************************************************** // サンプラーの作成 D3D11_SAMPLER_DESC descSampler; descSampler.Filter = D3D11_FILTER_ANISOTROPIC; descSampler.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; descSampler.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; descSampler.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; descSampler.MipLODBias = 0.0f; descSampler.MaxAnisotropy = 2; descSampler.ComparisonFunc = D3D11_COMPARISON_NEVER; descSampler.BorderColor[0] = 0.0f; descSampler.BorderColor[1] = 0.0f; descSampler.BorderColor[2] = 0.0f; descSampler.BorderColor[3] = 0.0f; descSampler.MinLOD = -FLT_MAX; descSampler.MaxLOD = FLT_MAX; hr = g_pD3DDevice->CreateSamplerState(&descSampler, &g_pTextureSampler); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateSamplerState", hr); // ********************************************************** // バック バッファの初期化 hr = InitBackBuffer(); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D InitBackBuffer", hr); return hr; }
/*------------------------------------------- Direct3D初期化 --------------------------------------------*/ HRESULT InitDirect3D(void) { // ウインドウのクライアント エリア RECT rc; GetClientRect(g_hWindow, &rc); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; // デバイスとスワップ チェインの作成 DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); // 構造体の値を初期化 sd.BufferCount = 3; // バック バッファ数 sd.BufferDesc.Width = width; // バック バッファの幅 sd.BufferDesc.Height = height; // バック バッファの高さ sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // フォーマット sd.BufferDesc.RefreshRate.Numerator = 60; // リフレッシュ レート(分子) sd.BufferDesc.RefreshRate.Denominator = 1; // リフレッシュ レート(分母) sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; // スキャンライン sd.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED; // スケーリング sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // バック バッファの使用法 sd.OutputWindow = g_hWindow; // 関連付けるウインドウ sd.SampleDesc.Count = 1; // マルチ サンプルの数 sd.SampleDesc.Quality = 0; // マルチ サンプルのクオリティ sd.Windowed = TRUE; // ウインドウ モード sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // モード自動切り替え #if defined(DEBUG) || defined(_DEBUG) UINT createDeviceFlags = D3D11_CREATE_DEVICE_DEBUG; #else UINT createDeviceFlags = 0; #endif // ハードウェア・デバイスを作成 HRESULT hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, g_pFeatureLevels, g_FeatureLevels, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pD3DDevice, &g_FeatureLevelsSupported, &g_pImmediateContext); if(FAILED(hr)) { // WARPデバイスを作成 hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_WARP, NULL, createDeviceFlags, g_pFeatureLevels, g_FeatureLevels, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pD3DDevice, &g_FeatureLevelsSupported, &g_pImmediateContext); if(FAILED(hr)) { // リファレンス・デバイスを作成 hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, createDeviceFlags, g_pFeatureLevels, g_FeatureLevels, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pD3DDevice, &g_FeatureLevelsSupported, &g_pImmediateContext); if(FAILED(hr)) { return DXTRACE_ERR(L"InitDirect3D D3D11CreateDeviceAndSwapChain", hr); } } } // ********************************************************** // 頂点シェーダのコードをコンパイル ID3DBlob* pBlobVS = NULL; hr = D3DX11CompileFromFile( L"..\\misc\\D3D11Sample06.sh", // ファイル名 NULL, // マクロ定義(なし) NULL, // インクルード・ファイル定義(なし) "VS", // 「VS関数」がシェーダから実行される "vs_4_0", // 頂点シェーダ g_flagCompile, // コンパイル・オプション 0, // エフェクトのコンパイル・オプション(なし) NULL, // 直ぐにコンパイルしてから関数を抜ける。 &pBlobVS, // コンパイルされたバイト・コード NULL, // エラーメッセージは不要 NULL); // 戻り値 if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D D3DX11CompileShaderFromFile", hr); // 頂点シェーダの作成 hr = g_pD3DDevice->CreateVertexShader( pBlobVS->GetBufferPointer(), // バイト・コードへのポインタ pBlobVS->GetBufferSize(), // バイト・コードの長さ NULL, &g_pVertexShader); // 頂点シェーダを受け取る変数 SAFE_RELEASE(pBlobVS); // バイト・コードを解放 if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateVertexShader", hr); // ********************************************************** // ジオメトリ・シェーダのコードをコンパイル ID3DBlob* pBlobGS = NULL; hr = D3DX11CompileFromFile( L"..\\misc\\D3D11Sample06.sh", // ファイル名 NULL, // マクロ定義(なし) NULL, // インクルード・ファイル定義(なし) "GS", // 「GS関数」がシェーダから実行される "gs_4_0", // ジオメトリ・シェーダ g_flagCompile, // コンパイル・オプション 0, // エフェクトのコンパイル・オプション(なし) NULL, // 直ぐにコンパイルしてから関数を抜ける。 &pBlobGS, // コンパイルされたバイト・コード NULL, // エラーメッセージは不要 NULL); // 戻り値 if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D D3DX11CompileShaderFromFile", hr); // ジオメトリ・シェーダの作成 hr = g_pD3DDevice->CreateGeometryShader( pBlobGS->GetBufferPointer(), // バイト・コードへのポインタ pBlobGS->GetBufferSize(), // バイト・コードの長さ NULL, &g_pGeometryShader); // ジオメトリ・シェーダを受け取る変数 SAFE_RELEASE(pBlobGS); // バイト・コードを解放 if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreatePixelShader", hr); // ********************************************************** // ピクセル・シェーダのコードをコンパイル ID3DBlob* pBlobPS = NULL; hr = D3DX11CompileFromFile( L"..\\misc\\D3D11Sample06.sh", // ファイル名 NULL, // マクロ定義(なし) NULL, // インクルード・ファイル定義(なし) "PS", // 「PS関数」がシェーダから実行される "ps_4_0", // ピクセル・シェーダ g_flagCompile, // コンパイル・オプション 0, // エフェクトのコンパイル・オプション(なし) NULL, // 直ぐにコンパイルしてから関数を抜ける。 &pBlobPS, // コンパイルされたバイト・コード NULL, // エラーメッセージは不要 NULL); // 戻り値 if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D D3DX11CompileShaderFromFile", hr); // ピクセル・シェーダの作成 hr = g_pD3DDevice->CreatePixelShader( pBlobPS->GetBufferPointer(), // バイト・コードへのポインタ pBlobPS->GetBufferSize(), // バイト・コードの長さ NULL, &g_pPixelShader); // ピクセル・シェーダを受け取る変数 SAFE_RELEASE(pBlobPS); // バイト・コードを解放 if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreatePixelShader", hr); // ********************************************************** // 定数バッファの定義 D3D11_BUFFER_DESC cBufferDesc; cBufferDesc.Usage = D3D11_USAGE_DYNAMIC; // 動的(ダイナミック)使用法 cBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; // 定数バッファ cBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // CPUから書き込む cBufferDesc.MiscFlags = 0; cBufferDesc.StructureByteStride = 0; // 定数バッファ�@の作成 cBufferDesc.ByteWidth = sizeof(cbCBuffer); // バッファ・サイズ hr = g_pD3DDevice->CreateBuffer(&cBufferDesc, NULL, &g_pCBuffer); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateBuffer", hr); // ********************************************************** // ブレンド・ステート・オブジェクトの作成 D3D11_BLEND_DESC BlendState; ZeroMemory(&BlendState, sizeof(D3D11_BLEND_DESC)); BlendState.AlphaToCoverageEnable = FALSE; BlendState.IndependentBlendEnable = FALSE; BlendState.RenderTarget[0].BlendEnable = FALSE; BlendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; hr = g_pD3DDevice->CreateBlendState(&BlendState, &g_pBlendState); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateBlendState", hr); // ラスタライザ・ステート・オブジェクトの作成 D3D11_RASTERIZER_DESC RSDesc; RSDesc.FillMode = D3D11_FILL_SOLID; // 普通に描画する RSDesc.CullMode = D3D11_CULL_NONE; // 両面を描画する RSDesc.FrontCounterClockwise = FALSE; // 時計回りが表面 RSDesc.DepthBias = 0; RSDesc.DepthBiasClamp = 0; RSDesc.SlopeScaledDepthBias = 0; RSDesc.DepthClipEnable = TRUE; RSDesc.ScissorEnable = FALSE; RSDesc.MultisampleEnable = FALSE; RSDesc.AntialiasedLineEnable = FALSE; hr = g_pD3DDevice->CreateRasterizerState(&RSDesc, &g_pRasterizerState); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateRasterizerState", hr); // ********************************************************** // 深度/ステンシル・ステート・オブジェクトの作成 D3D11_DEPTH_STENCIL_DESC DepthStencil; DepthStencil.DepthEnable = TRUE; // 深度テストあり DepthStencil.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; // 書き込む DepthStencil.DepthFunc = D3D11_COMPARISON_LESS; // 手前の物体を描画 DepthStencil.StencilEnable = FALSE; // ステンシル・テストなし DepthStencil.StencilReadMask = 0; // ステンシル読み込みマスク。 DepthStencil.StencilWriteMask = 0; // ステンシル書き込みマスク。 // 面が表を向いている場合のステンシル・テストの設定 DepthStencil.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.FrontFace.StencilFunc = D3D11_COMPARISON_NEVER; // 常に失敗 // 面が裏を向いている場合のステンシル・テストの設定 DepthStencil.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // 常に成功 hr = g_pD3DDevice->CreateDepthStencilState(&DepthStencil, &g_pDepthStencilState); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateDepthStencilState", hr); // ********************************************************** // バック バッファの初期化 hr = InitBackBuffer(); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D InitBackBuffer", hr); return hr; }
/*------------------------------------------- Direct3D初期化 --------------------------------------------*/ HRESULT InitDirect3D(void) { // ウインドウのクライアント エリア RECT rc; GetClientRect(g_hWindow, &rc); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; // デバイスとスワップ チェインの作成 DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); // 構造体の値を初期化 sd.BufferCount = 3; // バック バッファ数 sd.BufferDesc.Width = width; // バック バッファの幅 sd.BufferDesc.Height = height; // バック バッファの高さ sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // フォーマット sd.BufferDesc.RefreshRate.Numerator = 60; // リフレッシュ レート(分子) sd.BufferDesc.RefreshRate.Denominator = 1; // リフレッシュ レート(分母) sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; // スキャンライン sd.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED; // スケーリング sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // バック バッファの使用法 sd.OutputWindow = g_hWindow; // 関連付けるウインドウ sd.SampleDesc.Count = 1; // マルチ サンプルの数 sd.SampleDesc.Quality = 0; // マルチ サンプルのクオリティ sd.Windowed = TRUE; // ウインドウ モード sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // モード自動切り替え #if defined(DEBUG) || defined(_DEBUG) UINT createDeviceFlags = D3D11_CREATE_DEVICE_DEBUG; #else UINT createDeviceFlags = 0; #endif // ハードウェア・デバイスを作成 HRESULT hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, g_pFeatureLevels, g_FeatureLevels, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pD3DDevice, &g_FeatureLevelsSupported, &g_pImmediateContext); if(FAILED(hr)) { // WARPデバイスを作成 hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_WARP, NULL, createDeviceFlags, g_pFeatureLevels, g_FeatureLevels, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pD3DDevice, &g_FeatureLevelsSupported, &g_pImmediateContext); if(FAILED(hr)) { // リファレンス・デバイスを作成 hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, createDeviceFlags, g_pFeatureLevels, g_FeatureLevels, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pD3DDevice, &g_FeatureLevelsSupported, &g_pImmediateContext); if(FAILED(hr)) { return DXTRACE_ERR(L"InitDirect3D D3D11CreateDeviceAndSwapChain", hr); } } } // ********************************************************** // 頂点シェーダのコードをコンパイル ID3DBlob* pBlobVS = NULL; hr = D3DX11CompileFromFile( L"..\\misc\\D3D11Sample07.sh", // ファイル名 NULL, // マクロ定義(なし) NULL, // インクルード・ファイル定義(なし) "VS", // 「VS関数」がシェーダから実行される "vs_4_0", // 頂点シェーダ g_flagCompile, // コンパイル・オプション 0, // エフェクトのコンパイル・オプション(なし) NULL, // 直ぐにコンパイルしてから関数を抜ける。 &pBlobVS, // コンパイルされたバイト・コード NULL, // エラーメッセージは不要 NULL); // 戻り値 if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D D3DX11CompileShaderFromFile", hr); // 頂点シェーダの作成 hr = g_pD3DDevice->CreateVertexShader( pBlobVS->GetBufferPointer(), // バイト・コードへのポインタ pBlobVS->GetBufferSize(), // バイト・コードの長さ NULL, &g_pVertexShader); // 頂点シェーダを受け取る変数 SAFE_RELEASE(pBlobVS); // バイト・コードを解放 if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateVertexShader", hr); // ********************************************************** // ジオメトリ・シェーダのコードをコンパイル ID3DBlob* pBlobGS = NULL; hr = D3DX11CompileFromFile( L"..\\misc\\D3D11Sample07.sh", // ファイル名 NULL, // マクロ定義(なし) NULL, // インクルード・ファイル定義(なし) "GS", // 「GS関数」がシェーダから実行される "gs_4_0", // ジオメトリ・シェーダ g_flagCompile, // コンパイル・オプション 0, // エフェクトのコンパイル・オプション(なし) NULL, // 直ぐにコンパイルしてから関数を抜ける。 &pBlobGS, // コンパイルされたバイト・コード NULL, // エラーメッセージは不要 NULL); // 戻り値 if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D D3DX11CompileShaderFromFile", hr); // ジオメトリ・シェーダの作成 hr = g_pD3DDevice->CreateGeometryShader( pBlobGS->GetBufferPointer(), // バイト・コードへのポインタ pBlobGS->GetBufferSize(), // バイト・コードの長さ NULL, &g_pGeometryShader); // ジオメトリ・シェーダを受け取る変数 SAFE_RELEASE(pBlobGS); // バイト・コードを解放 if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreatePixelShader", hr); // ********************************************************** // ピクセル・シェーダのコードをコンパイル ID3DBlob* pBlobPS = NULL; hr = D3DX11CompileFromFile( L"..\\misc\\D3D11Sample07.sh", // ファイル名 NULL, // マクロ定義(なし) NULL, // インクルード・ファイル定義(なし) "PS", // 「PS関数」がシェーダから実行される "ps_4_0", // ピクセル・シェーダ g_flagCompile, // コンパイル・オプション 0, // エフェクトのコンパイル・オプション(なし) NULL, // 直ぐにコンパイルしてから関数を抜ける。 &pBlobPS, // コンパイルされたバイト・コード NULL, // エラーメッセージは不要 NULL); // 戻り値 if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D D3DX11CompileShaderFromFile", hr); // ピクセル・シェーダの作成 hr = g_pD3DDevice->CreatePixelShader( pBlobPS->GetBufferPointer(), // バイト・コードへのポインタ pBlobPS->GetBufferSize(), // バイト・コードの長さ NULL, &g_pPixelShader); // ピクセル・シェーダを受け取る変数 SAFE_RELEASE(pBlobPS); // バイト・コードを解放 if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreatePixelShader", hr); // ********************************************************** // 定数バッファの定義 D3D11_BUFFER_DESC cBufferDesc; cBufferDesc.Usage = D3D11_USAGE_DYNAMIC; // 動的(ダイナミック)使用法 cBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; // 定数バッファ cBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // CPUから書き込む cBufferDesc.MiscFlags = 0; cBufferDesc.StructureByteStride = 0; // 定数バッファの作成 cBufferDesc.ByteWidth = sizeof(cbCBuffer); // バッファ・サイズ hr = g_pD3DDevice->CreateBuffer(&cBufferDesc, NULL, &g_pCBuffer); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateBuffer", hr); // ********************************************************** // ブレンド・ステート・オブジェクトの作成 D3D11_BLEND_DESC BlendState; ZeroMemory(&BlendState, sizeof(D3D11_BLEND_DESC)); BlendState.AlphaToCoverageEnable = FALSE; BlendState.IndependentBlendEnable = FALSE; BlendState.RenderTarget[0].BlendEnable = FALSE; BlendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; hr = g_pD3DDevice->CreateBlendState(&BlendState, &g_pBlendState); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateBlendState", hr); // ラスタライザ・ステート・オブジェクトの作成 D3D11_RASTERIZER_DESC RSDesc; RSDesc.FillMode = D3D11_FILL_SOLID; // 普通に描画する RSDesc.CullMode = D3D11_CULL_NONE; // 両面を描画する RSDesc.FrontCounterClockwise = FALSE; // 時計回りが表面 RSDesc.DepthBias = 0; RSDesc.DepthBiasClamp = 0; RSDesc.SlopeScaledDepthBias = 0; RSDesc.DepthClipEnable = TRUE; RSDesc.ScissorEnable = FALSE; RSDesc.MultisampleEnable = FALSE; RSDesc.AntialiasedLineEnable = FALSE; hr = g_pD3DDevice->CreateRasterizerState(&RSDesc, &g_pRasterizerState); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateRasterizerState", hr); // ********************************************************** // 深度/ステンシル・ステート・オブジェクトの作成 D3D11_DEPTH_STENCIL_DESC DepthStencil; DepthStencil.DepthEnable = TRUE; // 深度テストあり DepthStencil.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; // 書き込む DepthStencil.DepthFunc = D3D11_COMPARISON_LESS; // 手前の物体を描画 DepthStencil.StencilEnable = FALSE; // ステンシル・テストなし DepthStencil.StencilReadMask = 0; // ステンシル読み込みマスク。 DepthStencil.StencilWriteMask = 0; // ステンシル書き込みマスク。 // 面が表を向いている場合のステンシル・テストの設定 DepthStencil.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.FrontFace.StencilFunc = D3D11_COMPARISON_NEVER; // 常に失敗 // 面が裏を向いている場合のステンシル・テストの設定 DepthStencil.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // 常に成功 hr = g_pD3DDevice->CreateDepthStencilState(&DepthStencil, &g_pDepthStencilState); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateDepthStencilState", hr); // ********************************************************** // 描画可能テクスチャの作成 D3D11_TEXTURE2D_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Width = 128; // 幅 desc.Height = 128; // 高さ desc.MipLevels = 1; // ミップマップ レベル数 desc.ArraySize = 1; // テクスチャの配列サイズ desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // フォーマット desc.SampleDesc.Count = 1; // マルチサンプリングの設定 desc.Usage = D3D11_USAGE_DYNAMIC; // 動的(Dynamic)使用法 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; // シェーダ リソース desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // CPUで書き込む hr = g_pD3DDevice->CreateTexture2D(&desc, NULL, &g_pTexture); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateTexture2D", hr); // 2Dテクスチャにアクセスするシェーダ リソース ビューの設定 D3D11_SHADER_RESOURCE_VIEW_DESC srDesc; srDesc.Format = desc.Format; // フォーマット srDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D; // 2Dテクスチャ srDesc.Texture2D.MostDetailedMip = 0; // 最初のミップマップ レベル srDesc.Texture2D.MipLevels = -1; // すべてのミップマップ レベル // シェーダ リソース ビューの作成 hr = g_pD3DDevice->CreateShaderResourceView( g_pTexture, // アクセスするテクスチャ リソース &srDesc, // シェーダ リソース ビューの設定 &g_pTextureSRV); // 受け取る変数 if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateShaderResourceView", hr); // リソースをマップする D3D11_MAPPED_SUBRESOURCE MappedResource; hr = g_pImmediateContext->Map( g_pTexture, // マップするリソース 0, // サブリソースのインデックス番号 D3D11_MAP_WRITE_DISCARD, // 書き込みアクセス 0, // &MappedResource); // データの書き込み先ポインタ if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pImmediateContext->Map", hr); // 失敗 // リソースに書き込む UCHAR* pTexels = (UCHAR*)MappedResource.pData; for (UINT row = 0; row < desc.Height; row++) // 行(高さ方向) { float b = 1.5f * (2.0f * row - desc.Height) / desc.Height; UINT rowStart = row * MappedResource.RowPitch; for (UINT col = 0; col < desc.Width; col++) // 列(幅方向) { float a = 1.5f * (2.0f * col - desc.Width) / desc.Width - 0.5f; // マンデルブロー計算 float x = 0, y = 0; int count = 0; while (count < 0xf) { float xn = x * x - y * y + a; float yn = 2 * x * y + b; x = xn; y = yn; float z = xn * xn + yn * yn; if (z > 100.0f) break; ++count; } // テクセル書き込み UINT colStart = col * 4; pTexels[rowStart + colStart + 0] = (UCHAR)(UCHAR)(count == 0xf ? 255 : (count << 4)); // 赤 pTexels[rowStart + colStart + 1] = (UCHAR)(count == 0xf ? 255 : 255 - (count << 4)); // 緑 pTexels[rowStart + colStart + 2] = (UCHAR)(count == 0xf ? 255 : 0); // 青 pTexels[rowStart + colStart + 3] = 255; // α } } // マップ解除 g_pImmediateContext->Unmap(g_pTexture, 0); // サンプラーの作成 D3D11_SAMPLER_DESC descSampler; descSampler.Filter = D3D11_FILTER_ANISOTROPIC; descSampler.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; descSampler.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; descSampler.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; descSampler.MipLODBias = 0.0f; descSampler.MaxAnisotropy = 2; descSampler.ComparisonFunc = D3D11_COMPARISON_NEVER; descSampler.BorderColor[0] = 0.0f; descSampler.BorderColor[1] = 0.0f; descSampler.BorderColor[2] = 0.0f; descSampler.BorderColor[3] = 0.0f; descSampler.MinLOD = -FLT_MAX; descSampler.MaxLOD = FLT_MAX; hr = g_pD3DDevice->CreateSamplerState(&descSampler, &g_pTextureSampler); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateSamplerState", hr); // ********************************************************** // バック バッファの初期化 hr = InitBackBuffer(); if (FAILED(hr)) return DXTRACE_ERR(L"InitDirect3D InitBackBuffer", hr); return hr; }
HRESULT CStreamingSound::FillBufferWithSound(BOOL restored) { HRESULT hr; VOID* pDSLockedBuffer = NULL; // Pointer to locked buffer memory DWORD dwDSLockedBufferSize = 0; // Size of the locked DirectSound buffer VOID* pDSLockedBuffer2 = NULL; DWORD dwDSLockedBufferSize2 = 0; //UINT dwDataWrote; DWORD dwPlayPos; DWORD dwWritePos; LONG lLockSize; DWORD dwReadSize; DWORD dwReadSizeAll=0; BYTE* aServalFrame = NULL; BYTE aFrame[BLOCK_SIZE]; //BYTE aFrame2[BLOCK_SIZE]; short asFrame[FRAME_SIZE]; if( m_pDSB == NULL ) return CO_E_NOTINITIALIZED; if( FAILED( hr = m_pDSB->GetCurrentPosition( &dwPlayPos, &dwWritePos ) ) ) return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); lLockSize = dwPlayPos - m_dwNextWriteOffset; if( lLockSize < 0 ) lLockSize += m_dwWriteBufferSize; // Block align lock size so that we are always write on a boundary lLockSize -= (lLockSize % m_dwNotifySize); if (lLockSize==0) return S_OK; if (restored) { Reset(); while (m_dwNextWriteOffset<m_dwWriteBufferSize) { m_dwNextWriteOffset %= m_dwWriteBufferSize; // Circular buffer // Lock the buffer down if( FAILED( hr = m_pDSB->Lock( m_dwNextWriteOffset, m_dwNotifySize, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, 0L ) ) ) return DXTRACE_ERR( TEXT("Lock"), hr ); dwReadSize = m_pDataBuffer->ReadBlock((BYTE*)pDSLockedBuffer,m_dwNotifySize); if( dwReadSize < m_dwNotifySize ) { // Wav is blank, so just fill with silence FillMemory( (BYTE*) pDSLockedBuffer, dwDSLockedBufferSize, (BYTE)0 ); } // Unlock the buffer, we don't need it anymore. m_pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); m_dwNextWriteOffset += dwDSLockedBufferSize; } m_dwNextWriteOffset %= m_dwWriteBufferSize; // Circular buffer } else { // Lock the buffer down if( FAILED( hr = m_pDSB->Lock( m_dwNextWriteOffset, lLockSize, &pDSLockedBuffer, &dwDSLockedBufferSize, &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) return DXTRACE_ERR( TEXT("Lock"), hr ); aServalFrame = new BYTE[lLockSize]; while (dwReadSizeAll<lLockSize && (dwReadSize = m_pDataBuffer->ReadBlock((BYTE*)(aServalFrame+dwReadSizeAll),m_dwNotifySize))) dwReadSizeAll += dwReadSize; if (dwReadSizeAll<lLockSize) { LOGWARNING("CStreamingSound::FillBufferWithSound:Fill with silence "<<lLockSize-dwReadSizeAll<<"/"<<lLockSize<<" bytes."); // Wav is blank, so just fill with silence FillMemory( (BYTE*) (aServalFrame+dwReadSizeAll), lLockSize-dwReadSizeAll, (BYTE)0 ); } CopyMemory(pDSLockedBuffer,aServalFrame,dwDSLockedBufferSize); if (pDSLockedBuffer2) CopyMemory(pDSLockedBuffer2,aServalFrame+dwDSLockedBufferSize,dwDSLockedBufferSize2); // Unlock the buffer, we don't need it anymore. m_pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); if (pDSLockedBuffer2) m_pDSB->Unlock( pDSLockedBuffer2, dwDSLockedBufferSize2, NULL, 0 ); m_dwNextWriteOffset += lLockSize; m_dwNextWriteOffset %= m_dwWriteBufferSize; // Circular buffer if (aServalFrame) { delete aServalFrame; aServalFrame = NULL; } } return S_OK; }
//----------------------------------------------------------------------------- // Name: CSoundManager::CreateStreaming() // Desc: //----------------------------------------------------------------------------- HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD m_dwNotifySize, HANDLE hNotifyEvent, FileLog* filelog) { HRESULT hr; if( m_pDS == NULL ) return CO_E_NOTINITIALIZED; if( ppStreamingSound == NULL || hNotifyEvent == NULL ) return E_INVALIDARG; LPDIRECTSOUNDBUFFER pDSBuffer = NULL; DWORD dwDSBufferSize = NULL; DSBPOSITIONNOTIFY* aPosNotify = NULL; LPDIRECTSOUNDNOTIFY m_pDSNotify = NULL; // Figure out how big the DSound buffer should be dwDSBufferSize = m_dwNotifySize * dwNotifyCount; // Set up the direct sound buffer. Request the NOTIFY flag, so // that we are notified as the sound buffer plays. Note, that using this flag // may limit the amount of hardware acceleration that can occur. DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = dwCreationFlags | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2| DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCSOFTWARE; dsbd.dwBufferBytes = dwDSBufferSize; dsbd.guid3DAlgorithm = guid3DAlgorithm; //LPWAVEFORMATEX wfx = new WAVEFORMATEX; WAVEFORMATEX wfx; ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = (WORD) m_dwPrimaryChannels; wfx.nSamplesPerSec = m_dwPrimaryFreq; wfx.wBitsPerSample = (WORD) m_dwPrimaryBitRate; wfx.nBlockAlign = (WORD) (wfx.wBitsPerSample / 8 * wfx.nChannels); wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; dsbd.lpwfxFormat = &wfx; if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) { // If wave format isn't then it will return // either DSERR_BADFORMAT or E_INVALIDARG if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) return DXTRACE_ERR_NOMSGBOX( TEXT("CreateSoundBuffer"), hr ); return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); } // Create the notification events, so that we know when to fill // the buffer as the sound plays. if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, (VOID**)&m_pDSNotify ) ) ) { SAFE_DELETE( aPosNotify ); return DXTRACE_ERR( TEXT("QueryInterface"), hr ); } aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; if( aPosNotify == NULL ) return E_OUTOFMEMORY; for( DWORD i = 0; i < dwNotifyCount; i++ ) { aPosNotify[i].dwOffset = (m_dwNotifySize * i) + m_dwNotifySize - 1; aPosNotify[i].hEventNotify = hNotifyEvent; } // Tell DirectSound when to notify us. The notification will come in the from // of signaled events that are handled in WinMain() if( FAILED( hr = m_pDSNotify->SetNotificationPositions( dwNotifyCount, aPosNotify ) ) ) { SAFE_RELEASE( m_pDSNotify ); SAFE_DELETE( aPosNotify ); return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); } SAFE_RELEASE( m_pDSNotify ); SAFE_DELETE( aPosNotify ); // Create the sound *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, m_dwNotifySize,hNotifyEvent,filelog); return S_OK; }
//----------------------------------------------------------------------------- // Name: MainDlgProc() // Desc: Handles dialog messages //----------------------------------------------------------------------------- INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam ) { HRESULT hr; switch( msg ) { case WM_INITDIALOG: OnInitDialog( hDlg ); break; case WM_COMMAND: switch( LOWORD(wParam) ) { case IDC_SOUNDFILE: OnOpenSoundFile( hDlg ); break; case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break; case IDC_PLAY: if( FAILED( hr = OnPlaySound( hDlg ) ) ) { DXTRACE_ERR( TEXT("OnPlaySound"), hr ); MessageBox( hDlg, "Error playing DirectSound buffer." "Sample will now exit.", "DirectSound Sample", MB_OK | MB_ICONERROR ); EndDialog( hDlg, IDABORT ); } break; case IDC_STOP: if( g_pSound ) { g_pSound->Stop(); g_pSound->Reset(); } // Update the UI controls to show the sound as stopped EnablePlayUI( hDlg, TRUE ); SetDlgItemText( hDlg, IDC_STATUS, TEXT("Sound stopped.") ); break; case IDC_DEFER: g_bDeferSettings = !g_bDeferSettings; OnSliderChanged( hDlg ); break; case IDC_APPLY: // Call the IDirectSound3DListener::CommitDeferredSettings // method to execute all of the deferred commands at once. // This is many times more efficent than recomputing everything // for every call. if( g_pDSListener ) g_pDSListener->CommitDeferredSettings(); break; default: return FALSE; // Didn't handle message } break; case WM_TIMER: if( wParam == IDT_MOVEMENT_TIMER ) OnMovementTimer( hDlg ); break; case WM_NOTIFY: OnSliderChanged( hDlg ); break; case WM_DESTROY: // Cleanup everything KillTimer( hDlg, 1 ); SAFE_RELEASE( g_pDSListener ); SAFE_RELEASE( g_pDS3DBuffer ); SAFE_DELETE( g_pSound ); SAFE_DELETE( g_pSoundManager ); break; default: return FALSE; // Didn't handle message } return TRUE; // Handled message }
//----------------------------------------------------------------------------- // Name: CSoundManager::CreateStreaming() // Desc: //----------------------------------------------------------------------------- HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, LPTSTR strWaveFileName, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNotifyCount, DWORD dwNotifySize, HANDLE hNotifyEvent ) { HRESULT hr; if( m_pDS == NULL ) return CO_E_NOTINITIALIZED; if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL ) return E_INVALIDARG; IDirectSoundBuffer* pDSBuffer = NULL; DWORD dwDSBufferSize = NULL; CWaveFile* pWaveFile = NULL; DSBPOSITIONNOTIFY* aPosNotify = NULL; IDirectSoundNotify* pDSNotify = NULL; pWaveFile = new CWaveFile(); if( pWaveFile == NULL ) return E_OUTOFMEMORY; pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ ); // Figure out how big the DirectSound buffer should be dwDSBufferSize = dwNotifySize * dwNotifyCount; // Set up the direct sound buffer. Request the NOTIFY flag, so // that we are notified as the sound buffer plays. Note, that using this flag // may limit the amount of hardware acceleration that can occur. DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = dwCreationFlags | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2; dsbd.dwBufferBytes = dwDSBufferSize; dsbd.guid3DAlgorithm = guid3DAlgorithm; dsbd.lpwfxFormat = pWaveFile->m_pwfx; if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) ) { // If wave format isn't then it will return // either DSERR_BADFORMAT or E_INVALIDARG if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG ) return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); } // Create the notification events, so that we know when to fill // the buffer as the sound plays. if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, (VOID**)&pDSNotify ) ) ) { SAFE_DELETE_ARRAY( aPosNotify ); return DXTRACE_ERR( TEXT("QueryInterface"), hr ); } aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ]; if( aPosNotify == NULL ) return E_OUTOFMEMORY; for( DWORD i = 0; i < dwNotifyCount; i++ ) { aPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; aPosNotify[i].hEventNotify = hNotifyEvent; } // Tell DirectSound when to notify us. The notification will come in the from // of signaled events that are handled in WinMain() if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, aPosNotify ) ) ) { SAFE_RELEASE( pDSNotify ); SAFE_DELETE_ARRAY( aPosNotify ); return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr ); } SAFE_RELEASE( pDSNotify ); SAFE_DELETE_ARRAY( aPosNotify ); // Create the sound *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize ); return S_OK; }
/*------------------------------------------- シェーダのコンパイル(3Dオブジェクト描画用) --------------------------------------------*/ HRESULT CreateShaderObj(void) { HRESULT hr; // ********************************************************** // 頂点シェーダのコードをコンパイル ID3DBlob* pBlobVS = NULL; hr = D3DX11CompileFromFile( L"..\\misc\\D3D11Sample17.sh", // ファイル名 NULL, // マクロ定義(なし) NULL, // インクルード・ファイル定義(なし) "VS", // 「VS関数」がシェーダから実行される "vs_4_0", // 頂点シェーダ g_flagCompile, // コンパイル・オプション 0, // エフェクトのコンパイル・オプション(なし) NULL, // 直ぐにコンパイルしてから関数を抜ける。 &pBlobVS, // コンパイルされたバイト・コード NULL, // エラーメッセージは不要 NULL); // 戻り値 if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderObj D3DX11CompileShaderFromFile", hr); // 頂点シェーダの作成 hr = g_pD3DDevice->CreateVertexShader( pBlobVS->GetBufferPointer(), // バイト・コードへのポインタ pBlobVS->GetBufferSize(), // バイト・コードの長さ NULL, &g_pVertexShader); // 頂点シェーダを受け取る変数 // SAFE_RELEASE(pBlobVS); // バイト・コードを解放 if (FAILED(hr)) { SAFE_RELEASE(pBlobVS); return DXTRACE_ERR(L"CreateShaderObj g_pD3DDevice->CreateVertexShader", hr); } // ********************************************************** // 入力要素 D3D11_INPUT_ELEMENT_DESC layout[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, sizeof(XMFLOAT3), D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXTURE", 0, DXGI_FORMAT_R32G32_FLOAT, 0, sizeof(XMFLOAT3) * 2, D3D11_INPUT_PER_VERTEX_DATA, 0} }; // 入力レイアウト・オブジェクトの作成 hr = g_pD3DDevice->CreateInputLayout( layout, // 定義の配列 _countof(layout), // 定義の要素数 pBlobVS->GetBufferPointer(), // バイト・コードへのポインタ pBlobVS->GetBufferSize(), // バイト・コードのサイズ &g_pInputLayout); // 受け取る変数のポインタ SAFE_RELEASE(pBlobVS); if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderObj g_pD3DDevice->CreateInputLayout", hr); // ********************************************************** // ピクセル・シェーダのコードをコンパイル ID3DBlob* pBlobPS = NULL; hr = D3DX11CompileFromFile( L"..\\misc\\D3D11Sample17.sh", // ファイル名 NULL, // マクロ定義(なし) NULL, // インクルード・ファイル定義(なし) "PS", // 「PS関数」がシェーダから実行される "ps_4_0", // ピクセル・シェーダ g_flagCompile, // コンパイル・オプション 0, // エフェクトのコンパイル・オプション(なし) NULL, // 直ぐにコンパイルしてから関数を抜ける。 &pBlobPS, // コンパイルされたバイト・コード NULL, // エラーメッセージは不要 NULL); // 戻り値 if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderObj D3DX11CompileShaderFromFile", hr); // ピクセル・シェーダの作成 hr = g_pD3DDevice->CreatePixelShader( pBlobPS->GetBufferPointer(), // バイト・コードへのポインタ pBlobPS->GetBufferSize(), // バイト・コードの長さ NULL, &g_pPixelShader); // ピクセル・シェーダを受け取る変数 SAFE_RELEASE(pBlobPS); // バイト・コードを解放 if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderObj g_pD3DDevice->CreatePixelShader", hr); // ********************************************************** // ブレンド・ステート・オブジェクトの作成 D3D11_BLEND_DESC BlendState; ZeroMemory(&BlendState, sizeof(D3D11_BLEND_DESC)); BlendState.AlphaToCoverageEnable = FALSE; BlendState.IndependentBlendEnable = FALSE; BlendState.RenderTarget[0].BlendEnable = FALSE; BlendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; hr = g_pD3DDevice->CreateBlendState(&BlendState, &g_pBlendState); if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderObj g_pD3DDevice->CreateBlendState", hr); // ********************************************************** // ラスタライザ・ステート・オブジェクトの作成 D3D11_RASTERIZER_DESC RSDesc; RSDesc.FillMode = D3D11_FILL_SOLID; // 普通に描画する RSDesc.CullMode = D3D11_CULL_BACK; // 表面を描画する RSDesc.FrontCounterClockwise = FALSE; // 時計回りが表面 RSDesc.DepthBias = 0; RSDesc.DepthBiasClamp = 0; RSDesc.SlopeScaledDepthBias = 0; RSDesc.DepthClipEnable = TRUE; RSDesc.ScissorEnable = FALSE; RSDesc.MultisampleEnable = FALSE; RSDesc.AntialiasedLineEnable = FALSE; hr = g_pD3DDevice->CreateRasterizerState(&RSDesc, &g_pRasterizerState); if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderObj g_pD3DDevice->CreateRasterizerState", hr); // ********************************************************** // 深度/ステンシル・ステート・オブジェクトの作成 D3D11_DEPTH_STENCIL_DESC DepthStencil; DepthStencil.DepthEnable = TRUE; // 深度テストあり DepthStencil.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; // 書き込む DepthStencil.DepthFunc = D3D11_COMPARISON_LESS; // 手前の物体を描画 DepthStencil.StencilEnable = FALSE; // ステンシル・テストなし DepthStencil.StencilReadMask = 0xff; // ステンシル読み込みマスク。 DepthStencil.StencilWriteMask = 0xff; // ステンシル書き込みマスク。 // 面が表を向いている場合のステンシル・テストの設定 DepthStencil.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // 常に成功 // 面が裏を向いている場合のステンシル・テストの設定 DepthStencil.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // 常に成功 hr = g_pD3DDevice->CreateDepthStencilState(&DepthStencil, &g_pDepthStencilState); if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderObj g_pD3DDevice->CreateDepthStencilState", hr); return hr; }
//----------------------------------------------------------------------------- // Name: CStreamingSound::HandleWaveStreamNotification() // Desc: Handle the notification that tells us to put more wav data in the // circular buffer //----------------------------------------------------------------------------- HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay ) { HRESULT hr; DWORD dwCurrentPlayPos; DWORD dwPlayDelta; DWORD dwBytesWrittenToBuffer; VOID* pDSLockedBuffer = NULL; VOID* pDSLockedBuffer2 = NULL; DWORD dwDSLockedBufferSize; DWORD dwDSLockedBufferSize2; if( m_apDSBuffer == NULL || m_pWaveFile == NULL ) return CO_E_NOTINITIALIZED; // Restore the buffer if it was lost BOOL bRestored; if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) ) return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); if( bRestored ) { // The buffer was restored, so we need to fill it with new data if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) ) return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr ); return S_OK; } // Lock the DirectSound buffer if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, &pDSLockedBuffer, &dwDSLockedBufferSize, &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) ) return DXTRACE_ERR( TEXT("Lock"), hr ); // m_dwDSBufferSize and m_dwNextWriteOffset are both multiples of m_dwNotifySize, // it should the second buffer, so it should never be valid if( pDSLockedBuffer2 != NULL ) return E_UNEXPECTED; if( !m_bFillNextNotificationWithSilence ) { // Fill the DirectSound buffer with wav data if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, dwDSLockedBufferSize, &dwBytesWrittenToBuffer ) ) ) return DXTRACE_ERR( TEXT("Read"), hr ); } else { // Fill the DirectSound buffer with silence FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); dwBytesWrittenToBuffer = dwDSLockedBufferSize; } // If the number of bytes written is less than the // amount we requested, we have a short file. if( dwBytesWrittenToBuffer < dwDSLockedBufferSize ) { if( !bLoopedPlay ) { // Fill in silence for the rest of the buffer. FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, dwDSLockedBufferSize - dwBytesWrittenToBuffer, (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); // Any future notifications should just fill the buffer with silence m_bFillNextNotificationWithSilence = TRUE; } else { // We are looping, so reset the file and fill the buffer with wav data DWORD dwReadSoFar = dwBytesWrittenToBuffer; // From previous call above. while( dwReadSoFar < dwDSLockedBufferSize ) { // This will keep reading in until the buffer is full (for very short files). if( FAILED( hr = m_pWaveFile->ResetFile() ) ) return DXTRACE_ERR( TEXT("ResetFile"), hr ); if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, dwDSLockedBufferSize - dwReadSoFar, &dwBytesWrittenToBuffer ) ) ) return DXTRACE_ERR( TEXT("Read"), hr ); dwReadSoFar += dwBytesWrittenToBuffer; } } } // Unlock the DirectSound buffer m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); // Figure out how much data has been played so far. When we have played // past the end of the file, we will either need to start filling the // buffer with silence or starting reading from the beginning of the file, // depending if the user wants to loop the sound if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) ) return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr ); // Check to see if the position counter looped if( dwCurrentPlayPos < m_dwLastPlayPos ) dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos; else dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos; m_dwPlayProgress += dwPlayDelta; m_dwLastPlayPos = dwCurrentPlayPos; // If we are now filling the buffer with silence, then we have found the end so // check to see if the entire sound has played, if it has then stop the buffer. if( m_bFillNextNotificationWithSilence ) { // We don't want to cut off the sound before it's done playing. if( m_dwPlayProgress >= m_pWaveFile->GetSize() ) { m_apDSBuffer[0]->Stop(); } } // Update where the buffer will lock (for next time) m_dwNextWriteOffset += dwDSLockedBufferSize; m_dwNextWriteOffset %= m_dwDSBufferSize; // Circular buffer return S_OK; }
/*------------------------------------------- シェーダのコンパイル(シャドウ ボリューム描画用) --------------------------------------------*/ HRESULT CreateShaderShadowVolume(void) { HRESULT hr; // ********************************************************** // 頂点シェーダのコードをコンパイル ID3DBlob* pBlobVS = NULL; hr = D3DX11CompileFromFile( L"..\\misc\\D3D11Sample17.sh", // ファイル名 NULL, // マクロ定義(なし) NULL, // インクルード・ファイル定義(なし) "VS_SV", // 「VS_SV関数」がシェーダから実行される "vs_4_0", // 頂点シェーダ g_flagCompile, // コンパイル・オプション 0, // エフェクトのコンパイル・オプション(なし) NULL, // 直ぐにコンパイルしてから関数を抜ける。 &pBlobVS, // コンパイルされたバイト・コード NULL, // エラーメッセージは不要 NULL); // 戻り値 if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadowVolume1 D3DX11CompileShaderFromFile", hr); // 頂点シェーダの作成 hr = g_pD3DDevice->CreateVertexShader( pBlobVS->GetBufferPointer(), // バイト・コードへのポインタ pBlobVS->GetBufferSize(), // バイト・コードの長さ NULL, &g_pVertexShaderSV); // 頂点シェーダを受け取る変数 SAFE_RELEASE(pBlobVS); // バイト・コードを解放 if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadowVolume1 g_pD3DDevice->CreateVertexShader", hr); // ********************************************************** // ジオメトリ・シェーダのコードをコンパイル ID3DBlob* pBlobGS = NULL; hr = D3DX11CompileFromFile( L"..\\misc\\D3D11Sample17.sh", // ファイル名 NULL, // マクロ定義(なし) NULL, // インクルード・ファイル定義(なし) "GS_SV_1", // 「GS_SV_1関数」がシェーダから実行される "gs_4_0", // ジオメトリ・シェーダ g_flagCompile, // コンパイル・オプション 0, // エフェクトのコンパイル・オプション(なし) NULL, // 直ぐにコンパイルしてから関数を抜ける。 &pBlobGS, // コンパイルされたバイト・コード NULL, // エラーメッセージは不要 NULL); // 戻り値 if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadowVolume D3DX11CompileShaderFromFile", hr); // ジオメトリ・シェーダの作成 hr = g_pD3DDevice->CreateGeometryShader( pBlobGS->GetBufferPointer(), // バイト・コードへのポインタ pBlobGS->GetBufferSize(), // バイト・コードの長さ NULL, &g_pGeometryShaderSV1); // ジオメトリ・シェーダを受け取る変数 SAFE_RELEASE(pBlobGS); // バイト・コードを解放 if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadowVolume g_pD3DDevice->CreatePixelShader", hr); hr = D3DX11CompileFromFile( L"..\\misc\\D3D11Sample17.sh", // ファイル名 NULL, // マクロ定義(なし) NULL, // インクルード・ファイル定義(なし) "GS_SV_2", // 「GS_SV_2関数」がシェーダから実行される "gs_4_0", // ジオメトリ・シェーダ g_flagCompile, // コンパイル・オプション 0, // エフェクトのコンパイル・オプション(なし) NULL, // 直ぐにコンパイルしてから関数を抜ける。 &pBlobGS, // コンパイルされたバイト・コード NULL, // エラーメッセージは不要 NULL); // 戻り値 if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadowVolume D3DX11CompileShaderFromFile", hr); // ジオメトリ・シェーダの作成 hr = g_pD3DDevice->CreateGeometryShader( pBlobGS->GetBufferPointer(), // バイト・コードへのポインタ pBlobGS->GetBufferSize(), // バイト・コードの長さ NULL, &g_pGeometryShaderSV2); // ジオメトリ・シェーダを受け取る変数 SAFE_RELEASE(pBlobGS); // バイト・コードを解放 if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadowVolume g_pD3DDevice->CreatePixelShader", hr); // ********************************************************** // ブレンド・ステート・オブジェクトの作成 D3D11_BLEND_DESC BlendState; ZeroMemory(&BlendState, sizeof(D3D11_BLEND_DESC)); BlendState.AlphaToCoverageEnable = FALSE; BlendState.IndependentBlendEnable = FALSE; BlendState.RenderTarget[0].BlendEnable = TRUE; BlendState.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; BlendState.RenderTarget[0].DestBlend = D3D11_BLEND_ONE; BlendState.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; BlendState.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; BlendState.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; BlendState.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; BlendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; hr = g_pD3DDevice->CreateBlendState(&BlendState, &g_pBlendStateSV); if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadowVolume g_pD3DDevice->CreateBlendState", hr); // ********************************************************** // ラスタライザ・ステート・オブジェクトの作成 D3D11_RASTERIZER_DESC RSDesc; RSDesc.FillMode = D3D11_FILL_SOLID; // 普通に描画する RSDesc.CullMode = D3D11_CULL_NONE; // 両面を描画する RSDesc.FrontCounterClockwise = FALSE; // 時計回りが表面 RSDesc.DepthBias = 0; RSDesc.DepthBiasClamp = 0; RSDesc.SlopeScaledDepthBias = 0; RSDesc.DepthClipEnable = TRUE; RSDesc.ScissorEnable = FALSE; RSDesc.MultisampleEnable = FALSE; RSDesc.AntialiasedLineEnable = FALSE; hr = g_pD3DDevice->CreateRasterizerState(&RSDesc, &g_pRasterizerStateSV); if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadowVolume g_pD3DDevice->CreateRasterizerState", hr); // ********************************************************** // 深度/ステンシル・ステート・オブジェクトの作成 D3D11_DEPTH_STENCIL_DESC DepthStencil; DepthStencil.DepthEnable = TRUE; // 深度テストあり DepthStencil.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; // 書き込まない DepthStencil.DepthFunc = D3D11_COMPARISON_LESS; // 手前の物体を描画 DepthStencil.StencilEnable = TRUE; // ステンシル・テストあり DepthStencil.StencilReadMask = 0xff; // ステンシル読み込みマスク。 DepthStencil.StencilWriteMask = 0xff; // ステンシル書き込みマスク。 // 面が表を向いている場合のステンシル・テストの設定 DepthStencil.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.FrontFace.StencilPassOp = D3D11_STENCIL_OP_INCR; // +1 DepthStencil.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // 常に成功 // 面が裏を向いている場合のステンシル・テストの設定 DepthStencil.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.BackFace.StencilPassOp = D3D11_STENCIL_OP_DECR; // −1 DepthStencil.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // 常に成功 hr = g_pD3DDevice->CreateDepthStencilState(&DepthStencil, &g_pDepthStencilStateSV); if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadowVolume g_pD3DDevice->CreateDepthStencilState", hr); return hr; }
HRESULT AnimaApplication::CreateInstance( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { assert( AnimaApplication::mInstance == 0 ); HWND hWnd; WNDCLASSEX winClass; memset( &winClass, 0x0, sizeof(WNDCLASSEX) ); winClass.lpszClassName = "MY_WINDOWS_CLASS"; winClass.cbSize = sizeof(WNDCLASSEX); winClass.style = CS_HREDRAW | CS_VREDRAW; winClass.lpfnWndProc = WindowProc; winClass.hInstance = hInstance; winClass.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON); winClass.hIconSm = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON); winClass.hCursor = LoadCursor(NULL, IDC_ARROW); winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); winClass.lpszMenuName = NULL; winClass.cbClsExtra = 0; winClass.cbWndExtra = 0; if( !RegisterClassEx(&winClass) ) return E_FAIL; hWnd = CreateWindowEx( NULL, "MY_WINDOWS_CLASS", "DX9 Skinning Sample", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, NULL, NULL, hInstance, NULL ); if( hWnd == NULL ) return E_FAIL; // register raw input device RAWINPUTDEVICE Rid[2]; Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC; Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE; Rid[0].dwFlags = RIDEV_INPUTSINK; Rid[0].hwndTarget = hWnd; // Keyboard Rid[1].usUsagePage = HID_USAGE_PAGE_GENERIC; Rid[1].usUsage = 6; Rid[1].dwFlags = 0; Rid[1].hwndTarget=hWnd; RegisterRawInputDevices( Rid, 2, sizeof(Rid[0]) ); ShowWindow( hWnd, nCmdShow ); UpdateWindow( hWnd ); LPWSTR *szArglist; int nArgs; szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs); TestEnvironment* testEnvironment = new TestEnvironment( nArgs, szArglist ); Math::Random::Init( testEnvironment->GetRandomSeed() ); AnimaApplication::mInstance = new AnimaApplication( winClass, hWnd ); char szCurrentDir[2048]; GetCurrentDirectory( sizeof(szCurrentDir), szCurrentDir ); strcat_s(szCurrentDir, "/../Shaders"); Instance()->mShadersWatcher = FindFirstChangeNotification( szCurrentDir, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE); if (Instance()->mShadersWatcher == INVALID_HANDLE_VALUE) DXTRACE_ERR("Unable to monitor shaders directory. Live shaders editing will not work", E_FAIL ); Instance()->mTestEnvironment = testEnvironment; Instance()->mRenderContext = new RenderContext( hWnd, DISPLAY_WIDTH, DISPLAY_HEIGHT ); Instance()->mFramerateCounter = new FramerateCounter; Instance()->mUserInterface = new UserInterface( mInstance->mRenderContext, mInstance->mFramerateCounter ); Instance()->mUserInterface->AcquireResources( Instance()->mRenderContext ); Instance()->mInput = new Input(); Instance()->mCamera = new Camera( *Instance()->mInput, *Instance()->mRenderContext ); // set up renderer Instance()->mModel = new SkeletalModel( "..\\Models\\frank.dae" ); Instance()->mModel->Load( Instance()->mRenderContext ); Instance()->mModel->SetNext( Instance()->mUserInterface ); Instance()->mModel->PlayAnimation( 0, 0.25f ); Instance()->mModelRotationAngle = 0.f; Instance()->mRotateModel = true; Instance()->mFrameCounter = 0; return S_OK; }
/*------------------------------------------- シェーダのコンパイル(シャドウ描画用) --------------------------------------------*/ HRESULT CreateShaderShadow(void) { HRESULT hr; // ********************************************************** // 頂点シェーダのコードをコンパイル ID3DBlob* pBlobVS = NULL; hr = D3DX11CompileFromFile( L"..\\misc\\D3D11Sample17.sh", // ファイル名 NULL, // マクロ定義(なし) NULL, // インクルード・ファイル定義(なし) "VS_S", // 「VS_S関数」がシェーダから実行される "vs_4_0", // 頂点シェーダ g_flagCompile, // コンパイル・オプション 0, // エフェクトのコンパイル・オプション(なし) NULL, // 直ぐにコンパイルしてから関数を抜ける。 &pBlobVS, // コンパイルされたバイト・コード NULL, // エラーメッセージは不要 NULL); // 戻り値 if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadow D3DX11CompileShaderFromFile", hr); // 頂点シェーダの作成 hr = g_pD3DDevice->CreateVertexShader( pBlobVS->GetBufferPointer(), // バイト・コードへのポインタ pBlobVS->GetBufferSize(), // バイト・コードの長さ NULL, &g_pVertexShaderShadow); // 頂点シェーダを受け取る変数 SAFE_RELEASE(pBlobVS); // バイト・コードを解放 if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadow g_pD3DDevice->CreateVertexShader", hr); // ********************************************************** // ピクセル・シェーダのコードをコンパイル ID3DBlob* pBlobPS = NULL; hr = D3DX11CompileFromFile( L"..\\misc\\D3D11Sample17.sh", // ファイル名 NULL, // マクロ定義(なし) NULL, // インクルード・ファイル定義(なし) "PS_S", // 「PS_S関数」がシェーダから実行される "ps_4_0", // ピクセル・シェーダ g_flagCompile, // コンパイル・オプション 0, // エフェクトのコンパイル・オプション(なし) NULL, // 直ぐにコンパイルしてから関数を抜ける。 &pBlobPS, // コンパイルされたバイト・コード NULL, // エラーメッセージは不要 NULL); // 戻り値 if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadow D3DX11CompileShaderFromFile", hr); // ピクセル・シェーダの作成 hr = g_pD3DDevice->CreatePixelShader( pBlobPS->GetBufferPointer(), // バイト・コードへのポインタ pBlobPS->GetBufferSize(), // バイト・コードの長さ NULL, &g_pPixelShaderShadow); // ピクセル・シェーダを受け取る変数 SAFE_RELEASE(pBlobPS); // バイト・コードを解放 if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadow g_pD3DDevice->CreatePixelShader", hr); // ********************************************************** // ブレンド・ステート・オブジェクトの作成 D3D11_BLEND_DESC BlendState; ZeroMemory(&BlendState, sizeof(D3D11_BLEND_DESC)); BlendState.AlphaToCoverageEnable = FALSE; BlendState.IndependentBlendEnable = FALSE; BlendState.RenderTarget[0].BlendEnable = TRUE; BlendState.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; BlendState.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; BlendState.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; BlendState.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; BlendState.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; BlendState.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; BlendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; hr = g_pD3DDevice->CreateBlendState(&BlendState, &g_pBlendStateShadow); if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadow g_pD3DDevice->CreateBlendState", hr); // ********************************************************** // 深度/ステンシル・ステート・オブジェクトの作成 D3D11_DEPTH_STENCIL_DESC DepthStencil; DepthStencil.DepthEnable = TRUE; // 深度テストあり DepthStencil.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; // 書き込まない DepthStencil.DepthFunc = D3D11_COMPARISON_GREATER; // 奥の物体を描画 DepthStencil.StencilEnable = TRUE; // ステンシル・テストあり DepthStencil.StencilReadMask = 0xff; // ステンシル読み込みマスク。 DepthStencil.StencilWriteMask = 0; // ステンシル書き込みマスク。 // 面が表を向いている場合のステンシル・テストの設定 DepthStencil.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.FrontFace.StencilFunc = D3D11_COMPARISON_NOT_EQUAL; // 同じでない場合、成功 // 面が裏を向いている場合のステンシル・テストの設定 DepthStencil.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; // 維持 DepthStencil.BackFace.StencilFunc = D3D11_COMPARISON_NEVER; // 常に失敗 hr = g_pD3DDevice->CreateDepthStencilState(&DepthStencil, &g_pDepthStencilStateShadow); if (FAILED(hr)) return DXTRACE_ERR(L"CreateShaderShadow g_pD3DDevice->CreateDepthStencilState", hr); return hr; }
//----------------------------------------------------------------------------- // Name: CSound::FillBufferWithSound() // Desc: Fills a DirectSound buffer with a sound file //----------------------------------------------------------------------------- HRESULT CSound::FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ) { HRESULT hr; VOID* pDSLockedBuffer = NULL; // Pointer to locked buffer memory DWORD dwDSLockedBufferSize = 0; // Size of the locked DirectSound buffer DWORD dwWavDataRead = 0; // Amount of data read from the wav file if( pDSB == NULL ) return CO_E_NOTINITIALIZED; // Make sure we have focus, and we didn't just switch in from // an app which had a DirectSound device if( FAILED( hr = RestoreBuffer( pDSB, NULL ) ) ) return DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); // Lock the buffer down if( FAILED( hr = pDSB->Lock( 0, m_dwDSBufferSize, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, 0L ) ) ) return DXTRACE_ERR( TEXT("Lock"), hr ); // Reset the wave file to the beginning m_pWaveFile->ResetFile(); if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, dwDSLockedBufferSize, &dwWavDataRead ) ) ) return DXTRACE_ERR( TEXT("Read"), hr ); if( dwWavDataRead == 0 ) { // Wav is blank, so just fill with silence FillMemory( (BYTE*) pDSLockedBuffer, dwDSLockedBufferSize, (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); } else if( dwWavDataRead < dwDSLockedBufferSize ) { // If the wav file was smaller than the DirectSound buffer, // we need to fill the remainder of the buffer with data if( bRepeatWavIfBufferLarger ) { // Reset the file and fill the buffer with wav data DWORD dwReadSoFar = dwWavDataRead; // From previous call above. while( dwReadSoFar < dwDSLockedBufferSize ) { // This will keep reading in until the buffer is full // for very short files if( FAILED( hr = m_pWaveFile->ResetFile() ) ) return DXTRACE_ERR( TEXT("ResetFile"), hr ); hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, dwDSLockedBufferSize - dwReadSoFar, &dwWavDataRead ); if( FAILED(hr) ) return DXTRACE_ERR( TEXT("Read"), hr ); dwReadSoFar += dwWavDataRead; } } else { // Don't repeat the wav file, just fill in silence FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, dwDSLockedBufferSize - dwWavDataRead, (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); } } // Unlock the buffer, we don't need it anymore. pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); return S_OK; }
/*------------------------------------------- バック バッファの初期化(バック バッファを描画ターゲットに設定) --------------------------------------------*/ HRESULT InitBackBuffer(void) { HRESULT hr; // スワップ・チェインから最初のバック・バッファを取得する ID3D11Texture2D *pBackBuffer; // バッファのアクセスに使うインターフェイス hr = g_pSwapChain->GetBuffer( 0, // バック・バッファの番号 __uuidof(ID3D11Texture2D), // バッファにアクセスするインターフェイス (LPVOID*)&pBackBuffer); // バッファを受け取る変数 if(FAILED(hr)) return DXTRACE_ERR(L"InitBackBuffer g_pSwapChain->GetBuffer", hr); // 失敗 // バック・バッファの情報 D3D11_TEXTURE2D_DESC descBackBuffer; pBackBuffer->GetDesc(&descBackBuffer); // バック・バッファの描画ターゲット・ビューを作る hr = g_pD3DDevice->CreateRenderTargetView( pBackBuffer, // ビューでアクセスするリソース NULL, // 描画ターゲット・ビューの定義 &g_pRenderTargetView); // 描画ターゲット・ビューを受け取る変数 SAFE_RELEASE(pBackBuffer); // 以降、バック・バッファは直接使わないので解放 if(FAILED(hr)) return DXTRACE_ERR(L"InitBackBuffer g_pD3DDevice->CreateRenderTargetView", hr); // 失敗 // 深度/ステンシル・テクスチャの作成 D3D11_TEXTURE2D_DESC descDepth = descBackBuffer; // descDepth.Width = descBackBuffer.Width; // 幅 // descDepth.Height = descBackBuffer.Height; // 高さ descDepth.MipLevels = 1; // ミップマップ・レベル数 descDepth.ArraySize = 1; // 配列サイズ descDepth.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT; // フォーマット(深度+ステンシル) // descDepth.SampleDesc.Count = 1; // マルチサンプリングの設定 // descDepth.SampleDesc.Quality = 0; // マルチサンプリングの品質 descDepth.Usage = D3D11_USAGE_DEFAULT; // デフォルト使用法 descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; // 深度/ステンシルとして使用 descDepth.CPUAccessFlags = 0; // CPUからはアクセスしない descDepth.MiscFlags = 0; // その他の設定なし hr = g_pD3DDevice->CreateTexture2D( &descDepth, // 作成する2Dテクスチャの設定 NULL, // &g_pDepthStencil); // 作成したテクスチャを受け取る変数 if (FAILED(hr)) return DXTRACE_ERR(L"InitBackBuffer g_pD3DDevice->CreateTexture2D", hr); // 失敗 // 深度/ステンシル ビューの作成 D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; descDSV.Format = descDepth.Format; // ビューのフォーマット descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; descDSV.Flags = 0; descDSV.Texture2D.MipSlice = 0; hr = g_pD3DDevice->CreateDepthStencilView( g_pDepthStencil, // 深度/ステンシル・ビューを作るテクスチャ &descDSV, // 深度/ステンシル・ビューの設定 &g_pDepthStencilView); // 作成したビューを受け取る変数 if (FAILED(hr)) return DXTRACE_ERR(L"InitBackBuffer g_pD3DDevice->CreateDepthStencilView", hr); // 失敗 // ビューポートの設定 g_ViewPort[0].TopLeftX = 0.0f; // ビューポート領域の左上X座標。 g_ViewPort[0].TopLeftY = 0.0f; // ビューポート領域の左上Y座標。 g_ViewPort[0].Width = (FLOAT)descBackBuffer.Width; // ビューポート領域の幅 g_ViewPort[0].Height = (FLOAT)descBackBuffer.Height; // ビューポート領域の高さ g_ViewPort[0].MinDepth = 0.0f; // ビューポート領域の深度値の最小値 g_ViewPort[0].MaxDepth = 1.0f; // ビューポート領域の深度値の最大値 // 定数バッファを更新 // 射影変換行列(パースペクティブ(透視法)射影) XMMATRIX mat = XMMatrixPerspectiveFovLH( XMConvertToRadians(30.0f), // 視野角30° (float)descBackBuffer.Width / (float)descBackBuffer.Height, // アスペクト比 1.0f, // 前方投影面までの距離 400.0f); // 後方投影面までの距離 mat = XMMatrixTranspose(mat); XMStoreFloat4x4(&g_cbCBuffer.Projection, mat); //サイズを保存 g_sizeWindow.cx = descBackBuffer.Width; g_sizeWindow.cy = descBackBuffer.Height; return S_OK; }
//----------------------------------------------------------------------------- // Name: CWaveFile::ReadMMIO() // Desc: Support function for reading from a multimedia I/O stream. // m_hmmio must be valid before calling. This function uses it to // update m_ckRiff, and m_pwfx. //----------------------------------------------------------------------------- HRESULT CWaveFile::ReadMMIO() { MMCKINFO ckIn; // chunk info. for general use. PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. m_pwfx = NULL; if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); // Check to make sure this is a valid wave file if( (m_ckRiff.ckid != FOURCC_RIFF) || (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) return DXTRACE_ERR( TEXT("mmioFOURCC"), E_FAIL ); // Search the input file for for the 'fmt ' chunk. ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); // Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>; // if there are extra parameters at the end, we'll ignore them if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); // Read the 'fmt ' chunk into <pcmWaveFormat>. if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); // Allocate the waveformatex, but if its not pcm format, read the next // word, and thats how many extra bytes to allocate. if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) { m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; if( NULL == m_pwfx ) return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL ); // Copy the bytes from the pcm structure to the waveformatex structure memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); m_pwfx->cbSize = 0; } else { // Read in length of extra bytes. WORD cbExtraBytes = 0L; if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; if( NULL == m_pwfx ) return DXTRACE_ERR( TEXT("new"), E_FAIL ); // Copy the bytes from the pcm structure to the waveformatex structure memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); m_pwfx->cbSize = cbExtraBytes; // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), cbExtraBytes ) != cbExtraBytes ) { SAFE_DELETE( m_pwfx ); return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); } } // Ascend the input file out of the 'fmt ' chunk. if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) { SAFE_DELETE( m_pwfx ); return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); } return S_OK; }
/* CDirect3D::ResetDevice resets the device called if surface was lost or the settings/display size require a device reset ----- returns true if successful, false otherwise */ bool CDirect3D::ResetDevice() { if(!init_done) return false; HRESULT hr; //release prior to reset DestroyDrawSurface(); if(cgAvailable) { cgShader->OnLostDevice(); cgD3D9SetDevice(NULL); } if(effect) effect->OnLostDevice(); //zero or unknown values result in the current window size/display settings dPresentParams.BackBufferWidth = 0; dPresentParams.BackBufferHeight = 0; dPresentParams.BackBufferCount = GUI.DoubleBuffered?2:1; dPresentParams.BackBufferFormat = D3DFMT_UNKNOWN; dPresentParams.FullScreen_RefreshRateInHz = 0; dPresentParams.Windowed = true; dPresentParams.PresentationInterval = GUI.Vsync?D3DPRESENT_INTERVAL_ONE:D3DPRESENT_INTERVAL_IMMEDIATE; if(fullscreen) { dPresentParams.BackBufferWidth = GUI.FullscreenMode.width; dPresentParams.BackBufferHeight = GUI.FullscreenMode.height; dPresentParams.BackBufferCount = GUI.DoubleBuffered?2:1; dPresentParams.Windowed = false; if(GUI.FullscreenMode.depth == 32) dPresentParams.BackBufferFormat = D3DFMT_X8R8G8B8; else dPresentParams.BackBufferFormat = D3DFMT_R5G6B5; dPresentParams.FullScreen_RefreshRateInHz = GUI.FullscreenMode.rate; } if(FAILED(hr = pDevice->Reset(&dPresentParams))) { DXTRACE_ERR(TEXT("Unable to reset device"), hr); return false; } if(effect) effect->OnResetDevice(); if(cgAvailable) { cgD3D9SetDevice(pDevice); cgShader->OnResetDevice(); } pDevice->SetRenderState(D3DRS_LIGHTING, FALSE); pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); //recreate the surface CreateDrawSurface(); SetViewport(); return true; }
//----------------------------------------------------------------------------- // Name: CWaveFile::WriteMMIO() // Desc: Support function for reading from a multimedia I/O stream // pwfxDest is the WAVEFORMATEX for this new wave file. // m_hmmio must be valid before calling. This function uses it to // update m_ckRiff, and m_ck. //----------------------------------------------------------------------------- HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest ) { DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile. MMCKINFO ckOut1; dwFactChunk = (DWORD)-1; // Create the output file RIFF chunk of form type 'WAVE'. m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E'); m_ckRiff.cksize = 0; if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ) return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); // We are now descended into the 'RIFF' chunk we just created. // Now create the 'fmt ' chunk. Since we know the size of this chunk, // specify it in the MMCKINFO structure so MMIO doesn't have to seek // back and set the chunk size after ascending from the chunk. m_ck.ckid = mmioFOURCC('f', 'm', 't', ' '); m_ck.cksize = sizeof(PCMWAVEFORMAT); if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) { if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT)) return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); } else { // Write the variable length size. if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, sizeof(*pwfxDest) + pwfxDest->cbSize ) != ( sizeof(*pwfxDest) + pwfxDest->cbSize ) ) return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); } // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) ) return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); // Now create the fact chunk, not required for PCM but nice to have. This is filled // in when the close routine is called. ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); ckOut1.cksize = 0; if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) ) return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != sizeof(dwFactChunk) ) return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL ); // Now ascend out of the fact chunk... if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) ) return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); return S_OK; }
/** MMIOストリームから読み込み * * @author SAM (T&GG, Org.)<*****@*****.**> * @date 2004/01/21 2:36:59 * Copyright (C) 2001,2002,2003,2004 SAM (T&GG, Org.). All rights reserved. */ HRslt WavFile::readMMIO() { MMCKINFO ckin; // chunk info. for general use. PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. wfx_ = NULL; if(mmioDescend(hmmio_, &ckriff_, NULL, 0)) return DXTRACE_ERR(TEXT("mmioDescend"), E_FAIL); // Check to make sure this is a valid wave file if( (ckriff_.ckid != FOURCC_RIFF) || (ckriff_.fccType != mmioFOURCC('W','A','V','E') ) ) return DXTRACE_ERR( TEXT("mmioFOURCC"), E_FAIL ); // Search the input file for for the 'fmt ' chunk. ckin.ckid = mmioFOURCC('f','m','t',' '); if(mmioDescend(hmmio_, &ckin, &ckriff_, MMIO_FINDCHUNK) ) return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); // Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>; // if there are extra parameters at the end, we'll ignore them if(ckin.cksize < sizeof(PCMWAVEFORMAT)) return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); // Read the 'fmt ' chunk into <pcmWaveFormat>. if( mmioRead( hmmio_, (HPSTR) &pcmWaveFormat, sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); // Allocate the waveformatex, but if its not pcm format, read the next // word, and thats how many extra bytes to allocate. if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) { wfx_ = reinterpret_cast<WAVEFORMATEX *>(malloc( sizeof(WAVEFORMATEX) )); if(!wfx_) return DXTRACE_ERR( TEXT("wfx_"), E_OUTOFMEMORY ); // Copy the bytes from the pcm structure to the waveformatex structure memcpy( wfx_, &pcmWaveFormat, sizeof(pcmWaveFormat) ); wfx_->cbSize = 0; } else { // Read in length of extra bytes. WORD cbExtraBytes = 0L; if( mmioRead( hmmio_, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); wfx_ = reinterpret_cast<WAVEFORMATEX *>(malloc( sizeof(WAVEFORMATEX) + cbExtraBytes )); if(!wfx_) return DXTRACE_ERR( TEXT("new"), E_OUTOFMEMORY ); // Copy the bytes from the pcm structure to the waveformatex structure memcpy( wfx_, &pcmWaveFormat, sizeof(pcmWaveFormat) ); wfx_->cbSize = cbExtraBytes; // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. if( mmioRead( hmmio_, (CHAR*)(((BYTE*)&(wfx_->cbSize))+sizeof(WORD)), cbExtraBytes ) != cbExtraBytes ) { SAFE_FREE( wfx_ ); return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); } } // Ascend the input file out of the 'fmt ' chunk. if( 0 != mmioAscend( hmmio_, &ckin, 0 ) ) { SAFE_FREE( wfx_ ); return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); } return S_OK; }
//----------------------------------------------------------------------------- // Name: MainDlgProc() // Desc: Handles dialog messages //----------------------------------------------------------------------------- INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam ) { HRESULT hr; switch( msg ) { case WM_COMMAND: switch( LOWORD(wParam) ) { case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break; case IDC_SOUNDFILE: OnOpenSoundFile( hDlg ); break; case IDC_PLAY: if( FAILED( hr = OnPlaySound( hDlg ) ) ) { DXTRACE_ERR( TEXT("OnPlaySound"), hr ); MessageBox( hDlg, "Error playing DirectSound buffer." "Sample will now exit.", "DirectSound Sample", MB_OK | MB_ICONERROR ); EndDialog( hDlg, IDABORT ); } break; case IDC_STOP: SAFE_RELEASE( g_pIGargle ); if( g_pSound ) { g_pSound->Stop(); g_pSound->Reset(); } break; case IDC_WAVEFORM_TRIANGLE: case IDC_WAVEFORM_SQUARE: OnEffectChanged( hDlg ); break; default: return FALSE; // Didn't handle message } break; case WM_TIMER: OnTimer( hDlg ); break; case WM_INITDIALOG: OnInitDialog( hDlg ); break; case WM_NOTIFY: OnEffectChanged( hDlg ); break; case WM_DESTROY: // Cleanup everything KillTimer( hDlg, 1 ); SAFE_RELEASE( g_pIGargle ); SAFE_DELETE( g_pSound ); SAFE_DELETE( g_pSoundManager ); break; default: return FALSE; // Didn't handle message } return TRUE; // Handled message }
//----------------------------------------------------------------------------- // Name: CSoundManager::CreateFromMemory() // Desc: //----------------------------------------------------------------------------- HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, BYTE* pbData, ULONG ulDataSize, LPWAVEFORMATEX pwfx, DWORD dwCreationFlags, GUID guid3DAlgorithm, DWORD dwNumBuffers ) { HRESULT hr; DWORD i; IDirectSoundBuffer** apDSBuffer = NULL; DWORD dwDSBufferSize = NULL; CWaveFile* pWaveFile = NULL; if( m_pDS == NULL ) return CO_E_NOTINITIALIZED; if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 ) return E_INVALIDARG; apDSBuffer = new IDirectSoundBuffer*[dwNumBuffers]; if( apDSBuffer == NULL ) { hr = E_OUTOFMEMORY; goto LFail; } pWaveFile = new CWaveFile(); if( pWaveFile == NULL ) { hr = E_OUTOFMEMORY; goto LFail; } pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ ); // Make the DirectSound buffer the same size as the wav file dwDSBufferSize = ulDataSize; // Create the direct sound buffer, and only request the flags needed // since each requires some overhead and limits if the buffer can // be hardware accelerated DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = dwCreationFlags; dsbd.dwBufferBytes = dwDSBufferSize; dsbd.guid3DAlgorithm = guid3DAlgorithm; dsbd.lpwfxFormat = pwfx; if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) ) { DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); goto LFail; } // Default to use DuplicateSoundBuffer() when created extra buffers since always // create a buffer that uses the same memory however DuplicateSoundBuffer() will fail if // DSBCAPS_CTRLFX is used, so use CreateSoundBuffer() instead in this case. if( (dwCreationFlags & DSBCAPS_CTRLFX) == 0 ) { for( i=1; i<dwNumBuffers; i++ ) { if( FAILED( hr = m_pDS->DuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) ) { DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr ); goto LFail; } } } else { for( i=1; i<dwNumBuffers; i++ ) { hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[i], NULL ); if( FAILED(hr) ) { DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr ); goto LFail; } } } // Create the sound *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile, dwCreationFlags ); SAFE_DELETE_ARRAY( apDSBuffer ); return S_OK; LFail: // Cleanup SAFE_DELETE_ARRAY( apDSBuffer ); return hr; }
/* =============== idAudioBufferWIN32::FillBufferWithSound =============== */ int idAudioBufferWIN32::FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, bool bRepeatWavIfBufferLarger ) { int hr; void* pDSLockedBuffer = NULL; // Pointer to locked buffer memory ulong dwDSLockedBufferSize = 0; // Size of the locked DirectSound buffer int dwWavDataRead = 0; // Amount of data read from the wav file if( pDSB == NULL ) return -1; // we may not even have a wavefile if (m_pWaveFile==NULL) { return -1; } // Make sure we have focus, and we didn't just switch in from // an app which had a DirectSound device if( FAILED( hr = RestoreBuffer( pDSB, NULL ) ) ) { DXTRACE_ERR( TEXT("RestoreBuffer"), hr ); return -1; } // Lock the buffer down if( FAILED( hr = pDSB->Lock( 0, m_dwDSBufferSize, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, 0L ) ) ) { DXTRACE_ERR( TEXT("Lock"), hr ); return -1; } // Reset the wave file to the beginning m_pWaveFile->ResetFile(); if( FAILED( hr = m_pWaveFile->Read( (byte*) pDSLockedBuffer, dwDSLockedBufferSize, &dwWavDataRead ) ) ) { return DXTRACE_ERR( TEXT("Read"), hr ); } if( dwWavDataRead == 0 ) { // Wav is blank, so just fill with silence memset( pDSLockedBuffer, (byte)(m_pWaveFile->mpwfx.Format.wBitsPerSample == 8 ? 128 : 0 ), dwDSLockedBufferSize ); } else if( dwWavDataRead < (int)dwDSLockedBufferSize ) { // If the wav file was smaller than the DirectSound buffer, // we need to fill the remainder of the buffer with data if( bRepeatWavIfBufferLarger ) { // Reset the file and fill the buffer with wav data int dwReadSoFar = dwWavDataRead; // From previous call above. while( dwReadSoFar < (int)dwDSLockedBufferSize ) { // This will keep reading in until the buffer is full // for very short files if( FAILED( hr = m_pWaveFile->ResetFile() ) ) { return DXTRACE_ERR( TEXT("ResetFile"), hr ); } hr = m_pWaveFile->Read( (byte*)pDSLockedBuffer + dwReadSoFar, dwDSLockedBufferSize - dwReadSoFar, &dwWavDataRead ); if( FAILED(hr) ) { return DXTRACE_ERR( TEXT("Read"), hr ); } dwReadSoFar += dwWavDataRead; } } else { // Don't repeat the wav file, just fill in silence memset( (byte*) pDSLockedBuffer + dwWavDataRead, (byte)(m_pWaveFile->mpwfx.Format.wBitsPerSample == 8 ? 128 : 0 ), dwDSLockedBufferSize - dwWavDataRead); } } // Unlock the buffer, we don't need it anymore. pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); return S_OK; }
//----------------------------------------------------------------------------- // Name: OnInitDialog() // Desc: Initializes the dialogs (sets up UI controls, etc.) //----------------------------------------------------------------------------- VOID OnInitDialog( HWND hDlg ) { HRESULT hr; // Load the icon #ifdef _WIN64 HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE ); #else HINSTANCE hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE ); #endif HICON hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDR_MAINFRAME ) ); // Create a static IDirectSound in the CSound class. // Set coop level to DSSCL_PRIORITY, and set primary buffer // format to stereo, 22kHz and 16-bit output. g_pSoundManager = new CSoundManager(); hr = g_pSoundManager->Initialize( hDlg, DSSCL_PRIORITY, 2, 22050, 16 ); // Get the 3D listener, so we can control its params hr |= g_pSoundManager->Get3DListenerInterface( &g_pDSListener ); if( FAILED(hr) ) { DXTRACE_ERR( TEXT("Get3DListenerInterface"), hr ); MessageBox( hDlg, "Error initializing DirectSound. Sample will now exit.", "DirectSound Sample", MB_OK | MB_ICONERROR ); EndDialog( hDlg, IDABORT ); return; } // Get listener parameters g_dsListenerParams.dwSize = sizeof(DS3DLISTENER); g_pDSListener->GetAllParameters( &g_dsListenerParams ); // Set the icon for this dialog. PostMessage( hDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon ); // Set big icon PostMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon ); // Set small icon // Create a timer to periodically move the 3D object around SetTimer( hDlg, IDT_MOVEMENT_TIMER, 0, NULL ); // Set the UI controls SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") ); SetDlgItemText( hDlg, IDC_STATUS, TEXT("No file loaded.") ); // Get handles to dialog items HWND hDopplerSlider = GetDlgItem( hDlg, IDC_DOPPLER_SLIDER ); HWND hRolloffSlider = GetDlgItem( hDlg, IDC_ROLLOFF_SLIDER ); HWND hMinDistSlider = GetDlgItem( hDlg, IDC_MINDISTANCE_SLIDER ); HWND hMaxDistSlider = GetDlgItem( hDlg, IDC_MAXDISTANCE_SLIDER ); HWND hVertSlider = GetDlgItem( hDlg, IDC_VERTICAL_SLIDER ); HWND hHorzSlider = GetDlgItem( hDlg, IDC_HORIZONTAL_SLIDER ); // Set the range and position of the sliders PostMessage( hDopplerSlider, TBM_SETRANGEMAX, TRUE, 40L ); PostMessage( hDopplerSlider, TBM_SETRANGEMIN, TRUE, 0L ); PostMessage( hRolloffSlider, TBM_SETRANGEMAX, TRUE, 40L ); PostMessage( hRolloffSlider, TBM_SETRANGEMIN, TRUE, 0L ); PostMessage( hMinDistSlider, TBM_SETRANGEMAX, TRUE, 40L ); PostMessage( hMinDistSlider, TBM_SETRANGEMIN, TRUE, 1L ); PostMessage( hMaxDistSlider, TBM_SETRANGEMAX, TRUE, 40L ); PostMessage( hMaxDistSlider, TBM_SETRANGEMIN, TRUE, 1L ); PostMessage( hVertSlider, TBM_SETRANGEMAX, TRUE, 100L ); PostMessage( hVertSlider, TBM_SETRANGEMIN, TRUE, -100L ); PostMessage( hVertSlider, TBM_SETPOS, TRUE, 100L ); PostMessage( hHorzSlider, TBM_SETRANGEMAX, TRUE, 100L ); PostMessage( hHorzSlider, TBM_SETRANGEMIN, TRUE, -100L ); PostMessage( hHorzSlider, TBM_SETPOS, TRUE, 100L ); // Set the position of the sliders SetSlidersPos( hDlg, 0.0f, 0.0f, ORBIT_MAX_RADIUS, ORBIT_MAX_RADIUS*2.0f ); }