XAudio2BasicSound.cpp
上传用户:May-22
上传日期:2015-07-19
资源大小:7113k
文件大小:9k
源码类别:

DirextX编程

开发平台:

Visual C++

  1. //--------------------------------------------------------------------------------------
  2. // File: XAudio2BasicSound.cpp
  3. //
  4. // XNA Developer Connection
  5. // (C) Copyright Microsoft Corp.  All rights reserved.
  6. //--------------------------------------------------------------------------------------
  7. #define _WIN32_DCOM
  8. #define _CRT_SECURE_NO_DEPRECATE
  9. #include <windows.h>
  10. #include <xaudio2.h>
  11. #include <strsafe.h>
  12. #include <shellapi.h>
  13. #include <mmsystem.h>
  14. #include <conio.h>
  15. #include "SDKwavefile.h"
  16. //--------------------------------------------------------------------------------------
  17. // Helper macros
  18. //--------------------------------------------------------------------------------------
  19. #ifndef SAFE_DELETE_ARRAY
  20. #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p);   (p)=NULL; } }
  21. #endif
  22. #ifndef SAFE_RELEASE
  23. #define SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }
  24. #endif
  25. //--------------------------------------------------------------------------------------
  26. // Forward declaration
  27. //--------------------------------------------------------------------------------------
  28. HRESULT PlayPCM( IXAudio2* pXaudio2, LPCWSTR szFilename );
  29. HRESULT FindMediaFileCch( WCHAR* strDestPath, int cchDest, LPCWSTR strFilename );
  30. //--------------------------------------------------------------------------------------
  31. // Entry point to the program
  32. //--------------------------------------------------------------------------------------
  33. int main()
  34. {
  35.     HRESULT hr;
  36.     //
  37.     // Initialize XAudio2
  38.     //
  39.     CoInitializeEx( NULL, COINIT_MULTITHREADED );
  40.     IXAudio2* pXAudio2 = NULL;
  41.     UINT32 flags = 0;
  42. #ifdef _DEBUG
  43.     flags |= XAUDIO2_DEBUG_ENGINE;
  44. #endif
  45.     if ( FAILED(hr = XAudio2Create( &pXAudio2, flags ) ) )
  46.     {
  47.         wprintf( L"Failed to init XAudio2 engine: %#Xn", hr );
  48.         CoUninitialize();
  49.         return 0;
  50.     }
  51.     //
  52.     // Create a mastering voice
  53.     //
  54.     IXAudio2MasteringVoice* pMasteringVoice = NULL;
  55.     if ( FAILED(hr = pXAudio2->CreateMasteringVoice( &pMasteringVoice ) ) )
  56.     {
  57.         wprintf( L"Failed creating mastering voice: %#Xn", hr );
  58.         SAFE_RELEASE( pXAudio2 );
  59.         CoUninitialize();
  60.         return 0;
  61.     }
  62.     //
  63.     // Play a PCM wave file
  64.     //
  65.     wprintf( L"Playing mono WAV PCM file..." );
  66.     if ( FAILED (hr = PlayPCM( pXAudio2, L"Media\Wavs\MusicMono.wav" ) ) )
  67.     {
  68.         wprintf( L"Failed creating source voice: %#Xn", hr );
  69.         SAFE_RELEASE( pXAudio2 );
  70.         CoUninitialize();
  71.         return 0;
  72.     }
  73.     //
  74. // Play a 5.1 PCM wave extensible file
  75. //
  76.     wprintf( L"nPlaying 5.1 WAV PCM file..." );
  77.     if ( FAILED (hr = PlayPCM( pXAudio2, L"Media\Wavs\MusicSurround.wav" ) ) )
  78.     {
  79.         wprintf( L"Failed creating source voice: %#Xn", hr );
  80.         SAFE_RELEASE( pXAudio2 );
  81.         CoUninitialize();
  82.         return 0;
  83.     }
  84.     //
  85.     // Cleanup XAudio2
  86.     //
  87.     wprintf( L"nFinished playingn" );
  88.     // All XAudio2 interfaces are released when the engine is destroyed, but being tidy
  89.     pMasteringVoice->DestroyVoice();
  90.     SAFE_RELEASE( pXAudio2 );
  91.     CoUninitialize();
  92. }
  93. //--------------------------------------------------------------------------------------
  94. // Name: PlayPCM
  95. // Desc: Plays a wave and blocks until the wave finishes playing
  96. //--------------------------------------------------------------------------------------
  97. HRESULT PlayPCM( IXAudio2* pXaudio2, LPCWSTR szFilename )
  98. {
  99.     HRESULT hr = S_OK;
  100.     //
  101.     // Locate the wave file
  102.     //
  103.     WCHAR strFilePath[MAX_PATH];
  104.     if( FAILED( hr = FindMediaFileCch( strFilePath, MAX_PATH, szFilename ) ) )
  105.     {
  106.         wprintf( L"Failed to find media file: %sn", szFilename);
  107.         return hr;
  108.     }
  109.     //
  110.     // Read in the wave file
  111.     //
  112.     CWaveFile wav;
  113.     if ( FAILED(hr = wav.Open( strFilePath, NULL, WAVEFILE_READ ) ) )
  114.     {
  115.         wprintf( L"Failed reading WAV file: %#X (%s)n", hr, strFilePath );
  116.         return hr;
  117.     }
  118.     // Get format of wave file
  119.     WAVEFORMATEX* pwfx = wav.GetFormat();
  120.     // Calculate how many bytes and samples are in the wave
  121.     DWORD cbWaveSize = wav.GetSize();
  122.     // Read the sample data into memory
  123.     BYTE* pbWaveData = new BYTE[ cbWaveSize ];
  124.     if( FAILED(hr = wav.Read( pbWaveData, cbWaveSize, &cbWaveSize ) ) )
  125.     {
  126.         wprintf( L"Failed to read WAV data: %#Xn", hr );
  127.         SAFE_DELETE_ARRAY( pbWaveData );
  128.         return hr;
  129.     }
  130.     //
  131.     // Play the wave using a XAudio2SourceVoice
  132.     //
  133.     // Create the source voice
  134.     IXAudio2SourceVoice* pSourceVoice;
  135.     if( FAILED(hr = pXaudio2->CreateSourceVoice( &pSourceVoice, pwfx ) ) )
  136.     {
  137.         wprintf( L"Error %#X creating source voicen", hr );
  138.         SAFE_DELETE_ARRAY( pbWaveData );
  139.         return hr;
  140.     }
  141.     // Submit the wave sample data using an XAUDIO2_BUFFER structure
  142.     XAUDIO2_BUFFER buffer = {0};
  143.     buffer.pAudioData = pbWaveData;
  144.     buffer.Flags = XAUDIO2_END_OF_STREAM;  // tell the source voice not to expect any data after this buffer
  145.     buffer.AudioBytes = cbWaveSize;
  146.     if( FAILED(hr = pSourceVoice->SubmitSourceBuffer( &buffer ) ) )
  147.     {
  148.         wprintf( L"Error %#X submitting source buffern", hr );
  149.         pSourceVoice->DestroyVoice();
  150.         SAFE_DELETE_ARRAY( pbWaveData );
  151.         return hr;
  152.     }
  153.     hr = pSourceVoice->Start( 0 );
  154.     // Let the sound play
  155.     BOOL isRunning = TRUE;
  156.     while( SUCCEEDED(hr) && isRunning )
  157.     {
  158.         XAUDIO2_VOICE_STATE state;
  159.         if( FAILED(hr = pSourceVoice->GetState( &state ) ) )
  160.         {
  161.             wprintf( L"Error %#X getting voice statusn", hr );
  162.             pSourceVoice->DestroyVoice();
  163.             SAFE_DELETE_ARRAY( pbWaveData );
  164.             return hr;
  165.         }
  166.         isRunning = (state.BuffersQueued > 0) != 0;
  167.         // Wait till the escape key is pressed
  168.         if ( GetAsyncKeyState( VK_ESCAPE ) )
  169.             break;
  170.         Sleep(10);
  171.     }
  172.     // Wait till the escape key is released
  173.     while( GetAsyncKeyState( VK_ESCAPE ) )
  174.         Sleep(10);
  175.     pSourceVoice->DestroyVoice();
  176.     SAFE_DELETE_ARRAY( pbWaveData );
  177.     return hr;
  178. }
  179. //--------------------------------------------------------------------------------------
  180. // Helper function to try to find the location of a media file
  181. //--------------------------------------------------------------------------------------
  182. HRESULT FindMediaFileCch( WCHAR* strDestPath, int cchDest, LPCWSTR strFilename )
  183. {
  184.     bool bFound = false;
  185.     if( NULL==strFilename || strFilename[0] == 0 || NULL==strDestPath || cchDest < 10 )
  186.         return E_INVALIDARG;
  187.     // Get the exe name, and exe path
  188.     WCHAR strExePath[MAX_PATH] = {0};
  189.     WCHAR strExeName[MAX_PATH] = {0};
  190.     WCHAR* strLastSlash = NULL;
  191.     GetModuleFileName( NULL, strExePath, MAX_PATH );
  192.     strExePath[MAX_PATH-1]=0;
  193.     strLastSlash = wcsrchr( strExePath, TEXT('\') );
  194.     if( strLastSlash )
  195.     {
  196.         StringCchCopy( strExeName, MAX_PATH, &strLastSlash[1] );
  197.         // Chop the exe name from the exe path
  198.         *strLastSlash = 0;
  199.         // Chop the .exe from the exe name
  200.         strLastSlash = wcsrchr( strExeName, TEXT('.') );
  201.         if( strLastSlash )
  202.             *strLastSlash = 0;
  203.     }
  204.     StringCchCopy( strDestPath, cchDest, strFilename );
  205.     if( GetFileAttributes( strDestPath ) != 0xFFFFFFFF )
  206.         return true;
  207.     // Search all parent directories starting at . and using strFilename as the leaf name
  208.     WCHAR strLeafName[MAX_PATH] = {0};
  209.     StringCchCopy( strLeafName, MAX_PATH, strFilename );
  210.     WCHAR strFullPath[MAX_PATH] = {0};
  211.     WCHAR strFullFileName[MAX_PATH] = {0};
  212.     WCHAR strSearch[MAX_PATH] = {0};
  213.     WCHAR* strFilePart = NULL;
  214.     GetFullPathName( L".", MAX_PATH, strFullPath, &strFilePart );
  215.     if( strFilePart == NULL )
  216.         return false;
  217.     while( strFilePart != NULL && *strFilePart != '' )
  218.     {
  219.         StringCchPrintf( strFullFileName, MAX_PATH, L"%s\%s", strFullPath, strLeafName );
  220.         if( GetFileAttributes( strFullFileName ) != 0xFFFFFFFF )
  221.         {
  222.             StringCchCopy( strDestPath, cchDest, strFullFileName );
  223.             bFound = true;
  224.             break;
  225.         }
  226.         StringCchPrintf( strFullFileName, MAX_PATH, L"%s\%s\%s", strFullPath, strExeName, strLeafName );
  227.         if( GetFileAttributes( strFullFileName ) != 0xFFFFFFFF )
  228.         {
  229.             StringCchCopy( strDestPath, cchDest, strFullFileName );
  230.             bFound = true;
  231.             break;
  232.         }
  233.         StringCchPrintf( strSearch, MAX_PATH, L"%s\..", strFullPath );
  234.         GetFullPathName( strSearch, MAX_PATH, strFullPath, &strFilePart );
  235.     }
  236.     if( bFound )
  237.         return S_OK;
  238.     // On failure, return the file as the path but also return an error code
  239.     StringCchCopy( strDestPath, cchDest, strFilename );
  240.     return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  241. }