3 #include "CSoundManager.h"
\r
4 #include "FDKError.h"
\r
7 #include "vorbis/vorbisfile.h"
\r
16 this->pDSBuffer = NULL;
\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
25 this->fSpeed = 1.0f;
\r
26 this->fPitch = 1.0f;
\r
27 this->bLoop = false;
\r
29 this->dwCurrentPosition = 0;
\r
35 HRESULT CSound::DuplicateFromSound( LPDIRECTSOUND8 pDS, CSound* srcSound )
\r
39 //
\8fð
\8c\8f\83`
\83F
\83b
\83N
\r
41 return FDKERR_DirectSound
\82ªNULL;
\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
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
51 //
\83T
\83E
\83\93\83h
\83o
\83b
\83t
\83@
\83T
\83C
\83Y
\82Ì
\8eæ
\93¾
\r
52 this->dwDSBufferSize = srcSound->GetDirectSoundBufferSize();
\r
56 HRESULT CSound::CreateFromFile( LPDIRECTSOUND8 pDS, LPCTSTR filename )
\r
60 //
\8fð
\8c\8f\83`
\83F
\83b
\83N
\r
62 return FDKERR_DirectSound
\82ªNULL;
\r
64 //
\83t
\83@
\83C
\83\8b\82Ì
\93Ç
\82Ý
\8d\9e\82Ý
\r
66 if( ! file.Load( filename ) )
\r
69 return FDKERR_
\83t
\83@
\83C
\83\8b\82Ì
\93Ç
\82Ý
\8d\9e\82Ý
\8e¸
\94s;
\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
76 return FDKERR_
\83T
\83E
\83\93\83h
\83o
\83b
\83t
\83@
\82Ì
\8dì
\90¬
\82É
\8e¸
\94s;
\r
79 lstrcpyn( this->strFileName, filename, _MAX_PATH );
\r
84 HRESULT CSound::CreateFromMemory( LPDIRECTSOUND8 pDS, BYTE* pData, DWORD dwSize )
\r
88 //
\8fð
\8c\8f\83`
\83F
\83b
\83N
\r
89 if( ! pData || dwSize == 0)
\r
90 return E_INVALIDARG;
\r
93 return FDKERR_DirectSound
\82ªNULL;
\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
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
108 HRESULT CSound::CreateAndCopyBuffer( LPDIRECTSOUND8 pDS, WAVEFORMATEX* pwfx, BYTE* pData, DWORD dwSize )
\r
112 this->dwDSBufferSize = dwSize;
\r
114 //
\83T
\83E
\83\93\83h
\83o
\83b
\83t
\83@
\82Ì
\90¶
\90¬
\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
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
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
136 CopyMemory( pDSLockedBuffer, pData, dwSize );
\r
137 this->pDSBuffer->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );
\r
142 HRESULT CSound::RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored )
\r
146 //
\8fð
\8c\8f\83`
\83F
\83b
\83N
\r
148 return CO_E_NOTINITIALIZED;
\r
150 if( pbWasRestored ) *pbWasRestored = FALSE;
\r
152 //
\83X
\83e
\81[
\83^
\83X
\82Å Lost
\83`
\83F
\83b
\83N
\r
154 if( FAILED( hr = pDSB->GetStatus( &dwStatus ) ) )
\r
157 if( dwStatus & DSBSTATUS_BUFFERLOST )
\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
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
168 if( pbWasRestored ) *pbWasRestored = TRUE;
\r
173 HRESULT CSound::DecodeFromXA( LPDIRECTSOUND8 pDS, BYTE* pSrcData, DWORD dwSrcSize )
\r
177 XASTREAMHEADER xash;
\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
186 ps = (UCHAR *)pSrcData + sizeof(XAHEADER);
\r
187 WAVEFORMATEX* pwfx = (WAVEFORMATEX*) malloc( sizeof(WAVEFORMATEX) );
\r
188 hxas = xaDecodeOpen( &xah, pwfx );
\r
190 return FDKERR_SoundType
\82ª
\96³
\8cø; // XA
\82Å
\82Í
\82È
\82©
\82Á
\82½
\r
192 //
\83f
\83R
\81[
\83h
\8cã
\83T
\83C
\83Y
\82Ì
\8eæ
\93¾
\r
193 if( ! xaDecodeSize( hxas, xah.nDataLen, &dlen ) )
\r
195 xaDecodeClose( hxas );
\r
196 return FDKERR_SoundType
\82ª
\96³
\8cø; // XA
\82Å
\82Í
\82È
\82©
\82Á
\82½
\81H
\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
203 xaDecodeClose( hxas );
\r
204 return E_OUTOFMEMORY; //
\83\81\83\82\83\8a\95s
\91«
\r
207 // XA
\81¨ WAV
\95Ï
\8a·
\r
209 xash.nSrcLen = xah.nDataLen;
\r
211 xash.pDst = (UCHAR *) pDestData;
\r
212 xash.nDstLen = dlen;
\r
214 if( ! xaDecodeConvert( hxas, &xash ) )
\r
216 xaDecodeClose( hxas );
\r
217 return FDKERR_SoundType
\82ª
\96³
\8cø; // XA
\82Å
\82Í
\82È
\82©
\82Á
\82½
\81H
\r
220 // XA
\95Ï
\8a·
\8a®
\97¹
\r
221 xaDecodeClose( hxas );
\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
227 //
\8dì
\90¬
\82Æ
\8f\91\82«
\8d\9e\82Ý
\r
229 if( FAILED( hr = CreateAndCopyBuffer( pDS, pwfx, pDestData, dwTrueLen ) ) )
\r
232 SAFE_FREE( pDestData );
\r
236 SAFE_FREE( pDestData );
\r
238 m_SoundType = SOUNDTYPE_XA;
\r
243 HRESULT CSound::DecodeFromMP3( LPDIRECTSOUND8 pDS, BYTE* pSrcData, DWORD dwSrcSize )
\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
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
252 DWORD dwID3Size = pSrcData[9] + (pSrcData[8]<<7) + (pSrcData[7]<<14) + (pSrcData[6]<<21);
\r
253 if( pSrcData[3] >= 0x04)
\r
255 if( pSrcData[5] & 0x10 )
\r
256 dwID3Size += 20; // ID3v2.4.0
\88È
\8d~
\81E
\83t
\83b
\83^
\82 \82è
\r
258 dwID3Size += 10; // ID3v2.4.0
\88È
\8d~
\81E
\83t
\83b
\83^
\82È
\82µ
\r
261 dwID3Size += 10; // ID3v2.3.0
\88È
\91O
\81E
\83t
\83b
\83^
\82È
\82µ
\r
263 if( dwSrcSize <= dwID3Size + 128 )
\r
264 return FDKERR_SoundType
\82ª
\96³
\8cø; // MP3
\82¶
\82á
\82È
\82¢
\r
266 pSrcData += dwID3Size;
\r
267 dwSrcSize -= dwID3Size;
\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
275 static const int anBitrate[2][3][16] = {
\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
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
289 static const int anFreq[2][4] = {
\r
290 { 44100,48000,32000,0 },
\r
291 { 22050,24000,16000,0 },
\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
297 return FDKERR_SoundType
\82ª
\96³
\8cø; // MP3
\82¶
\82á
\82È
\82©
\82Á
\82½
\81H
\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
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
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
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
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
332 BYTE* pDestData = NULL;
\r
333 DWORD dwDestSize = 0;
\r
335 // ACM
\82ð
\83I
\81[
\83v
\83\93\82·
\82é
\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
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
343 acmStreamClose( hAcm, NULL );
\r
344 return FDKERR_SoundType
\82ª
\96³
\8cø; // Error:
\83T
\83C
\83Y
\8eæ
\93¾
\8e¸
\94s
\r
346 if( dwDestSize == 0 )
\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
352 // PCM
\83o
\83b
\83t
\83@
\82Ì
\8am
\95Û
\r
353 pDestData = (LPBYTE) malloc( dwDestSize );
\r
356 acmStreamClose( hAcm, NULL );
\r
357 return E_OUTOFMEMORY; // Error:
\83\81\83\82\83\8a\95s
\91«
\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
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
377 if( ( mmr = acmStreamConvert( hAcm, &acmHeader, NULL ) ) != 0 )
\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
385 //
\90^
\82Ì
\95Ï
\8a·
\8cã
\83T
\83C
\83Y
\82ð
\8eæ
\93¾
\r
386 dwDestSize = acmHeader.cbDstLengthUsed;
\r
388 // ACM
\82ð
\95Â
\82¶
\82é
\r
389 acmStreamUnprepareHeader( hAcm, &acmHeader, NULL );
\r
390 acmStreamClose( hAcm, NULL );
\r
392 //
\8dì
\90¬
\82Æ
\8f\91\82«
\8d\9e\82Ý
\r
394 if( FAILED( hr = CreateAndCopyBuffer( pDS, &wfxDest, pDestData, dwDestSize ) ) )
\r
396 SAFE_FREE( pDestData );
\r
399 SAFE_FREE( pDestData );
\r
401 m_SoundType = SOUNDTYPE_MP3;
\r
406 HRESULT CSound::DecodeFromWAV( LPDIRECTSOUND8 pDS, BYTE* pSrcData, DWORD dwSrcSize )
\r
410 //
\83`
\83F
\83b
\83N
\r
412 ZeroMemory( &mmio, sizeof(MMIOINFO) );
\r
413 mmio.pchBuffer = (LPSTR)pSrcData;
\r
414 mmio.fccIOProc = FOURCC_MEM;
\r
415 mmio.cchBuffer = dwSrcSize;
\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
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
426 mmioClose( hmmio, 0 );
\r
427 return FDKERR_SoundType
\82ª
\96³
\8cø; // WAVE
\83`
\83\83\83\93\83N
\88Ú
\93®
\8e¸
\94s
\r
430 // WAVE
\82Ìfmt
\83`
\83\83\83\93\83N
\82Ö
\82Ì
\88Ú
\93®
\r
432 ckiChild.ckid = mmioFOURCC('f','m','t',' ');
\r
433 if( ( mmr = mmioDescend( hmmio, &ckiChild, &ckiParent, MMIO_FINDCHUNK ) ) != 0 )
\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
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
443 mmioClose( hmmio, 0 );
\r
444 return FDKERR_SoundType
\82ª
\96³
\8cø; // fmt
\83`
\83\83\83\93\83N
\92E
\8fo
\8e¸
\94s
\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
452 mmioClose( hmmio, 0 );
\r
453 return E_OUTOFMEMORY; //
\83\81\83\82\83\8a\95s
\91«
\r
455 CopyMemory( pwfx, pw, wfxsize );
\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
461 mmioClose( hmmio, 0 );
\r
463 return FDKERR_SoundType
\82ª
\96³
\8cø; // data
\83`
\83\83\83\93\83N
\82Ö
\82Ì
\88Ú
\93®
\8e¸
\94s
\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
471 /*
\82±
\82±
\82Ü
\82Å
\82Å
\81Apwfx, pDestData, dwDestSize
\82É RiffWAV
\82Ì
\93à
\97e
\82ª
\93¾
\82ç
\82ê
\82½
\81B*/
\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
476 WAVEFORMATEX* pSrcWfx = pwfx;
\r
477 BYTE* pSrcData = pDestData;
\r
478 DWORD dwSrcSize = dwDestSize;
\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
485 SAFE_FREE( pSrcWfx );
\r
486 return FDKERR_SoundType
\82ª
\96³
\8cø; // CODEC
\82ª
\82È
\82©
\82Á
\82½
\r
490 // ACM
\82ð
\83I
\81[
\83v
\83\93\82·
\82é
\r
492 if( ( mmr = acmStreamOpen( &hAcm, NULL, pSrcWfx, &wfxDest, NULL, NULL, NULL, ACM_STREAMOPENF_NONREALTIME ) ) != 0 )
\r
494 SAFE_FREE( pSrcWfx );
\r
495 return FDKERR_SoundType
\82ª
\96³
\8cø; // ACM
\82Ì
\83I
\81[
\83v
\83\93\82É
\8e¸
\94s
\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
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
505 if( dwDestSize == 0 )
\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
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
516 acmStreamClose( hAcm, NULL );
\r
517 SAFE_FREE( pSrcWfx );
\r
518 return E_OUTOFMEMORY; //
\83\81\83\82\83\8a\95s
\91«
\r
520 CopyMemory( pwfx, &wfxDest, sizeof(WAVEFORMATEX) );
\r
522 // PCM
\83o
\83b
\83t
\83@
\82Ì
\8am
\95Û
\r
523 pDestData = (LPBYTE) malloc( dwDestSize );
\r
526 acmStreamClose( hAcm, NULL );
\r
527 SAFE_FREE( pSrcWfx );
\r
528 return E_OUTOFMEMORY; //
\83\81\83\82\83\8a\95s
\91«
\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
541 acmStreamUnprepareHeader( hAcm, &acmHeader, NULL );
\r
542 acmStreamClose( hAcm, NULL );
\r
543 SAFE_FREE( pSrcWfx );
\r
545 SAFE_FREE( pDestData );
\r
546 return FDKERR_SoundType
\82ª
\96³
\8cø; // ACM
\83w
\83b
\83_
\93o
\98^
\8e¸
\94s
\r
550 if( ( mmr = acmStreamConvert( hAcm, &acmHeader, NULL ) ) != 0 )
\r
552 acmStreamUnprepareHeader( hAcm, &acmHeader, NULL );
\r
553 acmStreamClose( hAcm, NULL );
\r
554 SAFE_FREE( pSrcWfx );
\r
556 SAFE_FREE( pDestData );
\r
557 return FDKERR_SoundType
\82ª
\96³
\8cø; // ACM
\95Ï
\8a·
\8e¸
\94s
\r
560 //
\90^
\82Ì
\95Ï
\8a·
\8cã
\83T
\83C
\83Y
\82ð
\8eæ
\93¾
\r
561 dwDestSize = acmHeader.cbDstLengthUsed;
\r
563 // ACM
\82ð
\95Â
\82¶
\82é
\r
564 acmStreamUnprepareHeader( hAcm, &acmHeader, NULL );
\r
565 acmStreamClose( hAcm, NULL );
\r
567 //
\8dì
\90¬
\82Æ
\8f\91\82«
\8d\9e\82Ý
\r
569 if( FAILED( hr = CreateAndCopyBuffer( pDS, pwfx, pDestData, dwDestSize ) ) )
\r
572 SAFE_FREE( pSrcWfx );
\r
573 SAFE_FREE( pDestData );
\r
577 SAFE_FREE( pSrcWfx );
\r
578 SAFE_FREE( pDestData );
\r
582 //
\8dì
\90¬
\82Æ
\8f\91\82«
\8d\9e\82Ý
\r
584 if( FAILED( hr = CreateAndCopyBuffer( pDS, pwfx, pDestData, dwDestSize ) ) )
\r
592 m_SoundType = SOUNDTYPE_WAV;
\r
597 HRESULT CSound::DecodeFromOgg( LPDIRECTSOUND8 pDS, BYTE* pSrcData, DWORD dwSrcSize )
\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
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
610 LPBYTE pDestData = (LPBYTE) malloc( szDestDataSize );
\r
614 return E_OUTOFMEMORY; //
\83\81\83\82\83\8a\95s
\91«
\r
617 //
\83f
\83R
\81[
\83h
\r
618 if( ! ogg.ConvertToWav( pDestData, szDestDataSize ) )
\r
621 SAFE_FREE( pDestData );
\r
622 return FDKERR_SoundType
\82ª
\96³
\8cø; //
\95Ï
\8a·
\8e¸
\94s
\r
625 // WAVE
\83t
\83H
\81[
\83}
\83b
\83g
\82Ì
\8eæ
\93¾
\r
627 if( ! ogg.GetFormat( &wfx ) )
\r
630 SAFE_FREE( pDestData );
\r
631 return FDKERR_SoundType
\82ª
\96³
\8cø; //
\8eæ
\93¾
\8e¸
\94s
\r
634 //
\83T
\83E
\83\93\83h
\82Ì
\8dì
\90¬
\82Æ
\8f\91\82«
\8d\9e\82Ý
\r
636 if( FAILED( hr = CreateAndCopyBuffer( pDS, &wfx, pDestData, (DWORD)szDestDataSize ) ) )
\r
639 SAFE_FREE( pDestData );
\r
644 SAFE_FREE( pDestData );
\r
647 m_SoundType = SOUNDTYPE_OGG;
\r
652 void CSound::Play( bool bLoop )
\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
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
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
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
676 //
\8dÄ
\90¶
\83J
\81[
\83\
\83\8b\8f\89\8aú
\89»
\r
678 this->pDSBuffer->SetCurrentPosition( dwStartPos );
\r
679 this->pDSBuffer->GetStatus( &dwStatus );
\r
680 if( dwStatus & DSBSTATUS_PLAYING )
\r
682 this->pDSBuffer->Stop();
\r
683 this->pDSBuffer->SetCurrentPosition( dwStartPos );
\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
695 this->bLoop = bLoop;
\r
699 void CSound::Stop()
\r
701 if( this->pDSBuffer )
\r
703 this->pDSBuffer->Stop();
\r
704 this->pDSBuffer->SetCurrentPosition( 0 );
\r
709 void CSound::Pause()
\r
711 if( this->pDSBuffer && IsPlay() )
\r
713 this->pDSBuffer->GetCurrentPosition( &this->dwCurrentPosition, NULL );
\r
714 this->pDSBuffer->Stop();
\r
719 void CSound::Cont()
\r
721 if( this->nPause == 0 )
\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
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
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
744 //
\8dÄ
\90¶
\8aJ
\8en
\88Ê
\92u
\82Ì
\8c\88\92è
\r
745 DWORD dwStartPos = this->dwCurrentPosition;
\r
747 //
\8dÄ
\90¶
\83J
\81[
\83\
\83\8b\8f\89\8aú
\89»
\r
749 this->pDSBuffer->SetCurrentPosition( dwStartPos );
\r
750 this->pDSBuffer->GetStatus( &dwStatus );
\r
751 if( dwStatus & DSBSTATUS_PLAYING )
\r
753 this->pDSBuffer->Stop();
\r
754 this->pDSBuffer->SetCurrentPosition( dwStartPos );
\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
767 void CSound::Cont( double dbContTime )
\r
769 //
\83J
\81[
\83\
\83\8b\88Ú
\93®(this->dwCurrentPosition
\82à
\88Ú
\93®)
\r
770 SetPosition( GetPositionFromTime( dbContTime ) );
\r
772 // this->dwCurrentPosition
\82©
\82ç
\8dÄ
\8aJ
\r
776 void CSound::SetPosition( DWORD dwNewPosition )
\r
778 if( ! this->pDSBuffer )
\r
781 //
\83u
\83\8d\83b
\83N
\8b«
\8aE
\82É
\82»
\82ë
\82¦
\82é
\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
788 //
\83J
\81[
\83\
\83\8b\82ð
\88Ú
\93®
\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
796 this->dwCurrentPosition = dwNewPosition; //
\88ê
\89\9e\94½
\89f...
\r
800 DWORD CSound::GetPositionFromTime( double dbTime )
\r
802 if( ! this->pDSBuffer )
\r
805 //
\8eü
\94g
\90\94\83X
\83s
\81[
\83h
\82ð
\89Á
\96¡
\r
806 dbTime = dbTime * this->fSpeed * this->fPitch;
\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
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
819 //
\83u
\83\8d\83b
\83N
\8b«
\8aE
\82É
\82»
\82ë
\82¦
\82é
\r
820 dwCurPos -= dwCurPos % pWF->nBlockAlign;
\r
826 void CSound::SetVolume( long lVolume )
\r
829 lVolume = 1; // Vol = 0
\82Í
\82È
\82º
\82©
\89¹
\97Ê100%
\82É
\82È
\82Á
\82Ä
\82µ
\82Ü
\82¤
\82½
\82ß...
\r
831 this->lVolume = (long)(( 20.0 * log10( lVolume / 100.0 ) ) * 100.0);
\r
833 //
\89\89\91t
\92\86\82È
\82ç
\91¦
\94½
\89f
\r
835 this->pDSBuffer->SetVolume( this->lVolume );
\r
838 void CSound::SetPan( long lPan )
\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
846 //
\89\89\91t
\92\86\82È
\82ç
\91¦
\94½
\89f
\r
848 this->pDSBuffer->SetPan( lPan );
\r
851 bool CSound::IsPlay()
\r
853 if( ! this->pDSBuffer )
\r
857 this->pDSBuffer->GetStatus( &dwStatus );
\r
858 return dwStatus & DSBSTATUS_PLAYING;
\r
861 DWORD CSound::GetFrequency()
\r
863 if( ! this->pDSBuffer )
\r
867 this->pDSBuffer->GetFrequency( &dwFreq );
\r
871 DWORD CSound::SetFrequency( DWORD dwFreq )
\r
873 if( ! this->pDSBuffer )
\r
877 this->pDSBuffer->GetFrequency( &dwOldFreq );
\r
878 this->pDSBuffer->SetFrequency( dwFreq );
\r
882 double CSound::GetTotalTime()
\r
884 if( this->pDSBuffer == NULL )
\r
887 // WAVEFORMATEX
\8eæ
\93¾
\r
889 this->pDSBuffer->GetFormat( NULL, 0, &dwSize );
\r
890 LPWAVEFORMATEX pWF = (LPWAVEFORMATEX) malloc( dwSize );
\r
891 this->pDSBuffer->GetFormat( pWF, dwSize, NULL );
\r
893 //
\91\8d\8e\9e\8aÔ
\82Ì
\8cv
\8eZ
\r
894 double dbTotalTime = (double)( this->dwDSBufferSize / ( pWF->nAvgBytesPerSec * 0.001 ) );
\r
897 return dbTotalTime;
\r