cWavFile.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:19k
源码类别:

游戏

开发平台:

Visual C++

  1. // cWavFile.cpp: implementation of the cWavFile class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "cWavFile.h"
  6. #include "cApplication.h"
  7. //////////////////////////////////////////////////////////////////////
  8. // Construction/Destruction
  9. //////////////////////////////////////////////////////////////////////
  10. //-----------------------------------------------------------------------------
  11. // Name: CWaveFile::CWaveFile()
  12. // Desc: Constructs the class.  Call Open() to open a wave file for reading.  
  13. //       Then call Read() as needed.  Calling the destructor or Close() 
  14. //       will close the file.  
  15. //-----------------------------------------------------------------------------
  16. cWavFile::cWavFile()
  17. {
  18.     m_pwfx    = NULL;
  19.     m_hmmio   = NULL;
  20.     m_pResourceBuffer = NULL;
  21.     m_dwSize  = 0;
  22.     m_bIsReadingFromMemory = FALSE;
  23. }
  24. //-----------------------------------------------------------------------------
  25. // Name: CWaveFile::~CWaveFile()
  26. // Desc: Destructs the class
  27. //-----------------------------------------------------------------------------
  28. cWavFile::~cWavFile()
  29. {
  30.     Close();
  31.     if( !m_bIsReadingFromMemory )
  32.         if( m_pwfx )
  33. {
  34. delete[] m_pwfx;
  35. m_pwfx = NULL;
  36. }
  37. }
  38. //-----------------------------------------------------------------------------
  39. // Name: CWaveFile::Open()
  40. // Desc: Opens a wave file for reading
  41. //-----------------------------------------------------------------------------
  42. HRESULT cWavFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags )
  43. {
  44.     HRESULT hr;
  45.     m_dwFlags = dwFlags;
  46.     m_bIsReadingFromMemory = FALSE;
  47.     if( m_dwFlags == WAVEFILE_READ )
  48.     {
  49.         if( strFileName == NULL )
  50.             return E_INVALIDARG;
  51.         if( m_pwfx )
  52. {
  53. delete[] m_pwfx;
  54. m_pwfx = NULL;
  55. }
  56.         HRSRC   hResInfo;
  57.         HGLOBAL hResData;
  58.         DWORD   dwSize;
  59.         VOID*   pvRes;
  60.         // Loading it as a file failed, so try it as a resource
  61.         if( NULL == ( hResInfo = FindResource(  GetMainApp()->GetInstHandle(), strFileName, TEXT("WAVE") ) ) )
  62.         {
  63.             if( NULL == ( hResInfo = FindResource( GetMainApp()->GetInstHandle(), strFileName, TEXT("WAV") ) ) )
  64.                 m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ );
  65.         }
  66.         if(hResInfo != NULL)
  67. {
  68. if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) )
  69. return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL );
  70. if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) ) 
  71. return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL );
  72. if( NULL == ( pvRes = LockResource( hResData ) ) )
  73. return DXTRACE_ERR( TEXT("LockResource"), E_FAIL );
  74. m_pResourceBuffer = new CHAR[ dwSize ];
  75. memcpy( m_pResourceBuffer, pvRes, dwSize );
  76. MMIOINFO mmioInfo;
  77. ZeroMemory( &mmioInfo, sizeof(mmioInfo) );
  78. mmioInfo.fccIOProc = FOURCC_MEM;
  79. mmioInfo.cchBuffer = dwSize;
  80. mmioInfo.pchBuffer = (CHAR*) m_pResourceBuffer;
  81. m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ );
  82. }
  83.         if( NULL == m_hmmio )
  84.         {
  85.         }
  86.         if( FAILED( hr = ReadMMIO() ) )
  87.         {
  88.             // ReadMMIO will fail if its an not a wave file
  89.             mmioClose( m_hmmio, 0 );
  90.             return DXTRACE_ERR_NOMSGBOX( TEXT("ReadMMIO"), hr );
  91.         }
  92.         if( FAILED( hr = ResetFile() ) )
  93.             return DXTRACE_ERR( TEXT("ResetFile"), hr );
  94.         // After the reset, the size of the wav file is m_ck.cksize so store it now
  95.         m_dwSize = m_ck.cksize;
  96.     }
  97.     else
  98.     {
  99.         m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF  | 
  100.                                                   MMIO_READWRITE | 
  101.                                                   MMIO_CREATE );
  102.         if( NULL == m_hmmio )
  103.             return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL );
  104.         if( FAILED( hr = WriteMMIO( pwfx ) ) )
  105.         {
  106.             mmioClose( m_hmmio, 0 );
  107.             return DXTRACE_ERR( TEXT("WriteMMIO"), hr );
  108.         }
  109.                         
  110.         if( FAILED( hr = ResetFile() ) )
  111.             return DXTRACE_ERR( TEXT("ResetFile"), hr );
  112.     }
  113.     return hr;
  114. }
  115. //-----------------------------------------------------------------------------
  116. // Name: CWaveFile::OpenFromMemory()
  117. // Desc: copy data to CWaveFile member variable from memory
  118. //-----------------------------------------------------------------------------
  119. HRESULT cWavFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize, 
  120.                                    WAVEFORMATEX* pwfx, DWORD dwFlags )
  121. {
  122.     m_pwfx       = pwfx;
  123.     m_ulDataSize = ulDataSize;
  124.     m_pbData     = pbData;
  125.     m_pbDataCur  = m_pbData;
  126.     m_bIsReadingFromMemory = TRUE;
  127.     
  128.     if( dwFlags != WAVEFILE_READ )
  129.         return E_NOTIMPL;       
  130.     
  131.     return S_OK;
  132. }
  133. //-----------------------------------------------------------------------------
  134. // Name: CWaveFile::ReadMMIO()
  135. // Desc: Support function for reading from a multimedia I/O stream.
  136. //       m_hmmio must be valid before calling.  This function uses it to
  137. //       update m_ckRiff, and m_pwfx. 
  138. //-----------------------------------------------------------------------------
  139. HRESULT cWavFile::ReadMMIO()
  140. {
  141.     MMCKINFO        ckIn;           // chunk info. for general use.
  142.     PCMWAVEFORMAT   pcmWaveFormat;  // Temp PCM structure to load in.       
  143.     m_pwfx = NULL;
  144.     if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) )
  145.         return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL );
  146.     // Check to make sure this is a valid wave file
  147.     if( (m_ckRiff.ckid != FOURCC_RIFF) ||
  148.         (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) )
  149.         return DXTRACE_ERR_NOMSGBOX( TEXT("mmioFOURCC"), E_FAIL ); 
  150.     // Search the input file for for the 'fmt ' chunk.
  151.     ckIn.ckid = mmioFOURCC('f', 'm', 't', ' ');
  152.     if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) )
  153.         return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL );
  154.     // Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>;
  155.     // if there are extra parameters at the end, we'll ignore them
  156.        if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) )
  157.            return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL );
  158.     // Read the 'fmt ' chunk into <pcmWaveFormat>.
  159.     if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, 
  160.                   sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) )
  161.         return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL );
  162.     // Allocate the waveformatex, but if its not pcm format, read the next
  163.     // word, and thats how many extra bytes to allocate.
  164.     if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM )
  165.     {
  166.         m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ];
  167.         if( NULL == m_pwfx )
  168.             return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL );
  169.         // Copy the bytes from the pcm structure to the waveformatex structure
  170.         memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) );
  171.         m_pwfx->cbSize = 0;
  172.     }
  173.     else
  174.     {
  175.         // Read in length of extra bytes.
  176.         WORD cbExtraBytes = 0L;
  177.         if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) )
  178.             return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL );
  179.         m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ];
  180.         if( NULL == m_pwfx )
  181.             return DXTRACE_ERR( TEXT("new"), E_FAIL );
  182.         // Copy the bytes from the pcm structure to the waveformatex structure
  183.         memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) );
  184.         m_pwfx->cbSize = cbExtraBytes;
  185.         // Now, read those extra bytes into the structure, if cbExtraAlloc != 0.
  186.         if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)),
  187.                       cbExtraBytes ) != cbExtraBytes )
  188.         {
  189.             if( m_pwfx )
  190. {
  191. delete m_pwfx;
  192. m_pwfx = NULL;
  193. }
  194.             return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL );
  195.         }
  196.     }
  197.     // Ascend the input file out of the 'fmt ' chunk.
  198.     if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) )
  199.     {
  200.         if( m_pwfx )
  201. {
  202. delete m_pwfx;
  203. m_pwfx = NULL;
  204. }
  205.         return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );
  206.     }
  207.     return S_OK;
  208. }
  209. //-----------------------------------------------------------------------------
  210. // Name: CWaveFile::GetSize()
  211. // Desc: Retuns the size of the read access wave file 
  212. //-----------------------------------------------------------------------------
  213. DWORD cWavFile::GetSize()
  214. {
  215.     return m_dwSize;
  216. }
  217. //-----------------------------------------------------------------------------
  218. // Name: CWaveFile::ResetFile()
  219. // Desc: Resets the internal m_ck pointer so reading starts from the 
  220. //       beginning of the file again 
  221. //-----------------------------------------------------------------------------
  222. HRESULT cWavFile::ResetFile()
  223. {
  224.     if( m_bIsReadingFromMemory )
  225.     {
  226.         m_pbDataCur = m_pbData;
  227.     }
  228.     else 
  229.     {
  230.         if( m_hmmio == NULL )
  231.             return CO_E_NOTINITIALIZED;
  232.         if( m_dwFlags == WAVEFILE_READ )
  233.         {
  234.             // Seek to the data
  235.             if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC),
  236.                             SEEK_SET ) )
  237.                 return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL );
  238.             // Search the input file for the 'data' chunk.
  239.             m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
  240.             if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) )
  241.               return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL );
  242.         }
  243.         else
  244.         {
  245.             // Create the 'data' chunk that holds the waveform samples.  
  246.             m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
  247.             m_ck.cksize = 0;
  248.             if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) 
  249.                 return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL );
  250.             if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) )
  251.                 return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL );
  252.         }
  253.     }
  254.     
  255.     return S_OK;
  256. }
  257. //-----------------------------------------------------------------------------
  258. // Name: CWaveFile::Read()
  259. // Desc: Reads section of data from a wave file into pBuffer and returns 
  260. //       how much read in pdwSizeRead, reading not more than dwSizeToRead.
  261. //       This uses m_ck to determine where to start reading from.  So 
  262. //       subsequent calls will be continue where the last left off unless 
  263. //       Reset() is called.
  264. //-----------------------------------------------------------------------------
  265. HRESULT cWavFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead )
  266. {
  267.     if( m_bIsReadingFromMemory )
  268.     {
  269.         if( m_pbDataCur == NULL )
  270.             return CO_E_NOTINITIALIZED;
  271.         if( pdwSizeRead != NULL )
  272.             *pdwSizeRead = 0;
  273.         if( (BYTE*)(m_pbDataCur + dwSizeToRead) > 
  274.             (BYTE*)(m_pbData + m_ulDataSize) )
  275.         {
  276.             dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData);
  277.         }
  278.         
  279.         CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead );
  280.         
  281.         if( pdwSizeRead != NULL )
  282.             *pdwSizeRead = dwSizeToRead;
  283.         return S_OK;
  284.     }
  285.     else 
  286.     {
  287.         MMIOINFO mmioinfoIn; // current status of m_hmmio
  288.         if( m_hmmio == NULL )
  289.             return CO_E_NOTINITIALIZED;
  290.         if( pBuffer == NULL || pdwSizeRead == NULL )
  291.             return E_INVALIDARG;
  292.         if( pdwSizeRead != NULL )
  293.             *pdwSizeRead = 0;
  294.         if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) )
  295.             return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL );
  296.                 
  297.         UINT cbDataIn = dwSizeToRead;
  298.         if( cbDataIn > m_ck.cksize ) 
  299.             cbDataIn = m_ck.cksize;       
  300.         m_ck.cksize -= cbDataIn;
  301.     
  302.         for( DWORD cT = 0; cT < cbDataIn; cT++ )
  303.         {
  304.             // Copy the bytes from the io to the buffer.
  305.             if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
  306.             {
  307.                 if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) )
  308.                     return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL );
  309.                 if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
  310.                     return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL );
  311.             }
  312.             // Actual copy.
  313.             *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext);
  314.             mmioinfoIn.pchNext++;
  315.         }
  316.         if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) )
  317.             return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL );
  318.         if( pdwSizeRead != NULL )
  319.             *pdwSizeRead = cbDataIn;
  320.         return S_OK;
  321.     }
  322. }
  323. //-----------------------------------------------------------------------------
  324. // Name: CWaveFile::Close()
  325. // Desc: Closes the wave file 
  326. //-----------------------------------------------------------------------------
  327. HRESULT cWavFile::Close()
  328. {
  329.     if( m_dwFlags == WAVEFILE_READ )
  330.     {
  331.         mmioClose( m_hmmio, 0 );
  332.         m_hmmio = NULL;
  333.         if( m_pResourceBuffer )
  334. {
  335. delete[] m_pResourceBuffer;
  336. m_pResourceBuffer = NULL;
  337. }
  338.     }
  339.     else
  340.     {
  341.         m_mmioinfoOut.dwFlags |= MMIO_DIRTY;
  342.         if( m_hmmio == NULL )
  343.             return CO_E_NOTINITIALIZED;
  344.         if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) )
  345.             return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL );
  346.     
  347.         // Ascend the output file out of the 'data' chunk -- this will cause
  348.         // the chunk size of the 'data' chunk to be written.
  349.         if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) )
  350.             return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );
  351.     
  352.         // Do this here instead...
  353.         if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) )
  354.             return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );
  355.         
  356.         mmioSeek( m_hmmio, 0, SEEK_SET );
  357.         if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) )
  358.             return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL );
  359.     
  360.         m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't');
  361.         if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) 
  362.         {
  363.             DWORD dwSamples = 0;
  364.             mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) );
  365.             mmioAscend( m_hmmio, &m_ck, 0 ); 
  366.         }
  367.     
  368.         // Ascend the output file out of the 'RIFF' chunk -- this will cause
  369.         // the chunk size of the 'RIFF' chunk to be written.
  370.         if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) )
  371.             return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );
  372.     
  373.         mmioClose( m_hmmio, 0 );
  374.         m_hmmio = NULL;
  375.     }
  376.     return S_OK;
  377. }
  378. //-----------------------------------------------------------------------------
  379. // Name: CWaveFile::WriteMMIO()
  380. // Desc: Support function for reading from a multimedia I/O stream
  381. //       pwfxDest is the WAVEFORMATEX for this new wave file.  
  382. //       m_hmmio must be valid before calling.  This function uses it to
  383. //       update m_ckRiff, and m_ck.  
  384. //-----------------------------------------------------------------------------
  385. HRESULT cWavFile::WriteMMIO( WAVEFORMATEX *pwfxDest )
  386. {
  387.     DWORD    dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile.
  388.     MMCKINFO ckOut1;
  389.     
  390.     dwFactChunk = (DWORD)-1;
  391.     // Create the output file RIFF chunk of form type 'WAVE'.
  392.     m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E');       
  393.     m_ckRiff.cksize = 0;
  394.     if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) )
  395.         return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL );
  396.     
  397.     // We are now descended into the 'RIFF' chunk we just created.
  398.     // Now create the 'fmt ' chunk. Since we know the size of this chunk,
  399.     // specify it in the MMCKINFO structure so MMIO doesn't have to seek
  400.     // back and set the chunk size after ascending from the chunk.
  401.     m_ck.ckid = mmioFOURCC('f', 'm', 't', ' ');
  402.     m_ck.cksize = sizeof(PCMWAVEFORMAT);   
  403.     if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) )
  404.         return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL );
  405.     
  406.     // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type. 
  407.     if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM )
  408.     {
  409.         if( mmioWrite( m_hmmio, (HPSTR) pwfxDest, 
  410.                        sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT))
  411.             return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL );
  412.     }   
  413.     else 
  414.     {
  415.         // Write the variable length size.
  416.         if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, 
  417.                              sizeof(*pwfxDest) + pwfxDest->cbSize ) != 
  418.                              ( sizeof(*pwfxDest) + pwfxDest->cbSize ) )
  419.             return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL );
  420.     }  
  421.     
  422.     // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk.
  423.     if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) )
  424.         return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );
  425.     
  426.     // Now create the fact chunk, not required for PCM but nice to have.  This is filled
  427.     // in when the close routine is called.
  428.     ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't');
  429.     ckOut1.cksize = 0;
  430.     if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) )
  431.         return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL );
  432.     
  433.     if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) != 
  434.                     sizeof(dwFactChunk) )
  435.          return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL );
  436.     
  437.     // Now ascend out of the fact chunk...
  438.     if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) )
  439.         return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );
  440.        
  441.     return S_OK;
  442. }
  443. //-----------------------------------------------------------------------------
  444. // Name: CWaveFile::Write()
  445. // Desc: Writes data to the open wave file
  446. //-----------------------------------------------------------------------------
  447. HRESULT cWavFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote )
  448. {
  449.     UINT cT;
  450.     if( m_bIsReadingFromMemory )
  451.         return E_NOTIMPL;
  452.     if( m_hmmio == NULL )
  453.         return CO_E_NOTINITIALIZED;
  454.     if( pnSizeWrote == NULL || pbSrcData == NULL )
  455.         return E_INVALIDARG;
  456.     *pnSizeWrote = 0;
  457.     
  458.     for( cT = 0; cT < nSizeToWrite; cT++ )
  459.     {       
  460.         if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite )
  461.         {
  462.             m_mmioinfoOut.dwFlags |= MMIO_DIRTY;
  463.             if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) )
  464.                 return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL );
  465.         }
  466.         *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT);
  467.         (BYTE*)m_mmioinfoOut.pchNext++;
  468.         (*pnSizeWrote)++;
  469.     }
  470.     return S_OK;
  471. }