OSDN Git Service

・#26997 DTXViewer023 のソースコード一式を追加。変更点は以下の通り。
[dtxmania/dtxmania.git] / @FDK10プロジェクト / CSound.cpp
1 #include "stdafx.h"\r
2 #include "CSound.h"\r
3 #include "CSoundManager.h"\r
4 #include "FDKError.h"\r
5 #include "CFileMM.h"\r
6 #include "xadec.h"\r
7 #include "vorbis/vorbisfile.h"\r
8 #include "COgg.h"\r
9 #include "Debug.h"\r
10 \r
11 namespace FDK {\r
12         namespace Sound {\r
13 \r
14 CSound::CSound()\r
15 {\r
16         this->pDSBuffer = NULL;\r
17 }\r
18 void    CSound::Init()\r
19 {\r
20         SAFE_RELEASE( this->pDSBuffer );\r
21         this->dwDSBufferSize = 0;\r
22         this->strFileName[0] = _T('\0');\r
23         this->lVolume = DSBVOLUME_MAX;\r
24         this->lPan = 0;\r
25         this->fSpeed = 1.0f;\r
26         this->fPitch = 1.0f;\r
27         this->bLoop = false;\r
28         this->nPause = 0;\r
29         this->dwCurrentPosition = 0;\r
30 }\r
31 void    CSound::Term()\r
32 {\r
33         Init();\r
34 }\r
35 HRESULT CSound::DuplicateFromSound( LPDIRECTSOUND8 pDS, CSound* srcSound )\r
36 {\r
37         HRESULT hr;\r
38 \r
39         // \8fð\8c\8f\83`\83F\83b\83N\r
40         if( ! pDS )\r
41                 return FDKERR_DirectSound\82ªNULL;\r
42         if( ! srcSound )\r
43                 return FDKERR_\83T\83E\83\93\83h\83o\83b\83t\83@\82ªNULL;\r
44         if( this->pDSBuffer )\r
45                 Term();         // \97\98\97p\92\86\82È\82Ì\82Å\90æ\82É\8fI\97¹\8f\88\97\9d\82ð\8ds\82¤\r
46 \r
47         // \83T\83E\83\93\83h\82Ì\95¡\90»\r
48         if( FAILED( hr = pDS->DuplicateSoundBuffer( srcSound->GetDirectSoundBuffer(), &this->pDSBuffer ) ) )\r
49                 return FDKERR_\83T\83E\83\93\83h\83o\83b\83t\83@\82Ì\8dì\90¬\82É\8e¸\94s;\r
50         \r
51         // \83T\83E\83\93\83h\83o\83b\83t\83@\83T\83C\83Y\82Ì\8eæ\93¾\r
52         this->dwDSBufferSize = srcSound->GetDirectSoundBufferSize();\r
53 \r
54         return S_OK;\r
55 }\r
56 HRESULT CSound::CreateFromFile( LPDIRECTSOUND8 pDS, LPCTSTR filename )\r
57 {\r
58         HRESULT hr;\r
59 \r
60         // \8fð\8c\8f\83`\83F\83b\83N\r
61         if( ! pDS )\r
62                 return FDKERR_DirectSound\82ªNULL;\r
63 \r
64         // \83t\83@\83C\83\8b\82Ì\93Ç\82Ý\8d\9e\82Ý\r
65         CFileMM file;\r
66         if( ! file.Load( filename ) )\r
67         {\r
68                 file.Term();\r
69                 return FDKERR_\83t\83@\83C\83\8b\82Ì\93Ç\82Ý\8d\9e\82Ý\8e¸\94s;\r
70         }\r
71 \r
72         // \83t\83@\83C\83\8b\83f\81[\83^\82©\82ç\82Ì\83T\83E\83\93\83h\83o\83b\83t\83@\8dì\90¬\r
73         if( FAILED( hr = CreateFromMemory( pDS, file.GetData(), file.GetSize() ) ) )\r
74         {\r
75                 file.Term();\r
76                 return FDKERR_\83T\83E\83\93\83h\83o\83b\83t\83@\82Ì\8dì\90¬\82É\8e¸\94s;\r
77         }\r
78 \r
79         lstrcpyn( this->strFileName, filename, _MAX_PATH );\r
80         file.Term();\r
81 \r
82         return S_OK;\r
83 }\r
84 HRESULT CSound::CreateFromMemory( LPDIRECTSOUND8 pDS, BYTE* pData, DWORD dwSize )\r
85 {\r
86         HRESULT hr;\r
87 \r
88         // \8fð\8c\8f\83`\83F\83b\83N\r
89         if( ! pData || dwSize == 0)\r
90                 return E_INVALIDARG;\r
91         \r
92         if( ! pDS )\r
93                 return FDKERR_DirectSound\82ªNULL;\r
94         \r
95         if( this->pDSBuffer )\r
96                 Term(); // \97\98\97p\92\86\82È\82Ì\82Å\81A\90æ\82É\8fI\97¹\8f\88\97\9d\82ð\8ds\82¤\r
97 \r
98         // \83T\83E\83\93\83h\82Ì\83f\83R\81[\83h\r
99         if( FAILED( hr = DecodeFromOgg( pDS, pData, dwSize ) ) )\r
100         if( FAILED( hr = DecodeFromXA(  pDS, pData, dwSize ) ) )\r
101         if( FAILED( hr = DecodeFromMP3( pDS, pData, dwSize ) ) ) \r
102         if( FAILED( hr = DecodeFromWAV( pDS, pData, dwSize ) ) )\r
103                 return FDKERR_\83T\83E\83\93\83h\83o\83b\83t\83@\82Ì\8dì\90¬\82É\8e¸\94s;             // \96¢\83T\83|\81[\83g\83f\81[\83^\r
104 \r
105         return hr;\r
106 }\r
107 \r
108 HRESULT CSound::CreateAndCopyBuffer( LPDIRECTSOUND8 pDS, WAVEFORMATEX* pwfx, BYTE* pData, DWORD dwSize )\r
109 {\r
110         HRESULT hr;\r
111 \r
112         this->dwDSBufferSize = dwSize;\r
113 \r
114         // \83T\83E\83\93\83h\83o\83b\83t\83@\82Ì\90\90¬\r
115     DSBUFFERDESC dsbd;\r
116     ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );\r
117         dsbd.dwSize          = sizeof(DSBUFFERDESC);\r
118         dsbd.dwFlags         = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCDEFER;\r
119         dsbd.dwBufferBytes   = dwSize;\r
120         dsbd.guid3DAlgorithm = DS3DALG_DEFAULT;\r
121         dsbd.lpwfxFormat     = pwfx;\r
122         if( FAILED( hr = pDS->CreateSoundBuffer( &dsbd, &this->pDSBuffer, NULL ) ) )\r
123                 return FDKERR_\83T\83E\83\93\83h\83o\83b\83t\83@\82Ì\8dì\90¬\82É\8e¸\94s;\r
124 \r
125         // \83T\83E\83\93\83h\83o\83b\83t\83@\82Ì Lost \83`\83F\83b\83N\r
126         if( FAILED( hr = RestoreBuffer( this->pDSBuffer, NULL ) ) )\r
127                 return hr;\r
128 \r
129         // \83f\83R\81[\83h\83f\81[\83^\82ð\83T\83E\83\93\83h\83o\83b\83t\83@\82É\93]\91\97\r
130         VOID* pDSLockedBuffer           = NULL;\r
131         DWORD dwDSLockedBufferSize      = 0;\r
132     if( FAILED( hr = this->pDSBuffer->Lock( 0, dwSize, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, DSBLOCK_ENTIREBUFFER ) ) )\r
133                 return FDKERR_Lock\82É\8e¸\94s;\r
134         else\r
135         {\r
136                 CopyMemory( pDSLockedBuffer, pData, dwSize );\r
137                 this->pDSBuffer->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );\r
138         }\r
139         return S_OK;\r
140 }\r
141 \r
142 HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored )\r
143 {\r
144     HRESULT hr;\r
145 \r
146         // \8fð\8c\8f\83`\83F\83b\83N\r
147     if( pDSB == NULL )\r
148         return CO_E_NOTINITIALIZED;\r
149         \r
150         if( pbWasRestored ) *pbWasRestored = FALSE;\r
151 \r
152         // \83X\83e\81[\83^\83X\82Å Lost \83`\83F\83b\83N\r
153     DWORD dwStatus;\r
154     if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) )\r
155         return hr;\r
156 \r
157     if( dwStatus & DSBSTATUS_BUFFERLOST )\r
158     {\r
159                 // \83T\83E\83\93\83h\83o\83b\83t\83@\82ª Lost \82µ\82Ä\82¢\82é\82Ì\82Å\95\9c\8b\8c\82·\82é\81B\r
160                 // \83A\83v\83\8a\83P\81[\83V\83\87\83\93\82Í\8a\88\90«\89»\82µ\82½\82Î\82©\82è\82Ì\8fê\8d\87\81A\82Ü\82¾ DirectSound \82Í\90§\8cä\8c \82ð\r
161                 // \93n\82µ\82Ä\82­\82ê\82Ä\82¢\82È\82¢\82½\82ß\81A\83o\83b\83t\83@\82Ì Restore \82ª\8e¸\94s\82·\82é\82±\82Æ\82ª\82 \82é\81B\r
162                 // \82à\82µ\82»\82¤\82È\82Á\82½\82ç\81ADirectSound \82ª\90§\8cä\8c \82ð\82­\82ê\82é\82Ü\82Å\83X\83\8a\81[\83v\82·\82é\81B\r
163                 while( ( hr = pDSB->Restore() ) == DSERR_BUFFERLOST )\r
164                         Sleep( 100 );\r
165 \r
166                 // \81¦\82±\82±\82Å\82Í\83o\83b\83t\83@\82Ì\95\9c\8c³\82¾\82¯\81B\83f\81[\83^\82Ì\93à\97e\82Í\8cÄ\82Ñ\8fo\82µ\8c³\82Å\95Ê\93r\95\9c\8c³\82·\82é\82±\82Æ\81B\r
167 \r
168                 if( pbWasRestored )     *pbWasRestored = TRUE;\r
169         }\r
170         return S_OK;\r
171 }\r
172 \r
173 HRESULT CSound::DecodeFromXA(  LPDIRECTSOUND8 pDS, BYTE* pSrcData, DWORD dwSrcSize )\r
174 {\r
175         XAHEADER xah;\r
176         HXASTREAM hxas;\r
177         XASTREAMHEADER xash;\r
178         UCHAR *ps;\r
179         ULONG dlen;\r
180 \r
181         // \83w\83b\83_\83`\83F\83b\83N\r
182         CopyMemory( &xah, pSrcData, sizeof(XAHEADER) );\r
183         if( xah.id != _XAID )\r
184                 return FDKERR_SoundType\82ª\96³\8cø;          // XA \82Å\82Í\82È\82©\82Á\82½\r
185 \r
186         ps = (UCHAR *)pSrcData + sizeof(XAHEADER);\r
187         WAVEFORMATEX* pwfx = (WAVEFORMATEX*) malloc( sizeof(WAVEFORMATEX) );\r
188         hxas = xaDecodeOpen( &xah, pwfx );\r
189         if( hxas == NULL )\r
190                 return FDKERR_SoundType\82ª\96³\8cø;          // XA \82Å\82Í\82È\82©\82Á\82½\r
191 \r
192         // \83f\83R\81[\83h\8cã\83T\83C\83Y\82Ì\8eæ\93¾\r
193         if( ! xaDecodeSize( hxas, xah.nDataLen, &dlen ) )\r
194         {\r
195                 xaDecodeClose( hxas );\r
196                 return FDKERR_SoundType\82ª\96³\8cø;          // XA \82Å\82Í\82È\82©\82Á\82½\81H\r
197         }\r
198 \r
199         // \83f\83R\81[\83h\8cã\83T\83C\83Y\95ª\82Ì\83\81\83\82\83\8a\82ð\8am\95Û\r
200         BYTE* pDestData = (LPBYTE) malloc( dlen );\r
201         if( ! pDestData )\r
202         {\r
203                 xaDecodeClose( hxas );\r
204                 return E_OUTOFMEMORY;           // \83\81\83\82\83\8a\95s\91«\r
205         }\r
206 \r
207         // XA \81¨ WAV \95Ï\8a·\r
208         xash.pSrc = ps;\r
209         xash.nSrcLen = xah.nDataLen;\r
210         xash.nSrcUsed = 0;\r
211         xash.pDst = (UCHAR *) pDestData;\r
212         xash.nDstLen = dlen;\r
213         xash.nDstUsed = 0;\r
214         if( ! xaDecodeConvert( hxas, &xash ) )\r
215         {\r
216                 xaDecodeClose( hxas );\r
217                 return FDKERR_SoundType\82ª\96³\8cø;          // XA \82Å\82Í\82È\82©\82Á\82½\81H\r
218         }\r
219 \r
220         // XA \95Ï\8a·\8a®\97¹\r
221         xaDecodeClose( hxas );\r
222 \r
223         // \8eÀ\82Ì\95Ï\8a·\8cã\83T\83C\83Y\82Ì\8cv\8eZ\r
224 //      lpSrcInfo->dwPCMSize = dlen;            // xadec \82Ì\83o\83O\r
225         DWORD dwTrueLen = xah.nSamples * xah.nChannels * 2;\r
226 \r
227         // \8dì\90¬\82Æ\8f\91\82«\8d\9e\82Ý\r
228         HRESULT hr;\r
229         if( FAILED( hr = CreateAndCopyBuffer( pDS, pwfx, pDestData, dwTrueLen ) ) )\r
230         {\r
231                 SAFE_FREE( pwfx );\r
232                 SAFE_FREE( pDestData );\r
233                 return hr;\r
234         }\r
235         SAFE_FREE( pwfx );\r
236         SAFE_FREE( pDestData );\r
237 \r
238         m_SoundType = SOUNDTYPE_XA;\r
239 \r
240         return S_OK;\r
241 }\r
242 \r
243 HRESULT CSound::DecodeFromMP3( LPDIRECTSOUND8 pDS, BYTE* pSrcData, DWORD dwSrcSize )\r
244 {\r
245         // \83w\83b\83_\83`\83F\83b\83N\r
246         if( dwSrcSize <= 128 )\r
247                 return FDKERR_SoundType\82ª\96³\8cø;          // MP3\82\82á\82È\82¢\r
248 \r
249         //  ID3v2\83^\83O\82ª\82Â\82¢\82Ä\82¢\82é\82È\82ç\82Î\81A\93Ç\82Ý\94ò\82Î\82·\r
250         if( (pSrcData[0] == 'I') && (pSrcData[1] == 'D') && (pSrcData[2] == '3') )\r
251         {\r
252                 DWORD dwID3Size = pSrcData[9] + (pSrcData[8]<<7) + (pSrcData[7]<<14) + (pSrcData[6]<<21);\r
253                 if( pSrcData[3] >= 0x04)\r
254                 {\r
255                         if( pSrcData[5] & 0x10 )\r
256                                 dwID3Size += 20; // ID3v2.4.0\88È\8d~\81E\83t\83b\83^\82 \82è\r
257                         else\r
258                                 dwID3Size += 10; // ID3v2.4.0\88È\8d~\81E\83t\83b\83^\82È\82µ\r
259                 }\r
260                 else\r
261                         dwID3Size += 10;         // ID3v2.3.0\88È\91O\81E\83t\83b\83^\82È\82µ\r
262                 \r
263                 if( dwSrcSize <= dwID3Size + 128 )\r
264                         return FDKERR_SoundType\82ª\96³\8cø;          // MP3\82\82á\82È\82¢\r
265 \r
266                 pSrcData += dwID3Size;\r
267                 dwSrcSize -= dwID3Size;\r
268         }\r
269 \r
270         //      MP3\83`\83F\83b\83N\r
271         if( pSrcData[0] != 0xff || (pSrcData[1] & 0xf0) != 0xf0 )\r
272                 return FDKERR_SoundType\82ª\96³\8cø;          // MP3\82\82á\82È\82¢\r
273 \r
274 \r
275         static const int anBitrate[2][3][16] = {\r
276                 {\r
277                         // MPEG-1\r
278                         { 0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0 },   //      32000Hz(layer1)\r
279                         { 0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0 },   //      44100Hz(layer2)\r
280                         { 0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,0 },   //      48000Hz(layer3)\r
281                 },\r
282                 {\r
283                         // MPEG-2, 2.5\r
284                         { 0,32,48,56, 64, 80, 96,112,128,144,160,176,192,224,256,0 },   //      32000Hz(layer1)\r
285                         { 0, 8,16,24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0 },   //      44100Hz(layer2)\r
286                         { 0, 8,16,24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0 },   //      48000Hz(layer3)\r
287                         },\r
288         };\r
289         static const int anFreq[2][4] = {\r
290                 { 44100,48000,32000,0 },\r
291                 { 22050,24000,16000,0 },\r
292         };\r
293 \r
294         // \83\8c\83C\83\84\81[\94Ô\8d\86\82Ì\83`\83F\83b\83N\r
295         int nLayer = 4-((pSrcData[1] >> 1) & 3);\r
296         if( nLayer == 4 )\r
297                 return FDKERR_SoundType\82ª\96³\8cø;                  // MP3 \82\82á\82È\82©\82Á\82½\81H\r
298         \r
299         int nMpeg               = ((pSrcData[1] & 8) == 0) ? 1 : 0;\r
300         int nBitrate    = anBitrate[ nMpeg ][ nLayer-1 ][ pSrcData[2]>>4 ];\r
301         int nFreq               = anFreq[ nMpeg ][ (pSrcData[2] >> 2) & 3];\r
302         int nChannel    = ((pSrcData[3] >> 6) == 3) ? 1 : 2;\r
303         int nFrameSize  = 144000 * nBitrate / nFreq;\r
304 \r
305         // MP3\82Ì\83^\83O\82ð\97p\88Ó\82·\82é\r
306         MPEGLAYER3WAVEFORMAT wfxMP3;\r
307         ZeroMemory( &wfxMP3, sizeof(MPEGLAYER3WAVEFORMAT) );\r
308         wfxMP3.wfx.cbSize                       = MPEGLAYER3_WFX_EXTRA_BYTES;\r
309         wfxMP3.wfx.wFormatTag           = WAVE_FORMAT_MPEGLAYER3;\r
310         wfxMP3.wfx.nChannels            = nChannel;\r
311         wfxMP3.wfx.nSamplesPerSec       = nFreq;\r
312         wfxMP3.wfx.nAvgBytesPerSec      = nBitrate * 1000 / 8;\r
313         wfxMP3.wfx.nBlockAlign          = 1;\r
314         wfxMP3.wfx.wBitsPerSample       = 0;\r
315         wfxMP3.wID                                      = MPEGLAYER3_ID_MPEG;\r
316         wfxMP3.fdwFlags                         = MPEGLAYER3_FLAG_PADDING_OFF;\r
317         wfxMP3.nBlockSize                       = nFrameSize;\r
318         wfxMP3.nFramesPerBlock          = 1;\r
319         wfxMP3.nCodecDelay                      = 0x0571;\r
320 \r
321         //      ID3\83^\83O\82ª\82Â\82¢\82Ä\82¢\82é\82È\82ç\82Î\81A\82»\82Ì\95ª\82ð\8f\9c\8aO\82·\82é\r
322         if( (pSrcData[ dwSrcSize-128 ] == 'T') && (pSrcData[ dwSrcSize-127 ] == 'A') && (pSrcData[ dwSrcSize-126 ] == 'G') )\r
323                 dwSrcSize-= 128;\r
324 \r
325         // \83\\81[\83X\82©\82ç PCM \82É\95Ï\8a·\89Â\94\\82È codec \82ª\82 \82é\82©\92²\82×\81AwfxDest \82ð\90Ý\92è\r
326         MMRESULT mmr;\r
327         WAVEFORMATEX wfxDest;\r
328         wfxDest.wFormatTag = WAVE_FORMAT_PCM;\r
329         if( ( mmr = acmFormatSuggest( NULL, (WAVEFORMATEX*)(&wfxMP3), &wfxDest, sizeof(WAVEFORMATEX), ACM_FORMATSUGGESTF_WFORMATTAG ) ) != 0 )\r
330                 return FDKERR_SoundType\82ª\96³\8cø;          // Error: CODEC \82ª\82È\82©\82Á\82½\r
331 \r
332         BYTE* pDestData = NULL;\r
333         DWORD dwDestSize = 0;\r
334 \r
335         // ACM \82ð\83I\81[\83v\83\93\82·\82é\r
336         HACMSTREAM hAcm;\r
337         if( ( mmr = acmStreamOpen( &hAcm, NULL, (WAVEFORMATEX*)(&wfxMP3), &wfxDest, NULL, NULL, NULL, ACM_STREAMOPENF_NONREALTIME ) ) != 0 )\r
338                 return FDKERR_SoundType\82ª\96³\8cø;          // Error: \83I\81[\83v\83\93\8e¸\94s\r
339 \r
340         // \95Ï\8a·\8cã\82Ì\83T\83C\83Y\82ð\8eæ\93¾\82µ\81AdwDestSize \82É\90Ý\92è\r
341         if( ( mmr = acmStreamSize( hAcm, dwSrcSize, &dwDestSize, ACM_STREAMSIZEF_SOURCE ) ) != 0 )\r
342         {\r
343                 acmStreamClose( hAcm, NULL );\r
344                 return FDKERR_SoundType\82ª\96³\8cø;          // Error: \83T\83C\83Y\8eæ\93¾\8e¸\94s\r
345         }\r
346         if( dwDestSize == 0 )\r
347         {\r
348                 acmStreamClose( hAcm, NULL );\r
349                 return FDKERR_SoundType\82ª\96³\8cø;          // Error: \95Ï\8a·\8cã\82Ì\83T\83C\83Y\82ª\83[\83\8d\r
350         }\r
351 \r
352         // PCM\83o\83b\83t\83@\82Ì\8am\95Û\r
353         pDestData = (LPBYTE) malloc( dwDestSize );\r
354         if( ! pDestData ) \r
355         {\r
356                 acmStreamClose( hAcm, NULL );\r
357                 return E_OUTOFMEMORY;                           // Error: \83\81\83\82\83\8a\95s\91«\r
358         }\r
359 \r
360         // \95Ï\8a·\97p\83w\83b\83_\8f\80\94õ\r
361         ACMSTREAMHEADER acmHeader;\r
362         ZeroMemory( &acmHeader, sizeof(acmHeader) );\r
363         acmHeader.cbStruct              = sizeof(acmHeader);\r
364         acmHeader.pbSrc                 = pSrcData;\r
365         acmHeader.cbSrcLength   = dwSrcSize;\r
366         acmHeader.pbDst                 = pDestData;\r
367         acmHeader.cbDstLength   = dwDestSize;\r
368         if( ( mmr = acmStreamPrepareHeader( hAcm, &acmHeader, NULL ) ) != 0 )\r
369         {\r
370                 acmStreamUnprepareHeader( hAcm, &acmHeader, NULL );\r
371                 acmStreamClose( hAcm, NULL );\r
372                 SAFE_FREE( pDestData );\r
373                 return FDKERR_SoundType\82ª\96³\8cø;          // ACM\83w\83b\83_\93o\98^\8e¸\94s\r
374         }\r
375 \r
376         // \95Ï\8a·\r
377         if( ( mmr = acmStreamConvert( hAcm, &acmHeader, NULL ) ) != 0 )\r
378         {\r
379                 acmStreamUnprepareHeader( hAcm, &acmHeader, NULL );\r
380                 acmStreamClose( hAcm, NULL );\r
381                 SAFE_FREE( pDestData );\r
382                 return FDKERR_SoundType\82ª\96³\8cø;          // ACM\95Ï\8a·\8e¸\94s\r
383         }\r
384 \r
385         // \90^\82Ì\95Ï\8a·\8cã\83T\83C\83Y\82ð\8eæ\93¾\r
386         dwDestSize = acmHeader.cbDstLengthUsed;\r
387 \r
388         // ACM \82ð\95Â\82\82é\r
389         acmStreamUnprepareHeader( hAcm, &acmHeader, NULL );\r
390         acmStreamClose( hAcm, NULL );\r
391 \r
392         // \8dì\90¬\82Æ\8f\91\82«\8d\9e\82Ý\r
393         HRESULT hr;\r
394         if( FAILED( hr = CreateAndCopyBuffer( pDS, &wfxDest, pDestData, dwDestSize ) ) )\r
395         {\r
396                 SAFE_FREE( pDestData );\r
397                 return hr;\r
398         }\r
399         SAFE_FREE( pDestData );\r
400         \r
401         m_SoundType = SOUNDTYPE_MP3;\r
402 \r
403         return S_OK;\r
404 }\r
405 \r
406 HRESULT CSound::DecodeFromWAV( LPDIRECTSOUND8 pDS, BYTE* pSrcData, DWORD dwSrcSize )\r
407 {\r
408         MMRESULT mmr;\r
409 \r
410         // \83`\83F\83b\83N\r
411         MMIOINFO mmio;\r
412         ZeroMemory( &mmio, sizeof(MMIOINFO) );\r
413         mmio.pchBuffer = (LPSTR)pSrcData;\r
414         mmio.fccIOProc = FOURCC_MEM;\r
415         mmio.cchBuffer = dwSrcSize;\r
416 \r
417         HMMIO hmmio;\r
418         if( ( hmmio = mmioOpen( NULL, &mmio, MMIO_READ ) ) == NULL )    // \83\81\83\82\83\8a\82©\82çMMIO\83I\81[\83v\83\93\r
419                 return FDKERR_SoundType\82ª\96³\8cø;          // RIFF \82Å\82Í\82È\82©\82Á\82½\r
420 \r
421         // WAVE\83`\83\83\83\93\83N\82Ö\88Ú\93®\r
422         MMCKINFO ckiParent;\r
423         ckiParent.fccType = mmioFOURCC('W','A','V','E');\r
424         if( ( mmr = mmioDescend( hmmio, &ckiParent, NULL, MMIO_FINDRIFF ) ) != 0 )\r
425         {\r
426                 mmioClose( hmmio, 0 );\r
427                 return FDKERR_SoundType\82ª\96³\8cø;          // WAVE\83`\83\83\83\93\83N\88Ú\93®\8e¸\94s\r
428         }\r
429 \r
430         // WAVE\82Ìfmt\83`\83\83\83\93\83N\82Ö\82Ì\88Ú\93®\r
431         MMCKINFO ckiChild;\r
432         ckiChild.ckid = mmioFOURCC('f','m','t',' ');\r
433         if( ( mmr = mmioDescend( hmmio, &ckiChild, &ckiParent, MMIO_FINDCHUNK ) ) != 0 )\r
434         {\r
435                 mmioClose( hmmio, 0 );\r
436                 return FDKERR_SoundType\82ª\96³\8cø;          // fmt \83`\83\83\83\93\83N\88Ú\93®\8e¸\94s\r
437         }\r
438 \r
439         // WAVEFORMATEX \82ð\8eæ\93¾\82µ\81Afmt\83`\83\83\83\93\83N\82©\82ç\94²\82¯\82é\r
440         WAVEFORMATEX* pw = (WAVEFORMATEX *) (((LPBYTE)pSrcData) + ((int)mmioSeek( hmmio, 0, SEEK_CUR )) );\r
441         if( ( mmr = mmioAscend( hmmio, &ckiChild, 0 ) ) != MMSYSERR_NOERROR )\r
442         {\r
443                 mmioClose( hmmio, 0 );\r
444                 return FDKERR_SoundType\82ª\96³\8cø;          // fmt \83`\83\83\83\93\83N\92E\8fo\8e¸\94s\r
445         }\r
446 \r
447         // WAVEFORMATEX \82ð\90V\82µ\82­ malloc \82µ\82½\97Ì\88æ\82É\95¡\8eÊ\82·\82é\r
448         WORD wfxsize = sizeof(WAVEFORMATEX) + ( ( pw->wFormatTag != WAVE_FORMAT_PCM ) ? pw->cbSize : 0 );\r
449         WAVEFORMATEX* pwfx = (WAVEFORMATEX*) malloc( wfxsize );\r
450         if( ! pwfx )\r
451         {\r
452                 mmioClose( hmmio, 0 );\r
453                 return E_OUTOFMEMORY;                           // \83\81\83\82\83\8a\95s\91«\r
454         }\r
455         CopyMemory( pwfx, pw, wfxsize );\r
456 \r
457         // data\83`\83\83\83\93\83N\82Ö\88Ú\93®\r
458         ckiChild.ckid = mmioFOURCC('d','a','t','a');\r
459         if( ( mmr = mmioDescend( hmmio, &ckiChild, &ckiParent, MMIO_FINDCHUNK ) ) != 0 )\r
460         {\r
461                 mmioClose( hmmio, 0 );\r
462                 SAFE_FREE( pwfx );\r
463                 return FDKERR_SoundType\82ª\96³\8cø;          // data\83`\83\83\83\93\83N\82Ö\82Ì\88Ú\93®\8e¸\94s\r
464         }\r
465 \r
466         // \83T\83C\83Y\82Æ\83|\83C\83\93\83^\82ð\8eæ\93¾\82µ\81AMMIO\82ð\95Â\82\82é\r
467         BYTE* pDestData = (LPBYTE) ((LPBYTE)pSrcData + mmioSeek( hmmio, 0, SEEK_CUR ) );\r
468         DWORD dwDestSize = ckiChild.cksize;\r
469         mmioClose( hmmio, 0 );\r
470 \r
471         /* \82±\82±\82Ü\82Å\82Å\81Apwfx, pDestData, dwDestSize \82É RiffWAV \82Ì\93à\97e\82ª\93¾\82ç\82ê\82½\81B*/\r
472 \r
473         // WAVE \83t\83H\81[\83}\83b\83g\82Å\82È\82¢\8fê\8d\87\82Í ACM \82Å\83f\83R\81[\83h\r
474         if( pwfx->wFormatTag != WAVE_FORMAT_PCM )\r
475         {\r
476                 WAVEFORMATEX* pSrcWfx   = pwfx;\r
477                 BYTE* pSrcData                  = pDestData;\r
478                 DWORD dwSrcSize                 = dwDestSize;\r
479 \r
480                 // \83\\81[\83X\82©\82ç PCM \82É\95Ï\8a·\89Â\94\\82È codec \82ª\82 \82é\82©\92²\82×\81AwfxDest \82ð\90Ý\92è\r
481                 WAVEFORMATEX wfxDest;\r
482                 wfxDest.wFormatTag = WAVE_FORMAT_PCM;\r
483                 if( ( mmr = acmFormatSuggest( NULL, pSrcWfx, &wfxDest, sizeof(WAVEFORMATEX), ACM_FORMATSUGGESTF_WFORMATTAG ) ) != 0 )\r
484                 {\r
485                         SAFE_FREE( pSrcWfx );\r
486                         return FDKERR_SoundType\82ª\96³\8cø;          // CODEC \82ª\82È\82©\82Á\82½\r
487                 }\r
488 \r
489 \r
490                 // ACM \82ð\83I\81[\83v\83\93\82·\82é\r
491                 HACMSTREAM hAcm;\r
492                 if( ( mmr = acmStreamOpen( &hAcm, NULL, pSrcWfx, &wfxDest, NULL, NULL, NULL, ACM_STREAMOPENF_NONREALTIME ) ) != 0 )\r
493                 {\r
494                         SAFE_FREE( pSrcWfx );\r
495                         return FDKERR_SoundType\82ª\96³\8cø;          // ACM\82Ì\83I\81[\83v\83\93\82É\8e¸\94s\r
496                 }\r
497 \r
498                 // \95Ï\8a·\8cã\82Ì\83T\83C\83Y\82ð\8eæ\93¾\82µ\81AdwDestSize \82É\90Ý\92è\r
499                 if( ( mmr = acmStreamSize( hAcm, dwSrcSize, &dwDestSize, ACM_STREAMSIZEF_SOURCE ) ) != 0 )\r
500                 {\r
501                         acmStreamClose( hAcm, NULL );\r
502                         SAFE_FREE( pSrcWfx );\r
503                         return FDKERR_SoundType\82ª\96³\8cø;          // \95Ï\8a·\8cã\82Ì\83T\83C\83Y\82Ì\8eæ\93¾\82É\8e¸\94s\r
504                 }\r
505                 if( dwDestSize == 0 )\r
506                 {\r
507                         acmStreamClose( hAcm, NULL );\r
508                         SAFE_FREE( pSrcWfx );\r
509                         return FDKERR_SoundType\82ª\96³\8cø;          // \95Ï\8a·\8cã\82Ì\83T\83C\83Y\82ª\83[\83\8d\r
510                 }\r
511 \r
512                 // \95Ï\8a·\8cã\83t\83H\81[\83}\83b\83g\82Ì\8eæ\93¾\81\95\90Ý\92è\r
513                 pwfx = (WAVEFORMATEX*) malloc( sizeof(WAVEFORMATEX) );\r
514                 if( ! pwfx )\r
515                 {\r
516                         acmStreamClose( hAcm, NULL );\r
517                         SAFE_FREE( pSrcWfx );\r
518                         return E_OUTOFMEMORY;                           // \83\81\83\82\83\8a\95s\91«\r
519                 }\r
520                 CopyMemory( pwfx, &wfxDest, sizeof(WAVEFORMATEX) );\r
521 \r
522                 // PCM\83o\83b\83t\83@\82Ì\8am\95Û\r
523                 pDestData = (LPBYTE) malloc( dwDestSize );\r
524                 if( ! pDestData )\r
525                 {\r
526                         acmStreamClose( hAcm, NULL );\r
527                         SAFE_FREE( pSrcWfx );\r
528                         return E_OUTOFMEMORY;                           // \83\81\83\82\83\8a\95s\91«\r
529                 }\r
530 \r
531                 // \95Ï\8a·\97p\83w\83b\83_\8f\80\94õ\r
532                 ACMSTREAMHEADER acmHeader;\r
533                 ZeroMemory( &acmHeader, sizeof(acmHeader) );\r
534                 acmHeader.cbStruct              = sizeof(acmHeader);\r
535                 acmHeader.pbSrc                 = pSrcData;\r
536                 acmHeader.cbSrcLength   = dwSrcSize;\r
537                 acmHeader.pbDst                 = pDestData;\r
538                 acmHeader.cbDstLength   = dwDestSize;\r
539                 if( ( mmr = acmStreamPrepareHeader( hAcm, &acmHeader, NULL ) ) != 0 )\r
540                 {\r
541                         acmStreamUnprepareHeader( hAcm, &acmHeader, NULL );\r
542                         acmStreamClose( hAcm, NULL );\r
543                         SAFE_FREE( pSrcWfx );\r
544                         SAFE_FREE( pwfx );\r
545                         SAFE_FREE( pDestData );\r
546                         return FDKERR_SoundType\82ª\96³\8cø;          // ACM\83w\83b\83_\93o\98^\8e¸\94s\r
547                 }\r
548 \r
549                 // \95Ï\8a·\r
550                 if( ( mmr = acmStreamConvert( hAcm, &acmHeader, NULL ) ) != 0 )\r
551                 {\r
552                         acmStreamUnprepareHeader( hAcm, &acmHeader, NULL );\r
553                         acmStreamClose( hAcm, NULL );\r
554                         SAFE_FREE( pSrcWfx );\r
555                         SAFE_FREE( pwfx );\r
556                         SAFE_FREE( pDestData );\r
557                         return FDKERR_SoundType\82ª\96³\8cø;          // ACM\95Ï\8a·\8e¸\94s\r
558                 }\r
559 \r
560                 // \90^\82Ì\95Ï\8a·\8cã\83T\83C\83Y\82ð\8eæ\93¾\r
561                 dwDestSize = acmHeader.cbDstLengthUsed;\r
562 \r
563                 // ACM \82ð\95Â\82\82é\r
564                 acmStreamUnprepareHeader( hAcm, &acmHeader, NULL );\r
565                 acmStreamClose( hAcm, NULL );\r
566 \r
567                 // \8dì\90¬\82Æ\8f\91\82«\8d\9e\82Ý\r
568                 HRESULT hr;\r
569                 if( FAILED( hr = CreateAndCopyBuffer( pDS, pwfx, pDestData, dwDestSize ) ) )\r
570                 {\r
571                         SAFE_FREE( pwfx );\r
572                         SAFE_FREE( pSrcWfx );\r
573                         SAFE_FREE( pDestData );\r
574                         return hr;\r
575                 }\r
576                 SAFE_FREE( pwfx );\r
577                 SAFE_FREE( pSrcWfx );\r
578                 SAFE_FREE( pDestData );\r
579         }\r
580         else\r
581         {\r
582                 // \8dì\90¬\82Æ\8f\91\82«\8d\9e\82Ý\r
583                 HRESULT hr;\r
584                 if( FAILED( hr = CreateAndCopyBuffer( pDS, pwfx, pDestData, dwDestSize ) ) )\r
585                 {\r
586                         SAFE_FREE( pwfx );\r
587                         return hr;\r
588                 }\r
589                 SAFE_FREE( pwfx );\r
590         }\r
591 \r
592         m_SoundType = SOUNDTYPE_WAV;\r
593 \r
594         return S_OK;\r
595 }\r
596 \r
597 HRESULT CSound::DecodeFromOgg( LPDIRECTSOUND8 pDS, BYTE* pSrcData, DWORD dwSrcSize )\r
598 {\r
599         COgg ogg;\r
600 \r
601         // \83`\83F\83b\83N\r
602         if( ! ogg.Init( pSrcData, dwSrcSize ) )\r
603                 return FDKERR_SoundType\82ª\96³\8cø;          // Ogg \82\82á\82È\82¢\r
604 \r
605         // \83f\83R\81[\83h\83o\83b\83t\83@\82Ì\8am\95Û\r
606         size_t szDestDataSize = ogg.GetDestSize();\r
607         if( szDestDataSize == 0 )\r
608                 return FDKERR_SoundType\82ª\96³\8cø;\r
609 \r
610         LPBYTE pDestData = (LPBYTE) malloc( szDestDataSize );\r
611         if( ! pDestData )\r
612         {\r
613                 ogg.Term();\r
614                 return E_OUTOFMEMORY;                           // \83\81\83\82\83\8a\95s\91«\r
615         }\r
616         \r
617         // \83f\83R\81[\83h\r
618         if( ! ogg.ConvertToWav( pDestData, szDestDataSize ) )\r
619         {\r
620                 ogg.Term();\r
621                 SAFE_FREE( pDestData );\r
622                 return FDKERR_SoundType\82ª\96³\8cø;          // \95Ï\8a·\8e¸\94s\r
623         }\r
624 \r
625         // WAVE\83t\83H\81[\83}\83b\83g\82Ì\8eæ\93¾\r
626         WAVEFORMATEX wfx;\r
627         if( ! ogg.GetFormat( &wfx ) )\r
628         {\r
629                 ogg.Term();\r
630                 SAFE_FREE( pDestData );\r
631                 return FDKERR_SoundType\82ª\96³\8cø;          // \8eæ\93¾\8e¸\94s\r
632         }\r
633 \r
634         // \83T\83E\83\93\83h\82Ì\8dì\90¬\82Æ\8f\91\82«\8d\9e\82Ý\r
635         HRESULT hr;\r
636         if( FAILED( hr = CreateAndCopyBuffer( pDS, &wfx, pDestData, (DWORD)szDestDataSize ) ) )\r
637         {\r
638                 ogg.Term();\r
639                 SAFE_FREE( pDestData );\r
640                 return hr;\r
641         }\r
642 \r
643         // \8a®\97¹\r
644         SAFE_FREE( pDestData );\r
645         ogg.Term();\r
646 \r
647         m_SoundType = SOUNDTYPE_OGG;\r
648 \r
649         return S_OK;\r
650 }\r
651 \r
652 void    CSound::Play( bool bLoop )\r
653 {\r
654         HRESULT hr;\r
655 \r
656         // \83`\83F\83b\83N\r
657         if( this->pDSBuffer == NULL )\r
658                 return;         // \83Z\83J\83\93\83_\83\8a\83o\83b\83t\83@\82ª\96³\8cø\r
659 \r
660         // \83T\83E\83\93\83h\83o\83b\83t\83@\82Ì\83\8a\83X\83g\83A\83`\83F\83b\83N\r
661         BOOL bRestored = FALSE;\r
662     if( FAILED( hr = this->RestoreBuffer( this->pDSBuffer, &bRestored ) ) )\r
663                 return;         // \83T\83E\83\93\83h\83o\83b\83t\83@\82Ì\95\9c\8b\8c\82É\8e¸\94s\r
664         if( bRestored )\r
665         {\r
666                 Term();\r
667                 TCHAR filename[_MAX_PATH];\r
668                 lstrcpyn( filename, this->strFileName, _MAX_PATH );\r
669                 if( FAILED( hr = CreateFromFile( CSoundManager::GetDirectSound(), filename ) ) )\r
670                         return; // \83T\83E\83\93\83h\83o\83b\83t\83@\82Ì\95\9c\8b\8c\82É\8e¸\94s\r
671         }\r
672 \r
673         // \8dÄ\90\8aJ\8en\88Ê\92u\82Ì\8c\88\92è\r
674         DWORD dwStartPos = (m_SoundType == SOUNDTYPE_MP3) ? GetPositionFromTime( CSoundManager::dbMP3\8dÄ\90\92x\89\84\8e\9e\8aÔms ) : 0;\r
675 \r
676         // \8dÄ\90\83J\81[\83\\83\8b\8f\89\8aú\89»\r
677         DWORD dwStatus;\r
678         this->pDSBuffer->SetCurrentPosition( dwStartPos );\r
679         this->pDSBuffer->GetStatus( &dwStatus );\r
680         if( dwStatus & DSBSTATUS_PLAYING )\r
681         {\r
682                 this->pDSBuffer->Stop();\r
683                 this->pDSBuffer->SetCurrentPosition( dwStartPos );\r
684         }\r
685 \r
686         // \8dÄ\90\r
687         DWORD dwFreq;\r
688         this->pDSBuffer->SetFrequency( DSBFREQUENCY_ORIGINAL );\r
689         this->pDSBuffer->GetFrequency( &dwFreq );\r
690         this->pDSBuffer->SetFrequency( (DWORD)(dwFreq * this->fSpeed * this->fPitch ) );\r
691         this->pDSBuffer->SetVolume( this->lVolume );\r
692         this->pDSBuffer->SetPan( this->lPan );\r
693         this->pDSBuffer->Play( 0, 0, (bLoop) ? DSBPLAY_LOOPING : 0 );\r
694 \r
695         this->bLoop = bLoop;\r
696         this->nPause = 0;\r
697 }\r
698 \r
699 void    CSound::Stop()\r
700 {\r
701         if( this->pDSBuffer )\r
702         {\r
703                 this->pDSBuffer->Stop();\r
704                 this->pDSBuffer->SetCurrentPosition( 0 );\r
705                 this->nPause = 0;\r
706         }\r
707 }\r
708 \r
709 void    CSound::Pause()\r
710 {\r
711         if( this->pDSBuffer && IsPlay() )\r
712         {\r
713                 this->pDSBuffer->GetCurrentPosition( &this->dwCurrentPosition, NULL );\r
714                 this->pDSBuffer->Stop();\r
715                 this->nPause ++;\r
716         }\r
717 }\r
718 \r
719 void    CSound::Cont()\r
720 {\r
721         if( this->nPause == 0 )\r
722                 return;\r
723         this->nPause --;\r
724 \r
725         HRESULT hr;\r
726 \r
727         // \83`\83F\83b\83N\r
728         if( this->pDSBuffer == NULL )\r
729                 return; // \83Z\83J\83\93\83_\83\8a\83o\83b\83t\83@\82ª\96³\8cø\r
730 \r
731         // \83T\83E\83\93\83h\83o\83b\83t\83@\82Ì\83\8a\83X\83g\83A\83`\83F\83b\83N\r
732         BOOL bRestored = FALSE;\r
733     if( FAILED( hr = RestoreBuffer( this->pDSBuffer, &bRestored ) ) )\r
734                 return; // \83T\83E\83\93\83h\83o\83b\83t\83@\82Ì\95\9c\8b\8c\82É\8e¸\94s\r
735         if( bRestored )\r
736         {\r
737                 Term();\r
738                 TCHAR   filename[_MAX_PATH];\r
739                 lstrcpyn( filename, this->strFileName, _MAX_PATH );\r
740                 if( FAILED( hr = CreateFromFile( CSoundManager::GetDirectSound(), filename ) ) )\r
741                         return; // \83T\83E\83\93\83h\83o\83b\83t\83@\82Ì\95\9c\8b\8c\82É\8e¸\94s\r
742         }\r
743 \r
744         // \8dÄ\90\8aJ\8en\88Ê\92u\82Ì\8c\88\92è\r
745         DWORD dwStartPos = this->dwCurrentPosition;\r
746 \r
747         // \8dÄ\90\83J\81[\83\\83\8b\8f\89\8aú\89»\r
748         DWORD dwStatus;\r
749         this->pDSBuffer->SetCurrentPosition( dwStartPos );\r
750         this->pDSBuffer->GetStatus( &dwStatus );\r
751         if( dwStatus & DSBSTATUS_PLAYING )\r
752         {\r
753                 this->pDSBuffer->Stop();\r
754                 this->pDSBuffer->SetCurrentPosition( dwStartPos );\r
755         }\r
756 \r
757         // \8dÄ\90\r
758         DWORD dwFreq;\r
759         this->pDSBuffer->SetFrequency( DSBFREQUENCY_ORIGINAL );\r
760         this->pDSBuffer->GetFrequency( &dwFreq );\r
761         this->pDSBuffer->SetFrequency( (DWORD)(dwFreq * this->fSpeed * this->fPitch ) );\r
762         this->pDSBuffer->SetVolume( this->lVolume );\r
763         this->pDSBuffer->SetPan( this->lPan );\r
764         this->pDSBuffer->Play( 0, 0, (this->bLoop) ? DSBPLAY_LOOPING : 0 );\r
765 }\r
766 \r
767 void    CSound::Cont( double dbContTime )\r
768 {\r
769         // \83J\81[\83\\83\8b\88Ú\93®(this->dwCurrentPosition\82à\88Ú\93®)\r
770         SetPosition( GetPositionFromTime( dbContTime ) );\r
771         \r
772         // this->dwCurrentPosition \82©\82ç\8dÄ\8aJ\r
773         Cont();\r
774 }\r
775 \r
776 void    CSound::SetPosition( DWORD dwNewPosition )\r
777 {\r
778         if( ! this->pDSBuffer )\r
779                 return;\r
780 \r
781         // \83u\83\8d\83b\83N\8b«\8aE\82É\82»\82ë\82¦\82é\r
782         DWORD dwSize;\r
783         this->pDSBuffer->GetFormat( NULL, 0, &dwSize );\r
784         WAVEFORMATEX* pWF = (LPWAVEFORMATEX) malloc( dwSize );\r
785         this->pDSBuffer->GetFormat( pWF, dwSize, NULL );\r
786         dwNewPosition -= dwNewPosition % pWF->nBlockAlign;\r
787 \r
788         // \83J\81[\83\\83\8b\82ð\88Ú\93®\r
789         DSBCAPS dsbc;\r
790         ZeroMemory( &dsbc, sizeof(dsbc) );\r
791         dsbc.dwSize = sizeof(DSBCAPS);\r
792         this->pDSBuffer->GetCaps( &dsbc );\r
793         if( dwNewPosition < dsbc.dwBufferBytes )\r
794                 this->pDSBuffer->SetCurrentPosition( dwNewPosition );\r
795 \r
796         this->dwCurrentPosition = dwNewPosition;        // \88ê\89\9e\94½\89f...\r
797         free( pWF );\r
798 }\r
799 \r
800 DWORD   CSound::GetPositionFromTime( double dbTime )\r
801 {\r
802         if( ! this->pDSBuffer )\r
803                 return 0;\r
804 \r
805         // \8eü\94g\90\94\83X\83s\81[\83h\82ð\89Á\96¡\r
806         dbTime = dbTime * this->fSpeed * this->fPitch;\r
807 \r
808         // MP3 \82È\82ç\81AdwTime \82É\92x\89\84\8e\9e\8aÔ\82ð\89Á\8eZ\81B\r
809         if( m_SoundType == SOUNDTYPE_MP3 ) \r
810                 dbTime += CSoundManager::dbMP3\8dÄ\90\92x\89\84\8e\9e\8aÔms;\r
811 \r
812         // dbTime [ms] \82©\82ç dwCurPos [byte] \82ð\8eZ\8fo\r
813         DWORD dwCurPos, dwSize;\r
814         this->pDSBuffer->GetFormat( NULL, 0, &dwSize );\r
815         WAVEFORMATEX* pWF = (LPWAVEFORMATEX) malloc( dwSize );\r
816         this->pDSBuffer->GetFormat( pWF, dwSize, NULL );\r
817         dwCurPos = (DWORD)(dbTime * 0.001 * (pWF->nSamplesPerSec/* * this->fSpeedw*/) * pWF->nBlockAlign);      //pWF->nAvgBytesPerSec \82Í\8f¬\82³\82¢\92l\82ð\95Ô\82·\82±\82Æ\82ª\82 \82è\81A\8cv\8eZ\8e®\8e\9f\91æ\82Å\82Í\83I\81[\83o\81[\83t\83\8d\81[\82·\82é\82Ì\82Å\92\8d\88Ó\r
818 \r
819         // \83u\83\8d\83b\83N\8b«\8aE\82É\82»\82ë\82¦\82é\r
820         dwCurPos -= dwCurPos % pWF->nBlockAlign;\r
821 \r
822         free( pWF );\r
823         return dwCurPos;\r
824 }\r
825 \r
826 void    CSound::SetVolume( long lVolume )\r
827 {\r
828         if( lVolume == 0 )\r
829                 lVolume = 1;            // Vol = 0 \82Í\82È\82º\82©\89¹\97Ê100%\82É\82È\82Á\82Ä\82µ\82Ü\82¤\82½\82ß...\r
830 \r
831         this->lVolume = (long)(( 20.0 * log10( lVolume / 100.0 ) ) * 100.0);\r
832 \r
833         // \89\89\91t\92\86\82È\82ç\91¦\94½\89f\r
834         if( IsPlay() )\r
835                 this->pDSBuffer->SetVolume( this->lVolume );\r
836 }\r
837 \r
838 void    CSound::SetPan( long lPan )\r
839 {\r
840         if( lPan == 0 ) this->lPan = 0;\r
841         else if( lPan == -100 ) this->lPan = DSBPAN_LEFT;\r
842         else if( lPan ==  100 ) this->lPan = DSBPAN_RIGHT;\r
843         else if( lPan < 0 ) this->lPan = (long)( (20.0 * log10((lPan+100)/100.0)) * 100.0 );\r
844         else this->lPan = (long)( (-20.0 * log10((100-lPan)/100.0)) * 100.0 );\r
845 \r
846         // \89\89\91t\92\86\82È\82ç\91¦\94½\89f\r
847         if( IsPlay() )\r
848                 this->pDSBuffer->SetPan( lPan );\r
849 }\r
850 \r
851 bool    CSound::IsPlay()\r
852 {\r
853         if( ! this->pDSBuffer )\r
854                 return false;\r
855 \r
856         DWORD dwStatus;\r
857         this->pDSBuffer->GetStatus( &dwStatus );\r
858         return dwStatus & DSBSTATUS_PLAYING;\r
859 }\r
860 \r
861 DWORD   CSound::GetFrequency()\r
862 {\r
863         if( ! this->pDSBuffer )\r
864                 return 0;\r
865 \r
866         DWORD dwFreq;\r
867         this->pDSBuffer->GetFrequency( &dwFreq );\r
868         return dwFreq;\r
869 }\r
870 \r
871 DWORD   CSound::SetFrequency( DWORD dwFreq )\r
872 {\r
873         if( ! this->pDSBuffer )\r
874                 return 0;\r
875 \r
876         DWORD dwOldFreq;\r
877         this->pDSBuffer->GetFrequency( &dwOldFreq );\r
878         this->pDSBuffer->SetFrequency( dwFreq );\r
879         return dwOldFreq;\r
880 }\r
881 \r
882 double  CSound::GetTotalTime()\r
883 {\r
884         if( this->pDSBuffer == NULL )\r
885                 return 0.0;\r
886 \r
887         // WAVEFORMATEX \8eæ\93¾\r
888         DWORD dwSize;\r
889         this->pDSBuffer->GetFormat( NULL, 0, &dwSize );\r
890         LPWAVEFORMATEX pWF = (LPWAVEFORMATEX) malloc( dwSize );\r
891         this->pDSBuffer->GetFormat( pWF, dwSize, NULL );\r
892 \r
893         // \91\8d\8e\9e\8aÔ\82Ì\8cv\8eZ\r
894         double dbTotalTime = (double)( this->dwDSBufferSize / ( pWF->nAvgBytesPerSec * 0.001 ) );\r
895 \r
896         free( pWF );\r
897         return dbTotalTime;\r
898 }\r
899 \r
900         }//Sound\r
901 }//FDK