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