//-------------------------------------------------------------------------------------- // Load PCM wave data into a in-memory IXACT3Wave* //-------------------------------------------------------------------------------------- HRESULT LoadWaveFileInMemory( IXACT3Engine* pXACTEngine, WCHAR* strFile, DWORD dwSeconds, DWORD dwSampleRate, DWORD dwChannels, DWORD dwBits, IXACT3Wave** ppXACTWave, BYTE** ppWaveBuffer ) { HRESULT hr; WCHAR strFilePath[MAX_PATH]; if( FAILED( hr = FindMediaFileCch( strFilePath, MAX_PATH, strFile ) ) ) return hr; // Open PCM audio data in file HANDLE hFile = CreateFile( strFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 ); if( hFile == INVALID_HANDLE_VALUE ) return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ); DWORD dwBlockAlign = dwChannels * dwBits / 8; DWORD dwTotalNumBytes = dwSeconds * dwSampleRate * dwBlockAlign; // Initialize WAVEBANKENTRY struct WAVEBANKENTRY entry; entry.Format.wFormatTag = WAVEBANKMINIFORMAT_TAG_PCM; entry.Format.wBitsPerSample = ( dwBits == 16 ) ? WAVEBANKMINIFORMAT_BITDEPTH_16 : WAVEBANKMINIFORMAT_BITDEPTH_8; entry.Format.nChannels = dwChannels; entry.Format.wBlockAlign = dwChannels * ( dwBits / 8 ); entry.Format.nSamplesPerSec = dwSampleRate; entry.Duration = dwSeconds * dwSampleRate; entry.LoopRegion.dwStartSample = 0; entry.LoopRegion.dwTotalSamples = 0; entry.PlayRegion.dwOffset = 0; entry.PlayRegion.dwLength = dwTotalNumBytes; entry.dwFlags = 0; BYTE* pXACTWaveBuffer = new BYTE[dwTotalNumBytes]; DWORD dwBytesRead = 0; // Read PCM audio data from a file ReadFile( hFile, pXACTWaveBuffer, 44, &dwBytesRead, NULL ); // Skip wave format chunk ReadFile( hFile, pXACTWaveBuffer, dwTotalNumBytes, &dwBytesRead, NULL ); if( dwBytesRead != dwTotalNumBytes ) { SAFE_DELETE_ARRAY( pXACTWaveBuffer ); CloseHandle( hFile ); return E_FAIL; } CloseHandle( hFile ); // Create an in-memory IXACTWave interface using wave file data if( FAILED( hr = pXACTEngine->PrepareInMemoryWave( XACT_FLAG_UNITS_MS, entry, NULL, pXACTWaveBuffer, 0, 0, ppXACTWave ) ) ) { SAFE_DELETE_ARRAY( pXACTWaveBuffer ); return hr; } return S_OK; }
//-------------------------------------------------------------------------------------- // Load PCM wave data into a streaming IXACT3Wave* //-------------------------------------------------------------------------------------- HRESULT LoadWaveFileStreaming( IXACT3Engine* pXACTEngine, WCHAR* strFile, DWORD dwSeconds, DWORD dwSampleRate, DWORD dwChannels, DWORD dwBits, IXACT3Wave** ppXACTWave, HANDLE* phStreamingFile ) { HRESULT hr; WCHAR strFilePath[MAX_PATH]; if( FAILED( hr = FindMediaFileCch( strFilePath, MAX_PATH, strFile ) ) ) return hr; // Open PCM audio data in file HANDLE hFile = CreateFile( strFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 ); if( hFile == INVALID_HANDLE_VALUE ) return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ); DWORD dwBlockAlign = dwChannels * dwBits / 8; DWORD dwTotalNumBytes = dwSeconds * dwSampleRate * dwBlockAlign; // Initialize WAVEBANKENTRY struct WAVEBANKENTRY entry; entry.Format.wFormatTag = WAVEBANKMINIFORMAT_TAG_PCM; entry.Format.wBitsPerSample = ( dwBits == 16 ) ? WAVEBANKMINIFORMAT_BITDEPTH_16 : WAVEBANKMINIFORMAT_BITDEPTH_8; entry.Format.nChannels = dwChannels; entry.Format.wBlockAlign = dwChannels * ( dwBits / 8 ); entry.Format.nSamplesPerSec = dwSampleRate; entry.Duration = dwSeconds * dwSampleRate; entry.LoopRegion.dwStartSample = 0; entry.LoopRegion.dwTotalSamples = 0; entry.PlayRegion.dwOffset = 0; entry.PlayRegion.dwLength = dwTotalNumBytes; entry.dwFlags = 0; // Load PCM into an streaming IXACTWave *phStreamingFile = hFile; XACT_STREAMING_PARAMETERS streamingParams; streamingParams.file = hFile; streamingParams.flags = 0; streamingParams.offset = 44; streamingParams.packetSize = ( WORD )dwBits; // Create an streaming IXACTWave interface using wave file data if( FAILED( hr = pXACTEngine->PrepareStreamingWave( XACT_FLAG_UNITS_MS, entry, streamingParams, 4096, NULL, 0, 0, ppXACTWave ) ) ) { return hr; } return S_OK; }
void CSoundManager::Load( const std::string& file_name ) { std::map< std::string, CSoundWav* >::iterator it = m_buffers.find( file_name ) ; if( it != m_buffers.end() ) return ; HRESULT hr; CSoundWav* p_wav = new CSoundWav() ; // // Locate the wave file // WCHAR strFilePath[MAX_PATH] = {0} ; WCHAR w_path[256] = {0} ; DXconvAnsiToWide( w_path, file_name.c_str(), (file_name.length()+1) ) ; if( FAILED( hr = FindMediaFileCch( strFilePath, MAX_PATH, w_path ) ) ) { #ifdef _DEBUG WCHAR d_buff[256] = {0} ; std::string d_str = "サウンドデータのロードに失敗 001 : " + file_name ; DXconvAnsiToWide( d_buff, d_str.c_str(), (d_str.length()+1) ) ; DXUTTRACE( L"\n------------------------------------------------------------\n" ) ; DXUTTRACE( d_buff ) ; DXUTTRACE( L"\n------------------------------------------------------------\n" ) ; #endif return ; } // // Read in the wave file // if( FAILED( hr = p_wav->m_wav.Open( strFilePath, NULL, WAVEFILE_READ ) ) ) { #ifdef _DEBUG WCHAR d_buff[256] = {0} ; std::string d_str = "サウンドデータのロードに失敗 002 : " + file_name ; DXconvAnsiToWide( d_buff, d_str.c_str(), (d_str.length()+1) ) ; DXUTTRACE( L"\n------------------------------------------------------------\n" ) ; DXUTTRACE( d_buff ) ; DXUTTRACE( L"\n------------------------------------------------------------\n" ) ; #endif return ; } // Get format of wave file WAVEFORMATEX* pwfx = p_wav->m_wav.GetFormat(); // Calculate how many bytes and samples are in the wave DWORD cbWaveSize = p_wav->m_wav.GetSize(); // Read the sample data into memory p_wav->m_p_buffer = new BYTE[ cbWaveSize ]; if( FAILED( hr = p_wav->m_wav.Read( p_wav->m_p_buffer, cbWaveSize, &cbWaveSize ) ) ) { SAFE_DELETE_ARRAY( p_wav->m_p_buffer ); #ifdef _DEBUG WCHAR d_buff[256] = {0} ; std::string d_str = "サウンドデータのロードに失敗 003 : " + file_name ; DXconvAnsiToWide( d_buff, d_str.c_str(), (d_str.length()+1) ) ; DXUTTRACE( L"\n------------------------------------------------------------\n" ) ; DXUTTRACE( d_buff ) ; DXUTTRACE( L"\n------------------------------------------------------------\n" ) ; #endif return ; } m_buffers.insert( std::make_pair( file_name, p_wav ) ) ; }
//----------------------------------------------------------------------------------------- // This function does the following steps: // // 1. Initialize XACT by calling pEngine->Initialize // 2. Register for the XACT notification desired // 3. Create the in memory XACT wave bank(s) you want to use // 4. Create the streaming XACT wave bank(s) you want to use // 5. Create the XACT sound bank(s) you want to use // 6. Store indices to the XACT cue(s) your game uses //----------------------------------------------------------------------------------------- HRESULT PrepareXACT() { HRESULT hr; WCHAR str[MAX_PATH]; HANDLE hFile; DWORD dwFileSize; DWORD dwBytesRead; HANDLE hMapFile; // Clear struct ZeroMemory( &g_audioState, sizeof( AUDIO_STATE ) ); InitializeCriticalSection( &g_audioState.cs ); hr = CoInitializeEx( NULL, COINIT_MULTITHREADED ); // COINIT_APARTMENTTHREADED will work too if( SUCCEEDED( hr ) ) { // Switch to auditioning mode based on command line. Change if desired bool bAuditionMode = DoesCommandLineContainAuditionSwitch(); bool bDebugMode = false; DWORD dwCreationFlags = 0; if( bAuditionMode ) dwCreationFlags |= XACT_FLAG_API_AUDITION_MODE; if( bDebugMode ) dwCreationFlags |= XACT_FLAG_API_DEBUG_MODE; hr = XACT3CreateEngine( dwCreationFlags, &g_audioState.pEngine ); } if( FAILED( hr ) || g_audioState.pEngine == NULL ) return E_FAIL; // Initialize & create the XACT runtime XACT_RUNTIME_PARAMETERS xrParams = {0}; xrParams.lookAheadTime = XACT_ENGINE_LOOKAHEAD_DEFAULT; xrParams.fnNotificationCallback = XACTNotificationCallback; hr = g_audioState.pEngine->Initialize( &xrParams ); if( FAILED( hr ) ) return hr; //----------------------------------------------------------------------------------------- // Register for XACT notifications //----------------------------------------------------------------------------------------- // The "wave bank prepared" notification will let the app know when it is save to use // play cues that reference streaming wave data. XACT_NOTIFICATION_DESCRIPTION desc = {0}; desc.flags = XACT_FLAG_NOTIFICATION_PERSIST; desc.type = XACTNOTIFICATIONTYPE_WAVEBANKPREPARED; g_audioState.pEngine->RegisterNotification( &desc ); // The "sound bank destroyed" notification will let the app know when it is save to use // play cues that reference streaming wave data. desc.flags = XACT_FLAG_NOTIFICATION_PERSIST; desc.type = XACTNOTIFICATIONTYPE_SOUNDBANKDESTROYED; g_audioState.pEngine->RegisterNotification( &desc ); // The "cue stop" notification will let the app know when it a song stops so a new one // can be played desc.flags = XACT_FLAG_NOTIFICATION_PERSIST; desc.type = XACTNOTIFICATIONTYPE_CUESTOP; desc.cueIndex = XACTINDEX_INVALID; g_audioState.pEngine->RegisterNotification( &desc ); // The "cue prepared" notification will let the app know when it a a cue that uses // streaming data has been prepared so it is ready to be used for zero latency streaming desc.flags = XACT_FLAG_NOTIFICATION_PERSIST; desc.type = XACTNOTIFICATIONTYPE_CUEPREPARED; desc.cueIndex = XACTINDEX_INVALID; g_audioState.pEngine->RegisterNotification( &desc ); if( FAILED( hr = FindMediaFileCch( str, MAX_PATH, L"InMemoryWaveBank.xwb" ) ) ) return hr; // Create an "in memory" XACT wave bank file using memory mapped file IO hr = E_FAIL; // assume failure hFile = CreateFile( str, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); if( hFile != INVALID_HANDLE_VALUE ) { dwFileSize = GetFileSize( hFile, NULL ); if( dwFileSize != -1 ) { hMapFile = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, dwFileSize, NULL ); if( hMapFile ) { g_audioState.pbInMemoryWaveBank = MapViewOfFile( hMapFile, FILE_MAP_READ, 0, 0, 0 ); if( g_audioState.pbInMemoryWaveBank ) { hr = g_audioState.pEngine->CreateInMemoryWaveBank( g_audioState.pbInMemoryWaveBank, dwFileSize, 0, 0, &g_audioState.pInMemoryWaveBank ); } CloseHandle( hMapFile ); // pbInMemoryWaveBank maintains a handle on the file so close this unneeded handle } } CloseHandle( hFile ); // pbInMemoryWaveBank maintains a handle on the file so close this unneeded handle } if( FAILED( hr ) ) return E_FAIL; // CleanupXACT() will cleanup state before exiting //----------------------------------------------------------------------------------------- // Create a streaming XACT wave bank file. // Take note of the following: // 1) This wave bank in the XACT project file must marked as a streaming wave bank // This is set inside the XACT authoring tool) // 2) Use FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING flags when opening the file // 3) To use cues that reference this streaming wave bank, you must wait for the // wave bank to prepared first or the playing the cue will fail //----------------------------------------------------------------------------------------- if( FAILED( hr = FindMediaFileCch( str, MAX_PATH, L"StreamingWaveBank.xwb" ) ) ) return hr; hr = E_FAIL; // assume failure g_audioState.hStreamingWaveBankFile = CreateFile( str, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL ); if( g_audioState.hStreamingWaveBankFile != INVALID_HANDLE_VALUE ) { XACT_WAVEBANK_STREAMING_PARAMETERS wsParams; ZeroMemory( &wsParams, sizeof( XACT_WAVEBANK_STREAMING_PARAMETERS ) ); wsParams.file = g_audioState.hStreamingWaveBankFile; wsParams.offset = 0; // 64 means to allocate a 64 * 2k buffer for streaming. // This is a good size for DVD streaming and takes good advantage of the read ahead cache wsParams.packetSize = 64; hr = g_audioState.pEngine->CreateStreamingWaveBank( &wsParams, &g_audioState.pStreamingWaveBank ); } if( FAILED( hr ) ) return E_FAIL; // CleanupXACT() will cleanup state before exiting // Create the XACT sound bank file with using memory mapped file IO if( FAILED( hr = FindMediaFileCch( str, MAX_PATH, L"sounds.xsb" ) ) ) return hr; hr = E_FAIL; // assume failure hFile = CreateFile( str, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); if( hFile != INVALID_HANDLE_VALUE ) { dwFileSize = GetFileSize( hFile, NULL ); if( dwFileSize != -1 ) { // Allocate the data here and free the data when recieving the sound bank destroyed notification g_audioState.pbSoundBank = new BYTE[dwFileSize]; if( g_audioState.pbSoundBank ) { if( 0 != ReadFile( hFile, g_audioState.pbSoundBank, dwFileSize, &dwBytesRead, NULL ) ) { hr = g_audioState.pEngine->CreateSoundBank( g_audioState.pbSoundBank, dwFileSize, 0, 0, &g_audioState.pSoundBank ); } } } CloseHandle( hFile ); // pbInMemoryWaveBank maintains a handle on the file so close this unneeded handle } if( FAILED( hr ) ) return E_FAIL; // CleanupXACT() will cleanup state before exiting // Get the cue indices from the sound bank g_audioState.iZap = g_audioState.pSoundBank->GetCueIndex( "zap" ); g_audioState.iRev = g_audioState.pSoundBank->GetCueIndex( "rev" ); for( int i = 0; i < 3; i++ ) { CHAR sz[256]; StringCchPrintfA( sz, 256, "song%d", i + 1 ); g_audioState.iSong[i] = g_audioState.pSoundBank->GetCueIndex( sz ); } return S_OK; }
//-------------------------------------------------------------------------------------- HRESULT InitResources( ID3D10Device* pd3dDevice ) { HRESULT hr = S_OK; DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS; #if defined( DEBUG ) || defined( _DEBUG ) // Set the D3D10_SHADER_DEBUG flag to embed debug information in the shaders. // Setting this flag improves the shader debugging experience, but still allows // the shaders to be optimized and to run exactly the way they will run in // the release configuration of this program. dwShaderFlags |= D3D10_SHADER_DEBUG; #endif // Read the D3DX effect file WCHAR str[MAX_PATH]; hr = FindMediaFileCch( str, MAX_PATH, L"GPUSpectrogram.fx" ); if( FAILED( hr ) ) return hr; hr = D3DX10CreateEffectFromFile( str, NULL, NULL, "fx_4_0", dwShaderFlags, 0, pd3dDevice, NULL, NULL, &g_pEffect10, NULL, NULL ); if( FAILED( hr ) ) return hr; // Obtain the technique handles g_pReverse = g_pEffect10->GetTechniqueByName( "Reverse" ); g_pFFTInner = g_pEffect10->GetTechniqueByName( "FFTInner" ); g_pRenderQuad = g_pEffect10->GetTechniqueByName( "RenderQuad" ); g_ptxSource = g_pEffect10->GetVariableByName( "g_txSource" )->AsShaderResource(); g_pTextureSize = g_pEffect10->GetVariableByName( "g_TextureSize" )->AsVector(); g_pWR = g_pEffect10->GetVariableByName( "g_WR" )->AsScalar(); g_pWI = g_pEffect10->GetVariableByName( "g_WI" )->AsScalar(); g_pMMAX = g_pEffect10->GetVariableByName( "g_MMAX" )->AsScalar(); g_pM = g_pEffect10->GetVariableByName( "g_M" )->AsScalar(); g_pISTEP = g_pEffect10->GetVariableByName( "g_ISTEP" )->AsScalar(); hr = LoadAudioIntoBuffer( pd3dDevice, g_uiTexX, g_strWaveName ); if( FAILED( hr ) ) return hr; D3DXVECTOR4 vTextureSize( ( float )g_uiTexX, ( float )g_uiTexY, 0.0f, 0.0f ); g_pTextureSize->SetFloatVector( ( float* )vTextureSize ); // Create our quad vertex input layout const D3D10_INPUT_ELEMENT_DESC quadlayout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXTURE", 0, DXGI_FORMAT_R32G32_UINT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; D3D10_PASS_DESC PassDesc; g_pReverse->GetPassByIndex( 0 )->GetDesc( &PassDesc ); hr = pd3dDevice->CreateInputLayout( quadlayout, sizeof( quadlayout ) / sizeof( quadlayout[0] ), PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pQuadVertexLayout ); if( FAILED( hr ) ) return hr; hr = CreateQuad( pd3dDevice, g_uiTexX, g_uiTexY ); if( FAILED( hr ) ) return hr; return hr; }