dsutil.cpp
上传用户:hxb_1234
上传日期:2010-03-30
资源大小:8328k
文件大小:37k
源码类别:

VC书籍

开发平台:

Visual C++

  1. #define STRICT
  2. #include <windows.h>
  3. #include <mmsystem.h>
  4. #include <dxerr9.h>
  5. #include <dsound.h>
  6. #include "DXUtil.h"
  7. #include "DSUtil.h"
  8. CSoundManager::CSoundManager()
  9. {
  10.     m_pDS = NULL;
  11. }
  12. CSoundManager::~CSoundManager()
  13. {
  14.     SAFE_RELEASE( m_pDS ); 
  15. }
  16. HRESULT CSoundManager::Initialize( HWND  hWnd, 
  17.                                    DWORD dwCoopLevel )
  18. {
  19.     HRESULT             hr;
  20.     SAFE_RELEASE( m_pDS );
  21.     
  22.     if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) )
  23.         return DXTRACE_ERR( TEXT("DirectSoundCreate8"), hr );
  24.     
  25.     if( FAILED( hr = m_pDS->SetCooperativeLevel( hWnd, dwCoopLevel ) ) )
  26.         return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr );   
  27.     return S_OK;
  28. }
  29. HRESULT CSoundManager::SetPrimaryBufferFormat( DWORD dwPrimaryChannels, 
  30.                                                DWORD dwPrimaryFreq, 
  31.                                                DWORD dwPrimaryBitRate )
  32. {
  33.     HRESULT             hr;
  34.     LPDIRECTSOUNDBUFFER pDSBPrimary = NULL;
  35.     if( m_pDS == NULL )
  36.         return CO_E_NOTINITIALIZED;
  37.     
  38.     DSBUFFERDESC dsbd;
  39.     ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
  40.     dsbd.dwSize        = sizeof(DSBUFFERDESC);
  41.     dsbd.dwFlags       = DSBCAPS_PRIMARYBUFFER;
  42.     dsbd.dwBufferBytes = 0;
  43.     dsbd.lpwfxFormat   = NULL;
  44.        
  45.     if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) )
  46.         return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr );
  47.     WAVEFORMATEX wfx;
  48.     ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); 
  49.     wfx.wFormatTag      = (WORD) WAVE_FORMAT_PCM; 
  50.     wfx.nChannels       = (WORD) dwPrimaryChannels; 
  51.     wfx.nSamplesPerSec  = (DWORD) dwPrimaryFreq; 
  52.     wfx.wBitsPerSample  = (WORD) dwPrimaryBitRate; 
  53.     wfx.nBlockAlign     = (WORD) (wfx.wBitsPerSample / 8 * wfx.nChannels);
  54.     wfx.nAvgBytesPerSec = (DWORD) (wfx.nSamplesPerSec * wfx.nBlockAlign);
  55.     if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) )
  56.         return DXTRACE_ERR( TEXT("SetFormat"), hr );
  57.     SAFE_RELEASE( pDSBPrimary );
  58.     return S_OK;
  59. }
  60. HRESULT CSoundManager::Get3DListenerInterface( LPDIRECTSOUND3DLISTENER* ppDSListener )
  61. {
  62.     HRESULT             hr;
  63.     DSBUFFERDESC        dsbdesc;
  64.     LPDIRECTSOUNDBUFFER pDSBPrimary = NULL;
  65.     if( ppDSListener == NULL )
  66.         return E_INVALIDARG;
  67.     if( m_pDS == NULL )
  68.         return CO_E_NOTINITIALIZED;
  69.     *ppDSListener = NULL;
  70.     
  71.     ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
  72.     dsbdesc.dwSize = sizeof(DSBUFFERDESC);
  73.     dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER;
  74.     if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary, NULL ) ) )
  75.         return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr );
  76.     if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, 
  77.                                                   (VOID**)ppDSListener ) ) )
  78.     {
  79.         SAFE_RELEASE( pDSBPrimary );
  80.         return DXTRACE_ERR( TEXT("QueryInterface"), hr );
  81.     }
  82.     
  83.     SAFE_RELEASE( pDSBPrimary );
  84.     return S_OK;
  85. }
  86. HRESULT CSoundManager::Create( CSound** ppSound, 
  87.                                LPTSTR strWaveFileName, 
  88.                                DWORD dwCreationFlags, 
  89.                                GUID guid3DAlgorithm,
  90.                                DWORD dwNumBuffers )
  91. {
  92.     HRESULT hr;
  93.     HRESULT hrRet = S_OK;
  94.     DWORD   i;
  95.     LPDIRECTSOUNDBUFFER* apDSBuffer     = NULL;
  96.     DWORD                dwDSBufferSize = NULL;
  97.     CWaveFile*           pWaveFile      = NULL;
  98.     if( m_pDS == NULL )
  99.         return CO_E_NOTINITIALIZED;
  100.     if( strWaveFileName == NULL || ppSound == NULL || dwNumBuffers < 1 )
  101.         return E_INVALIDARG;
  102.     apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers];
  103.     if( apDSBuffer == NULL )
  104.     {
  105.         hr = E_OUTOFMEMORY;
  106.         goto LFail;
  107.     }
  108.     pWaveFile = new CWaveFile();
  109.     if( pWaveFile == NULL )
  110.     {
  111.         hr = E_OUTOFMEMORY;
  112.         goto LFail;
  113.     }
  114.     pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ );
  115.     if( pWaveFile->GetSize() == 0 )
  116.     {
  117.         
  118.         hr = E_FAIL;
  119.         goto LFail;
  120.     }
  121.     
  122.     dwDSBufferSize = pWaveFile->GetSize();
  123.     
  124.     
  125.     
  126.     DSBUFFERDESC dsbd;
  127.     ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
  128.     dsbd.dwSize          = sizeof(DSBUFFERDESC);
  129.     dsbd.dwFlags         = dwCreationFlags;
  130.     dsbd.dwBufferBytes   = dwDSBufferSize;
  131.     dsbd.guid3DAlgorithm = guid3DAlgorithm;
  132.     dsbd.lpwfxFormat     = pWaveFile->m_pwfx;
  133.     
  134.     
  135.     
  136.     hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL );
  137.     
  138.     
  139.     if( hr == DS_NO_VIRTUALIZATION )
  140.         hrRet = DS_NO_VIRTUALIZATION;
  141.             
  142.     if( FAILED(hr) )
  143.     {
  144.         
  145.         
  146.         
  147.         
  148.         
  149.         
  150.         DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr );
  151.                     
  152.         goto LFail;
  153.     }
  154.     
  155.     
  156.     
  157.     if( (dwCreationFlags & DSBCAPS_CTRLFX) == 0 )
  158.     {
  159.         for( i=1; i<dwNumBuffers; i++ )
  160.         {
  161.             if( FAILED( hr = m_pDS->DuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) )
  162.             {
  163.                 DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr );
  164.                 goto LFail;
  165.             }
  166.         }
  167.     }
  168.     else
  169.     {
  170.         for( i=1; i<dwNumBuffers; i++ )
  171.         {
  172.             hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[i], NULL );
  173.             if( FAILED(hr) )
  174.             {
  175.                 DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr );
  176.                 goto LFail;
  177.             }
  178.         }
  179.    }
  180.     
  181.     
  182.     *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile, dwCreationFlags );
  183.     
  184.     SAFE_DELETE( apDSBuffer );
  185.     return hrRet;
  186. LFail:
  187.     
  188.     SAFE_DELETE( pWaveFile );
  189.     SAFE_DELETE( apDSBuffer );
  190.     return hr;
  191. }
  192. HRESULT CSoundManager::CreateFromMemory( CSound** ppSound, 
  193.                                         BYTE* pbData,
  194.                                         ULONG  ulDataSize,
  195.                                         LPWAVEFORMATEX pwfx,
  196.                                         DWORD dwCreationFlags, 
  197.                                         GUID guid3DAlgorithm,
  198.                                         DWORD dwNumBuffers )
  199. {
  200.     HRESULT hr;
  201.     DWORD   i;
  202.     LPDIRECTSOUNDBUFFER* apDSBuffer     = NULL;
  203.     DWORD                dwDSBufferSize = NULL;
  204.     CWaveFile*           pWaveFile      = NULL;
  205.     if( m_pDS == NULL )
  206.         return CO_E_NOTINITIALIZED;
  207.     if( pbData == NULL || ppSound == NULL || dwNumBuffers < 1 )
  208.         return E_INVALIDARG;
  209.     apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers];
  210.     if( apDSBuffer == NULL )
  211.     {
  212.         hr = E_OUTOFMEMORY;
  213.         goto LFail;
  214.     }
  215.     pWaveFile = new CWaveFile();
  216.     if( pWaveFile == NULL )
  217.     {
  218.         hr = E_OUTOFMEMORY;
  219.         goto LFail;
  220.     }
  221.     pWaveFile->OpenFromMemory( pbData,ulDataSize, pwfx, WAVEFILE_READ );
  222.     
  223.     dwDSBufferSize = ulDataSize;
  224.     
  225.     
  226.     
  227.     DSBUFFERDESC dsbd;
  228.     ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
  229.     dsbd.dwSize          = sizeof(DSBUFFERDESC);
  230.     dsbd.dwFlags         = dwCreationFlags;
  231.     dsbd.dwBufferBytes   = dwDSBufferSize;
  232.     dsbd.guid3DAlgorithm = guid3DAlgorithm;
  233.     dsbd.lpwfxFormat     = pwfx;
  234.     if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[0], NULL ) ) )
  235.     {
  236.         DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr );
  237.         goto LFail;
  238.     }
  239.     
  240.     
  241.     
  242.     if( (dwCreationFlags & DSBCAPS_CTRLFX) == 0 )
  243.     {
  244.         for( i=1; i<dwNumBuffers; i++ )
  245.         {
  246.             if( FAILED( hr = m_pDS->DuplicateSoundBuffer( apDSBuffer[0], &apDSBuffer[i] ) ) )
  247.             {
  248.                 DXTRACE_ERR( TEXT("DuplicateSoundBuffer"), hr );
  249.                 goto LFail;
  250.             }
  251.         }
  252.     }
  253.     else
  254.     {
  255.         for( i=1; i<dwNumBuffers; i++ )
  256.         {
  257.             hr = m_pDS->CreateSoundBuffer( &dsbd, &apDSBuffer[i], NULL );
  258.             if( FAILED(hr) )
  259.             {
  260.                 DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr );
  261.                 goto LFail;
  262.             }
  263.         }
  264.    }
  265.     
  266.     *ppSound = new CSound( apDSBuffer, dwDSBufferSize, dwNumBuffers, pWaveFile, dwCreationFlags );
  267.     SAFE_DELETE( apDSBuffer );
  268.     return S_OK;
  269. LFail:
  270.     
  271.    
  272.     SAFE_DELETE( apDSBuffer );
  273.     return hr;
  274. }
  275. HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound, 
  276.                                         LPTSTR strWaveFileName, 
  277.                                         DWORD dwCreationFlags, 
  278.                                         GUID guid3DAlgorithm,
  279.                                         DWORD dwNotifyCount, 
  280.                                         DWORD dwNotifySize, 
  281.                                         HANDLE hNotifyEvent )
  282. {
  283.     HRESULT hr;
  284.     if( m_pDS == NULL )
  285.         return CO_E_NOTINITIALIZED;
  286.     if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL )
  287.         return E_INVALIDARG;
  288.     LPDIRECTSOUNDBUFFER pDSBuffer      = NULL;
  289.     DWORD               dwDSBufferSize = NULL;
  290.     CWaveFile*          pWaveFile      = NULL;
  291.     DSBPOSITIONNOTIFY*  aPosNotify     = NULL; 
  292.     LPDIRECTSOUNDNOTIFY pDSNotify      = NULL;
  293.     pWaveFile = new CWaveFile();
  294.     if( pWaveFile == NULL )
  295.         return E_OUTOFMEMORY;
  296.     pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ );
  297.     
  298.     dwDSBufferSize = dwNotifySize * dwNotifyCount;
  299.     
  300.     
  301.     
  302.     DSBUFFERDESC dsbd;
  303.     ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
  304.     dsbd.dwSize          = sizeof(DSBUFFERDESC);
  305.     dsbd.dwFlags         = dwCreationFlags | 
  306.                            DSBCAPS_CTRLPOSITIONNOTIFY | 
  307.                            DSBCAPS_GETCURRENTPOSITION2;
  308.     dsbd.dwBufferBytes   = dwDSBufferSize;
  309.     dsbd.guid3DAlgorithm = guid3DAlgorithm;
  310.     dsbd.lpwfxFormat     = pWaveFile->m_pwfx;
  311.     if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) )
  312.     {
  313.         
  314.         
  315.         if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG )
  316.             return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr );
  317.         return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr );
  318.     }
  319.     
  320.     
  321.     if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify, 
  322.                                                 (VOID**)&pDSNotify ) ) )
  323.     {
  324.         SAFE_DELETE_ARRAY( aPosNotify );
  325.         return DXTRACE_ERR( TEXT("QueryInterface"), hr );
  326.     }
  327.     aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ];
  328.     if( aPosNotify == NULL )
  329.         return E_OUTOFMEMORY;
  330.     for( DWORD i = 0; i < dwNotifyCount; i++ )
  331.     {
  332.         aPosNotify[i].dwOffset     = (dwNotifySize * i) + dwNotifySize - 1;
  333.         aPosNotify[i].hEventNotify = hNotifyEvent;             
  334.     }
  335.     
  336.     
  337.     
  338.     if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount, 
  339.                                                           aPosNotify ) ) )
  340.     {
  341.         SAFE_RELEASE( pDSNotify );
  342.         SAFE_DELETE_ARRAY( aPosNotify );
  343.         return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr );
  344.     }
  345.     SAFE_RELEASE( pDSNotify );
  346.     SAFE_DELETE_ARRAY( aPosNotify );
  347.     
  348.     *ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize );
  349.     return S_OK;
  350. }
  351. CSound::CSound( LPDIRECTSOUNDBUFFER* apDSBuffer, DWORD dwDSBufferSize, 
  352.                 DWORD dwNumBuffers, CWaveFile* pWaveFile, DWORD dwCreationFlags )
  353. {
  354.     DWORD i;
  355.     m_apDSBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers];
  356.     if( NULL != m_apDSBuffer )
  357.     {
  358.         for( i=0; i<dwNumBuffers; i++ )
  359.             m_apDSBuffer[i] = apDSBuffer[i];
  360.     
  361.         m_dwDSBufferSize = dwDSBufferSize;
  362.         m_dwNumBuffers   = dwNumBuffers;
  363.         m_pWaveFile      = pWaveFile;
  364.         m_dwCreationFlags = dwCreationFlags;
  365.         
  366.         FillBufferWithSound( m_apDSBuffer[0], FALSE );
  367.     }
  368. }
  369. CSound::~CSound()
  370. {
  371.     for( DWORD i=0; i<m_dwNumBuffers; i++ )
  372.     {
  373.         SAFE_RELEASE( m_apDSBuffer[i] ); 
  374.     }
  375.     SAFE_DELETE_ARRAY( m_apDSBuffer ); 
  376.     SAFE_DELETE( m_pWaveFile );
  377. }
  378. HRESULT CSound::FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger )
  379. {
  380.     HRESULT hr; 
  381.     VOID*   pDSLockedBuffer      = NULL; 
  382.     DWORD   dwDSLockedBufferSize = 0;    
  383.     DWORD   dwWavDataRead        = 0;    
  384.     if( pDSB == NULL )
  385.         return CO_E_NOTINITIALIZED;
  386.     
  387.     
  388.     if( FAILED( hr = RestoreBuffer( pDSB, NULL ) ) ) 
  389.         return DXTRACE_ERR( TEXT("RestoreBuffer"), hr );
  390.     
  391.     if( FAILED( hr = pDSB->Lock( 0, m_dwDSBufferSize, 
  392.                                  &pDSLockedBuffer, &dwDSLockedBufferSize, 
  393.                                  NULL, NULL, 0L ) ) )
  394.         return DXTRACE_ERR( TEXT("Lock"), hr );
  395.     
  396.     m_pWaveFile->ResetFile();
  397.     if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer,
  398.                                         dwDSLockedBufferSize, 
  399.                                         &dwWavDataRead ) ) )           
  400.         return DXTRACE_ERR( TEXT("Read"), hr );
  401.     if( dwWavDataRead == 0 )
  402.     {
  403.         
  404.         FillMemory( (BYTE*) pDSLockedBuffer, 
  405.                     dwDSLockedBufferSize, 
  406.                     (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) );
  407.     }
  408.     else if( dwWavDataRead < dwDSLockedBufferSize )
  409.     {
  410.         
  411.         
  412.         if( bRepeatWavIfBufferLarger )
  413.         {       
  414.             
  415.             DWORD dwReadSoFar = dwWavDataRead;    
  416.             while( dwReadSoFar < dwDSLockedBufferSize )
  417.             {  
  418.                 
  419.                 
  420.                 if( FAILED( hr = m_pWaveFile->ResetFile() ) )
  421.                     return DXTRACE_ERR( TEXT("ResetFile"), hr );
  422.                 hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar,
  423.                                         dwDSLockedBufferSize - dwReadSoFar,
  424.                                         &dwWavDataRead );
  425.                 if( FAILED(hr) )
  426.                     return DXTRACE_ERR( TEXT("Read"), hr );
  427.                 dwReadSoFar += dwWavDataRead;
  428.             } 
  429.         }
  430.         else
  431.         {
  432.             
  433.             FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, 
  434.                         dwDSLockedBufferSize - dwWavDataRead, 
  435.                         (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) );
  436.         }
  437.     }
  438.     
  439.     pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );
  440.     return S_OK;
  441. }
  442. HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored )
  443. {
  444.     HRESULT hr;
  445.     if( pDSB == NULL )
  446.         return CO_E_NOTINITIALIZED;
  447.     if( pbWasRestored )
  448.         *pbWasRestored = FALSE;
  449.     DWORD dwStatus;
  450.     if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) )
  451.         return DXTRACE_ERR( TEXT("GetStatus"), hr );
  452.     if( dwStatus & DSBSTATUS_BUFFERLOST )
  453.     {
  454.         
  455.         
  456.         
  457.         
  458.         do 
  459.         {
  460.             hr = pDSB->Restore();
  461.             if( hr == DSERR_BUFFERLOST )
  462.                 Sleep( 10 );
  463.         }
  464.         while( ( hr = pDSB->Restore() ) == DSERR_BUFFERLOST );
  465.         if( pbWasRestored != NULL )
  466.             *pbWasRestored = TRUE;
  467.         return S_OK;
  468.     }
  469.     else
  470.     {
  471.         return S_FALSE;
  472.     }
  473. }
  474. LPDIRECTSOUNDBUFFER CSound::GetFreeBuffer()
  475. {
  476.     if( m_apDSBuffer == NULL )
  477.         return FALSE; 
  478.     for( DWORD i=0; i<m_dwNumBuffers; i++ )
  479.     {
  480.         if( m_apDSBuffer[i] )
  481.         {  
  482.             DWORD dwStatus = 0;
  483.             m_apDSBuffer[i]->GetStatus( &dwStatus );
  484.             if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 )
  485.                 break;
  486.         }
  487.     }
  488.     if( i != m_dwNumBuffers )
  489.         return m_apDSBuffer[ i ];
  490.     else
  491.         return m_apDSBuffer[ rand() % m_dwNumBuffers ];
  492. }
  493. LPDIRECTSOUNDBUFFER CSound::GetBuffer( DWORD dwIndex )
  494. {
  495.     if( m_apDSBuffer == NULL )
  496.         return NULL;
  497.     if( dwIndex >= m_dwNumBuffers )
  498.         return NULL;
  499.     return m_apDSBuffer[dwIndex];
  500. }
  501. HRESULT CSound::Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer )
  502. {
  503.     if( m_apDSBuffer == NULL )
  504.         return CO_E_NOTINITIALIZED;
  505.     if( dwIndex >= m_dwNumBuffers )
  506.         return E_INVALIDARG;
  507.     *ppDS3DBuffer = NULL;
  508.     return m_apDSBuffer[dwIndex]->QueryInterface( IID_IDirectSound3DBuffer, 
  509.                                                   (VOID**)ppDS3DBuffer );
  510. }
  511. HRESULT CSound::Play( DWORD dwPriority, DWORD dwFlags, LONG lVolume, LONG lFrequency, LONG lPan )
  512. {
  513.     HRESULT hr;
  514.     BOOL    bRestored;
  515.     if( m_apDSBuffer == NULL )
  516.         return CO_E_NOTINITIALIZED;
  517.     LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer();
  518.     if( pDSB == NULL )
  519.         return DXTRACE_ERR( TEXT("GetFreeBuffer"), E_FAIL );
  520.     
  521.     if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) )
  522.         return DXTRACE_ERR( TEXT("RestoreBuffer"), hr );
  523.     if( bRestored )
  524.     {
  525.         
  526.         if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) )
  527.             return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr );
  528.     }
  529.     if( m_dwCreationFlags & DSBCAPS_CTRLVOLUME )
  530.     {
  531.         pDSB->SetVolume( lVolume );
  532.     }
  533.     if( lFrequency != -1 && 
  534.         (m_dwCreationFlags & DSBCAPS_CTRLFREQUENCY) )
  535.     {
  536.         pDSB->SetFrequency( lFrequency );
  537.     }
  538.     
  539.     if( m_dwCreationFlags & DSBCAPS_CTRLPAN )
  540.     {
  541.         pDSB->SetPan( lPan );
  542.     }
  543.     
  544.     return pDSB->Play( 0, dwPriority, dwFlags );
  545. }
  546. HRESULT CSound::Play3D( LPDS3DBUFFER p3DBuffer, DWORD dwPriority, DWORD dwFlags, LONG lFrequency )
  547. {
  548.     HRESULT hr;
  549.     BOOL    bRestored;
  550.     DWORD   dwBaseFrequency;
  551.     if( m_apDSBuffer == NULL )
  552.         return CO_E_NOTINITIALIZED;
  553.     LPDIRECTSOUNDBUFFER pDSB = GetFreeBuffer();
  554.     if( pDSB == NULL )
  555.         return DXTRACE_ERR( TEXT("GetFreeBuffer"), E_FAIL );
  556.     
  557.     if( FAILED( hr = RestoreBuffer( pDSB, &bRestored ) ) )
  558.         return DXTRACE_ERR( TEXT("RestoreBuffer"), hr );
  559.     if( bRestored )
  560.     {
  561.         
  562.         if( FAILED( hr = FillBufferWithSound( pDSB, FALSE ) ) )
  563.             return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr );
  564.     }
  565.     if( m_dwCreationFlags & DSBCAPS_CTRLFREQUENCY )
  566.     {
  567.         pDSB->GetFrequency( &dwBaseFrequency );
  568.         pDSB->SetFrequency( dwBaseFrequency + lFrequency );
  569.     }
  570.     
  571.     LPDIRECTSOUND3DBUFFER pDS3DBuffer;
  572.     hr = pDSB->QueryInterface( IID_IDirectSound3DBuffer, (VOID**) &pDS3DBuffer );
  573.     if( SUCCEEDED( hr ) )
  574.     {
  575.         hr = pDS3DBuffer->SetAllParameters( p3DBuffer, DS3D_IMMEDIATE );
  576.         if( SUCCEEDED( hr ) )
  577.         {
  578.             hr = pDSB->Play( 0, dwPriority, dwFlags );
  579.         }
  580.         pDS3DBuffer->Release();
  581.     }
  582.     return hr;
  583. }
  584. HRESULT CSound::Stop()
  585. {
  586.     if( m_apDSBuffer == NULL )
  587.         return CO_E_NOTINITIALIZED;
  588.     HRESULT hr = 0;
  589.     for( DWORD i=0; i<m_dwNumBuffers; i++ )
  590.         hr |= m_apDSBuffer[i]->Stop();
  591.     return hr;
  592. }
  593. HRESULT CSound::Reset()
  594. {
  595.     if( m_apDSBuffer == NULL )
  596.         return CO_E_NOTINITIALIZED;
  597.     HRESULT hr = 0;
  598.     for( DWORD i=0; i<m_dwNumBuffers; i++ )
  599.         hr |= m_apDSBuffer[i]->SetCurrentPosition( 0 );
  600.     return hr;
  601. }
  602. BOOL CSound::IsSoundPlaying()
  603. {
  604.     BOOL bIsPlaying = FALSE;
  605.     if( m_apDSBuffer == NULL )
  606.         return FALSE; 
  607.     for( DWORD i=0; i<m_dwNumBuffers; i++ )
  608.     {
  609.         if( m_apDSBuffer[i] )
  610.         {  
  611.             DWORD dwStatus = 0;
  612.             m_apDSBuffer[i]->GetStatus( &dwStatus );
  613.             bIsPlaying |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 );
  614.         }
  615.     }
  616.     return bIsPlaying;
  617. }
  618. CStreamingSound::CStreamingSound( LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwDSBufferSize, 
  619.                                   CWaveFile* pWaveFile, DWORD dwNotifySize ) 
  620.                 : CSound( &pDSBuffer, dwDSBufferSize, 1, pWaveFile, 0 )           
  621. {
  622.     m_dwLastPlayPos     = 0;
  623.     m_dwPlayProgress    = 0;
  624.     m_dwNotifySize      = dwNotifySize;
  625.     m_dwNextWriteOffset = 0;
  626.     m_bFillNextNotificationWithSilence = FALSE;
  627. }
  628. CStreamingSound::~CStreamingSound()
  629. {
  630. }
  631. HRESULT CStreamingSound::HandleWaveStreamNotification( BOOL bLoopedPlay )
  632. {
  633.     HRESULT hr;
  634.     DWORD   dwCurrentPlayPos;
  635.     DWORD   dwPlayDelta;
  636.     DWORD   dwBytesWrittenToBuffer;
  637.     VOID*   pDSLockedBuffer = NULL;
  638.     VOID*   pDSLockedBuffer2 = NULL;
  639.     DWORD   dwDSLockedBufferSize;
  640.     DWORD   dwDSLockedBufferSize2;
  641.     if( m_apDSBuffer == NULL || m_pWaveFile == NULL )
  642.         return CO_E_NOTINITIALIZED;
  643.     
  644.     BOOL bRestored;
  645.     if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) )
  646.         return DXTRACE_ERR( TEXT("RestoreBuffer"), hr );
  647.     if( bRestored )
  648.     {
  649.         
  650.         if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) )
  651.             return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr );
  652.         return S_OK;
  653.     }
  654.     
  655.     if( FAILED( hr = m_apDSBuffer[0]->Lock( m_dwNextWriteOffset, m_dwNotifySize, 
  656.                                             &pDSLockedBuffer, &dwDSLockedBufferSize, 
  657.                                             &pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) )
  658.         return DXTRACE_ERR( TEXT("Lock"), hr );
  659.     
  660.     
  661.     if( pDSLockedBuffer2 != NULL )
  662.         return E_UNEXPECTED; 
  663.     if( !m_bFillNextNotificationWithSilence )
  664.     {
  665.         
  666.         if( FAILED( hr = m_pWaveFile->Read( (BYTE*) pDSLockedBuffer, 
  667.                                                   dwDSLockedBufferSize, 
  668.                                                   &dwBytesWrittenToBuffer ) ) )           
  669.             return DXTRACE_ERR( TEXT("Read"), hr );
  670.     }
  671.     else
  672.     {
  673.         
  674.         FillMemory( pDSLockedBuffer, dwDSLockedBufferSize, 
  675.                     (BYTE)( m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) );
  676.         dwBytesWrittenToBuffer = dwDSLockedBufferSize;
  677.     }
  678.     
  679.     
  680.     if( dwBytesWrittenToBuffer < dwDSLockedBufferSize )
  681.     {
  682.         if( !bLoopedPlay ) 
  683.         {
  684.             
  685.             FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer, 
  686.                         dwDSLockedBufferSize - dwBytesWrittenToBuffer, 
  687.                         (BYTE)(m_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) );
  688.             
  689.             m_bFillNextNotificationWithSilence = TRUE;
  690.         }
  691.         else
  692.         {
  693.             
  694.             DWORD dwReadSoFar = dwBytesWrittenToBuffer;    
  695.             while( dwReadSoFar < dwDSLockedBufferSize )
  696.             {  
  697.                 
  698.                 if( FAILED( hr = m_pWaveFile->ResetFile() ) )
  699.                     return DXTRACE_ERR( TEXT("ResetFile"), hr );
  700.                 if( FAILED( hr = m_pWaveFile->Read( (BYTE*)pDSLockedBuffer + dwReadSoFar,
  701.                                                           dwDSLockedBufferSize - dwReadSoFar,
  702.                                                           &dwBytesWrittenToBuffer ) ) )
  703.                     return DXTRACE_ERR( TEXT("Read"), hr );
  704.                 dwReadSoFar += dwBytesWrittenToBuffer;
  705.             } 
  706.         } 
  707.     }
  708.     
  709.     m_apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );
  710.     
  711.     
  712.     
  713.     
  714.     if( FAILED( hr = m_apDSBuffer[0]->GetCurrentPosition( &dwCurrentPlayPos, NULL ) ) )
  715.         return DXTRACE_ERR( TEXT("GetCurrentPosition"), hr );
  716.     
  717.     if( dwCurrentPlayPos < m_dwLastPlayPos )
  718.         dwPlayDelta = ( m_dwDSBufferSize - m_dwLastPlayPos ) + dwCurrentPlayPos;
  719.     else
  720.         dwPlayDelta = dwCurrentPlayPos - m_dwLastPlayPos;
  721.     m_dwPlayProgress += dwPlayDelta;
  722.     m_dwLastPlayPos = dwCurrentPlayPos;
  723.     
  724.     
  725.     if( m_bFillNextNotificationWithSilence )
  726.     {
  727.         
  728.         if( m_dwPlayProgress >= m_pWaveFile->GetSize() )
  729.         {
  730.             m_apDSBuffer[0]->Stop();
  731.         }
  732.     }
  733.     
  734.     m_dwNextWriteOffset += dwDSLockedBufferSize; 
  735.     m_dwNextWriteOffset %= m_dwDSBufferSize; 
  736.     return S_OK;
  737. }
  738. HRESULT CStreamingSound::Reset()
  739. {
  740.     HRESULT hr;
  741.     if( m_apDSBuffer[0] == NULL || m_pWaveFile == NULL )
  742.         return CO_E_NOTINITIALIZED;
  743.     m_dwLastPlayPos     = 0;
  744.     m_dwPlayProgress    = 0;
  745.     m_dwNextWriteOffset = 0;
  746.     m_bFillNextNotificationWithSilence = FALSE;
  747.     
  748.     BOOL bRestored;
  749.     if( FAILED( hr = RestoreBuffer( m_apDSBuffer[0], &bRestored ) ) )
  750.         return DXTRACE_ERR( TEXT("RestoreBuffer"), hr );
  751.     if( bRestored )
  752.     {
  753.         
  754.         if( FAILED( hr = FillBufferWithSound( m_apDSBuffer[0], FALSE ) ) )
  755.             return DXTRACE_ERR( TEXT("FillBufferWithSound"), hr );
  756.     }
  757.     m_pWaveFile->ResetFile();
  758.     return m_apDSBuffer[0]->SetCurrentPosition( 0L );  
  759. }
  760. CWaveFile::CWaveFile()
  761. {
  762.     m_pwfx    = NULL;
  763.     m_hmmio   = NULL;
  764.     m_pResourceBuffer = NULL;
  765.     m_dwSize  = 0;
  766.     m_bIsReadingFromMemory = FALSE;
  767. }
  768. CWaveFile::~CWaveFile()
  769. {
  770.     Close();
  771.     if( !m_bIsReadingFromMemory )
  772.         SAFE_DELETE_ARRAY( m_pwfx );
  773. }
  774. HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags )
  775. {
  776.     HRESULT hr;
  777.     m_dwFlags = dwFlags;
  778.     m_bIsReadingFromMemory = FALSE;
  779.     if( m_dwFlags == WAVEFILE_READ )
  780.     {
  781.         if( strFileName == NULL )
  782.             return E_INVALIDARG;
  783.         SAFE_DELETE_ARRAY( m_pwfx );
  784.         m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ );
  785.         if( NULL == m_hmmio )
  786.         {
  787.             HRSRC   hResInfo;
  788.             HGLOBAL hResData;
  789.             DWORD   dwSize;
  790.             VOID*   pvRes;
  791.             
  792.             if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) )
  793.             {
  794.                 if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) )
  795.                     return DXTRACE_ERR( TEXT("FindResource"), E_FAIL );
  796.             }
  797.             if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) )
  798.                 return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL );
  799.             if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) 
  800.                 return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL );
  801.             if( NULL == ( pvRes = LockResource( hResData ) ) )
  802.                 return DXTRACE_ERR( TEXT("LockResource"), E_FAIL );
  803.             m_pResourceBuffer = new CHAR[ dwSize ];
  804.             memcpy( m_pResourceBuffer, pvRes, dwSize );
  805.             MMIOINFO mmioInfo;
  806.             ZeroMemory( &mmioInfo, sizeof(mmioInfo) );
  807.             mmioInfo.fccIOProc = FOURCC_MEM;
  808.             mmioInfo.cchBuffer = dwSize;
  809.             mmioInfo.pchBuffer = (CHAR*) m_pResourceBuffer;
  810.             m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ );
  811.         }
  812.         if( FAILED( hr = ReadMMIO() ) )
  813.         {
  814.             
  815.             mmioClose( m_hmmio, 0 );
  816.             return DXTRACE_ERR( TEXT("ReadMMIO"), hr );
  817.         }
  818.         if( FAILED( hr = ResetFile() ) )
  819.             return DXTRACE_ERR( TEXT("ResetFile"), hr );
  820.         
  821.         m_dwSize = m_ck.cksize;
  822.     }
  823.     else
  824.     {
  825.         m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF  | 
  826.                                                   MMIO_READWRITE | 
  827.                                                   MMIO_CREATE );
  828.         if( NULL == m_hmmio )
  829.             return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL );
  830.         if( FAILED( hr = WriteMMIO( pwfx ) ) )
  831.         {
  832.             mmioClose( m_hmmio, 0 );
  833.             return DXTRACE_ERR( TEXT("WriteMMIO"), hr );
  834.         }
  835.                         
  836.         if( FAILED( hr = ResetFile() ) )
  837.             return DXTRACE_ERR( TEXT("ResetFile"), hr );
  838.     }
  839.     return hr;
  840. }
  841. HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, 
  842.                                    WAVEFORMATEX* pwfx, DWORD dwFlags )
  843. {
  844.     m_pwfx       = pwfx;
  845.     m_ulDataSize = ulDataSize;
  846.     m_pbData     = pbData;
  847.     m_pbDataCur  = m_pbData;
  848.     m_bIsReadingFromMemory = TRUE;
  849.     
  850.     if( dwFlags != WAVEFILE_READ )
  851.         return E_NOTIMPL;       
  852.     
  853.     return S_OK;
  854. }
  855. HRESULT CWaveFile::ReadMMIO()
  856. {
  857.     MMCKINFO        ckIn;           
  858.     PCMWAVEFORMAT   pcmWaveFormat;  
  859.     m_pwfx = NULL;
  860.     if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) )
  861.         return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL );
  862.     
  863.     if( (m_ckRiff.ckid != FOURCC_RIFF) ||
  864.         (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) )
  865.         return DXTRACE_ERR( TEXT("mmioFOURCC"), E_FAIL ); 
  866.     
  867.     ckIn.ckid = mmioFOURCC('f', 'm', 't', ' ');
  868.     if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) )
  869.         return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL );
  870.     
  871.     
  872.        if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) )
  873.            return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL );
  874.     
  875.     if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, 
  876.                   sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) )
  877.         return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL );
  878.     
  879.     
  880.     if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM )
  881.     {
  882.         m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ];
  883.         if( NULL == m_pwfx )
  884.             return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL );
  885.         
  886.         memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) );
  887.         m_pwfx->cbSize = 0;
  888.     }
  889.     else
  890.     {
  891.         
  892.         WORD cbExtraBytes = 0L;
  893.         if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) )
  894.             return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL );
  895.         m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ];
  896.         if( NULL == m_pwfx )
  897.             return DXTRACE_ERR( TEXT("new"), E_FAIL );
  898.         
  899.         memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) );
  900.         m_pwfx->cbSize = cbExtraBytes;
  901.         
  902.         if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)),
  903.                       cbExtraBytes ) != cbExtraBytes )
  904.         {
  905.             SAFE_DELETE( m_pwfx );
  906.             return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL );
  907.         }
  908.     }
  909.     
  910.     if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) )
  911.     {
  912.         SAFE_DELETE( m_pwfx );
  913.         return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );
  914.     }
  915.     return S_OK;
  916. }
  917. DWORD CWaveFile::GetSize()
  918. {
  919.     return m_dwSize;
  920. }
  921. HRESULT CWaveFile::ResetFile()
  922. {
  923.     if( m_bIsReadingFromMemory )
  924.     {
  925.         m_pbDataCur = m_pbData;
  926.     }
  927.     else 
  928.     {
  929.         if( m_hmmio == NULL )
  930.             return CO_E_NOTINITIALIZED;
  931.         if( m_dwFlags == WAVEFILE_READ )
  932.         {
  933.             
  934.             if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC),
  935.                             SEEK_SET ) )
  936.                 return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL );
  937.             
  938.             m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
  939.             if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) )
  940.               return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL );
  941.         }
  942.         else
  943.         {
  944.             
  945.             m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
  946.             m_ck.cksize = 0;
  947.             if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) 
  948.                 return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL );
  949.             if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) )
  950.                 return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL );
  951.         }
  952.     }
  953.     
  954.     return S_OK;
  955. }
  956. HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead )
  957. {
  958.     if( m_bIsReadingFromMemory )
  959.     {
  960.         if( m_pbDataCur == NULL )
  961.             return CO_E_NOTINITIALIZED;
  962.         if( pdwSizeRead != NULL )
  963.             *pdwSizeRead = 0;
  964.         if( (BYTE*)(m_pbDataCur + dwSizeToRead) > 
  965.             (BYTE*)(m_pbData + m_ulDataSize) )
  966.         {
  967.             dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData);
  968.         }
  969.         
  970.         CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead );
  971.         
  972.         if( pdwSizeRead != NULL )
  973.             *pdwSizeRead = dwSizeToRead;
  974.         return S_OK;
  975.     }
  976.     else 
  977.     {
  978.         MMIOINFO mmioinfoIn; 
  979.         if( m_hmmio == NULL )
  980.             return CO_E_NOTINITIALIZED;
  981.         if( pBuffer == NULL || pdwSizeRead == NULL )
  982.             return E_INVALIDARG;
  983.         if( pdwSizeRead != NULL )
  984.             *pdwSizeRead = 0;
  985.         if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) )
  986.             return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL );
  987.                 
  988.         UINT cbDataIn = dwSizeToRead;
  989.         if( cbDataIn > m_ck.cksize ) 
  990.             cbDataIn = m_ck.cksize;       
  991.         m_ck.cksize -= cbDataIn;
  992.     
  993.         for( DWORD cT = 0; cT < cbDataIn; cT++ )
  994.         {
  995.             
  996.             if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
  997.             {
  998.                 if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) )
  999.                     return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL );
  1000.                 if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
  1001.                     return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL );
  1002.             }
  1003.             
  1004.             *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext);
  1005.             mmioinfoIn.pchNext++;
  1006.         }
  1007.         if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) )
  1008.             return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL );
  1009.         if( pdwSizeRead != NULL )
  1010.             *pdwSizeRead = cbDataIn;
  1011.         return S_OK;
  1012.     }
  1013. }
  1014. HRESULT CWaveFile::Close()
  1015. {
  1016.     if( m_dwFlags == WAVEFILE_READ )
  1017.     {
  1018.         mmioClose( m_hmmio, 0 );
  1019.         m_hmmio = NULL;
  1020.         SAFE_DELETE_ARRAY( m_pResourceBuffer );
  1021.     }
  1022.     else
  1023.     {
  1024.         m_mmioinfoOut.dwFlags |= MMIO_DIRTY;
  1025.         if( m_hmmio == NULL )
  1026.             return CO_E_NOTINITIALIZED;
  1027.         if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) )
  1028.             return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL );
  1029.     
  1030.         
  1031.         
  1032.         if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) )
  1033.             return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );
  1034.     
  1035.         
  1036.         if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) )
  1037.             return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );
  1038.         
  1039.         mmioSeek( m_hmmio, 0, SEEK_SET );
  1040.         if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) )
  1041.             return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL );
  1042.     
  1043.         m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't');
  1044.         if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) 
  1045.         {
  1046.             DWORD dwSamples = 0;
  1047.             mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) );
  1048.             mmioAscend( m_hmmio, &m_ck, 0 ); 
  1049.         }
  1050.     
  1051.         
  1052.         
  1053.         if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) )
  1054.             return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );
  1055.     
  1056.         mmioClose( m_hmmio, 0 );
  1057.         m_hmmio = NULL;
  1058.     }
  1059.     return S_OK;
  1060. }
  1061. HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest )
  1062. {
  1063.     DWORD    dwFactChunk; 
  1064.     MMCKINFO ckOut1;
  1065.     
  1066.     dwFactChunk = (DWORD)-1;
  1067.     
  1068.     m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E');       
  1069.     m_ckRiff.cksize = 0;
  1070.     if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) )
  1071.         return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL );
  1072.     
  1073.     
  1074.     
  1075.     
  1076.     
  1077.     m_ck.ckid = mmioFOURCC('f', 'm', 't', ' ');
  1078.     m_ck.cksize = sizeof(PCMWAVEFORMAT);   
  1079.     if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) )
  1080.         return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL );
  1081.     
  1082.     
  1083.     if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM )
  1084.     {
  1085.         if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, 
  1086.                        sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT))
  1087.             return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL );
  1088.     }   
  1089.     else 
  1090.     {
  1091.         
  1092.         if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, 
  1093.                              sizeof(*pwfxDest) + pwfxDest->cbSize ) != 
  1094.                              ( sizeof(*pwfxDest) + pwfxDest->cbSize ) )
  1095.             return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL );
  1096.     }  
  1097.     
  1098.     
  1099.     if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) )
  1100.         return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );
  1101.     
  1102.     
  1103.     
  1104.     ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't');
  1105.     ckOut1.cksize = 0;
  1106.     if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) )
  1107.         return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL );
  1108.     
  1109.     if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != 
  1110.                     sizeof(dwFactChunk) )
  1111.          return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL );
  1112.     
  1113.     
  1114.     if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) )
  1115.         return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );
  1116.        
  1117.     return S_OK;
  1118. }
  1119. HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote )
  1120. {
  1121.     UINT cT;
  1122.     if( m_bIsReadingFromMemory )
  1123.         return E_NOTIMPL;
  1124.     if( m_hmmio == NULL )
  1125.         return CO_E_NOTINITIALIZED;
  1126.     if( pnSizeWrote == NULL || pbSrcData == NULL )
  1127.         return E_INVALIDARG;
  1128.     *pnSizeWrote = 0;
  1129.     
  1130.     for( cT = 0; cT < nSizeToWrite; cT++ )
  1131.     {       
  1132.         if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite )
  1133.         {
  1134.             m_mmioinfoOut.dwFlags |= MMIO_DIRTY;
  1135.             if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) )
  1136.                 return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL );
  1137.         }
  1138.         *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT);
  1139.         (BYTE*)m_mmioinfoOut.pchNext++;
  1140.         (*pnSizeWrote)++;
  1141.     }
  1142.     return S_OK;
  1143. }