00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "Common/Console.h"
00012 #include "Common/Error.h"
00013 #include "Common/Assert.h"
00014 #include "Common/Directory.h"
00015 #include "Wave/Wav.h"
00016 #include "Wave/Ogg.h"
00017 #include "Sound/SoundDS.h"
00018
00019 #include "Sound/StreamTrackDS.h"
00020
00021
00022 KStreamTrack::KStreamTrack()
00023 {
00024 m_pWaveFile = NULL;
00025 m_pDSBuffer = NULL;
00026 m_pDSNotify = NULL;
00027 m_hStopEvent1 = NULL;
00028 m_hStopEvent2 = NULL;
00029 m_Fade = KSTF_NONE;
00030 m_StartFade = 0;
00031 m_EndFade = 0;
00032 }
00033
00034
00035 KStreamTrack::~KStreamTrack()
00036 {
00037 }
00038
00039
00040 bool KStreamTrack::LoadTrack( KStreamTrackBank* pStreamTrackBank, KStr& sFileName )
00041 {
00042 KASSERT( !m_pWaveFile );
00043 KASSERT( !m_pDSBuffer );
00044 KASSERT( !m_pDSNotify );
00045 KASSERT( pStreamTrackBank );
00046
00047 IDirectSound8* pDS = pStreamTrackBank->GetSound()->GetDirectSound();
00048 HRESULT hr;
00049
00050
00051 char* pExtension = KFile::GetFileExtension( sFileName );
00052 if( !pExtension )
00053 return false;
00054
00055 if( !stricmp( pExtension, "wav" ) )
00056 {
00057
00058 m_pWaveFile = new KWav();
00059 }
00060 else if( !stricmp( pExtension, "ogg" ) )
00061 {
00062
00063 m_pWaveFile = new KOgg();
00064 }
00065 else
00066 return false;
00067
00068
00069 if( !m_pWaveFile->OpenWave( sFileName ) )
00070 {
00071 Deletep( m_pWaveFile );
00072 return false;
00073 }
00074
00075
00076 DSBUFFERDESC dsdd;
00077
00078 memset( &dsdd, 0, sizeof( dsdd ) );
00079 dsdd.dwSize = sizeof( dsdd );
00080 dsdd.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCSOFTWARE;
00081 dsdd.dwBufferBytes = m_pWaveFile->GetMaxBlockSize() * 2;
00082 dsdd.lpwfxFormat = m_pWaveFile->GetWaveFormat();
00083
00084 IDirectSoundBuffer* pDSB;
00085 if( FAILED( hr = pDS->CreateSoundBuffer( &dsdd, &pDSB, NULL ) ) )
00086 {
00087 KError::FatalError( NULL, "KStreamTrack::LoadTrack(...) %s.", DXGetErrorString9( hr ) );
00088 return false;
00089 }
00090
00091 if( FAILED( hr = pDSB->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*)&m_pDSBuffer ) ) )
00092 {
00093 KError::FatalError( NULL, "KStreamTrack::LoadTrack(...) %s.", DXGetErrorString9( hr ) );
00094 return false;
00095 }
00096
00097 pDSB->Release();
00098
00099
00100 if( FAILED( hr = m_pDSBuffer->QueryInterface( IID_IDirectSoundNotify8, (LPVOID*)&m_pDSNotify ) ) )
00101 {
00102 KError::FatalError( NULL, "KStreamTrack::LoadTrack(...) %s.", DXGetErrorString9( hr ) );
00103 return false;
00104 }
00105
00106
00107 CopyNextBlock( 0 );
00108 CopyNextBlock( 1 );
00109
00110
00111 m_hStopEvent1 = CreateEvent( NULL, FALSE, FALSE, NULL );
00112 if( !m_hStopEvent1 )
00113 return false;
00114
00115 m_hStopEvent2 = CreateEvent( NULL, FALSE, FALSE, NULL );
00116 if( !m_hStopEvent2 )
00117 return false;
00118
00119 DSBPOSITIONNOTIFY dspn[2];
00120
00121 dspn[0].dwOffset = m_pWaveFile->GetMaxBlockSize() - 1;
00122 dspn[0].hEventNotify = m_hStopEvent1;
00123 dspn[1].dwOffset = m_pWaveFile->GetMaxBlockSize() * 2 - 1;
00124 dspn[1].hEventNotify = m_hStopEvent2;
00125 m_pDSNotify->SetNotificationPositions( 2, dspn );
00126 m_pDSNotify->Release();
00127 m_pDSNotify = NULL;
00128
00129 m_sFileName = sFileName;
00130
00131 return true;
00132 }
00133
00134
00135 bool KStreamTrack::UnloadTrack()
00136 {
00137 if( m_hStopEvent1 )
00138 {
00139 CloseHandle( m_hStopEvent1 );
00140 m_hStopEvent1 = NULL;
00141 }
00142
00143 if( m_hStopEvent2 )
00144 {
00145 CloseHandle( m_hStopEvent2 );
00146 m_hStopEvent2 = NULL;
00147 }
00148
00149 if( m_pWaveFile )
00150 {
00151 m_pWaveFile->CloseWave();
00152 SafeDeletep( m_pWaveFile );
00153 }
00154
00155 SafeRelease( m_pDSBuffer );
00156 SafeRelease( m_pDSNotify );
00157
00158 return true;
00159 }
00160
00161
00162 bool KStreamTrack::Lock( void** pData, u32* Size, u32 StartOffset, u32 SizeToLock )
00163 {
00164 HRESULT hr;
00165
00166 if( FAILED( hr = m_pDSBuffer->Lock( StartOffset, SizeToLock, pData, Size, NULL, NULL, SizeToLock ? 0 : DSBLOCK_ENTIREBUFFER ) ) )
00167 {
00168 KError::Error( NULL, "KStreamTrack::Lock(...) %s.", DXGetErrorString9( hr ) );
00169 return false;
00170 }
00171
00172 return true;
00173 }
00174
00175
00176 bool KStreamTrack::Unlock( void* pData, u32 Size )
00177 {
00178 HRESULT hr;
00179
00180 if( FAILED( hr = m_pDSBuffer->Unlock( pData, Size, NULL, NULL ) ) )
00181 {
00182 KError::Error( NULL, "KStreamTrack::Unlock(...) %s.", DXGetErrorString9( hr ) );
00183 return false;
00184 }
00185
00186 return true;
00187 }
00188
00189
00190 bool KStreamTrack::Play( bool bFadeIn, KTIME FadeTime )
00191 {
00192 KASSERT( m_pDSBuffer );
00193
00194 HRESULT hr;
00195
00196 if( bFadeIn )
00197 {
00198 m_Fade = KSTF_IN;
00199 m_StartFade = g_Time.GetTime();
00200 m_EndFade = m_StartFade + FadeTime;
00201 }
00202 else
00203 {
00204 m_Fade = KSTF_NONE;
00205 m_pDSBuffer->SetVolume( DSBVOLUME_MAX );
00206 }
00207
00208 if( FAILED( hr = m_pDSBuffer->Play( 0, 0, true ) ) )
00209 {
00210 KError::Error( NULL, "KStreamTrack::Play(...) %s.", DXGetErrorString9( hr ) );
00211 return false;
00212 }
00213
00214 return true;
00215 }
00216
00217
00218 bool KStreamTrack::Stop( bool bFadeOut, KTIME FadeTime )
00219 {
00220 HRESULT hr;
00221
00222 if( bFadeOut )
00223 {
00224 m_Fade = KSTF_OUT;
00225 m_StartFade = g_Time.GetTime();
00226 m_EndFade = m_StartFade + FadeTime;
00227 }
00228 else
00229 {
00230 m_Fade = KSTF_NONE;
00231 m_pDSBuffer->SetVolume( DSBVOLUME_MAX );
00232
00233 if( FAILED( hr = m_pDSBuffer->Stop() ) )
00234 {
00235 KError::Error( NULL, "KStreamTrack::Stop(...) %s.", DXGetErrorString9( hr ) );
00236 return false;
00237 }
00238 }
00239
00240 return true;
00241 }
00242
00243
00244
00245 void KStreamTrack::SetPlayPos( u32 Position )
00246 {
00247 KASSERT( m_pDSBuffer );
00248
00249 m_pDSBuffer->SetCurrentPosition( Position );
00250 }
00251
00252
00253 bool KStreamTrack::IsPlaying()
00254 {
00255 KASSERT( m_pDSBuffer );
00256
00257 DWORD Status;
00258
00259 m_pDSBuffer->GetStatus( &Status );
00260
00261 if( Status & DSBSTATUS_PLAYING )
00262 return true;
00263
00264 return false;
00265 }
00266
00267
00268 bool KStreamTrack::CopyNextBlock( u32 BufferId )
00269 {
00270 u32 SizeRead;
00271 u32 StartOffset;
00272
00273 StartOffset = BufferId * m_pWaveFile->GetMaxBlockSize();
00274
00275
00276 if( !m_pWaveFile->ReadNextBlock( &SizeRead ) )
00277 {
00278 return false;
00279
00280
00281
00282
00283 }
00284
00285
00286 if( m_pWaveFile->IsEnd() )
00287 {
00288
00289 m_pWaveFile->Rewind();
00290
00291 }
00292
00293 KASSERT( SizeRead <= m_pWaveFile->GetMaxBlockSize() );
00294
00295
00296 if( SizeRead < m_pWaveFile->GetMaxBlockSize() )
00297 {
00298 for( u32 i = SizeRead; i < m_pWaveFile->GetMaxBlockSize(); i ++ )
00299 {
00300 m_pWaveFile->GetBlock()[i] = 0;
00301 }
00302 SizeRead = m_pWaveFile->GetMaxBlockSize();
00303 }
00304
00305 if( SizeRead == 0 )
00306 return false;
00307
00308
00309 u8* pBuffer = NULL;
00310 u32 Size = 0;
00311
00312 Lock( (void**)&pBuffer, &Size, StartOffset, SizeRead );
00313 KASSERT( Size == SizeRead );
00314 memcpy( pBuffer, m_pWaveFile->GetBlock(), Size );
00315 Unlock( (void*)pBuffer, Size );
00316
00317 return true;
00318 }
00319
00320
00321 bool KStreamTrack::Manage()
00322 {
00323 KTIME Time = g_Time.GetTime();
00324 float delta = (float)( Time - m_StartFade ) / (float)( m_EndFade - m_StartFade );
00325
00326 switch( m_Fade )
00327 {
00328 case KSTF_NONE:
00329 break;
00330 case KSTF_IN:
00331 {
00332 if( delta > 1.0f )
00333 {
00334 delta = 1.0f;
00335 m_Fade = KSTF_NONE;
00336 }
00337
00338 LONG Volume = (LONG)( delta * (float)(DSBVOLUME_MAX - KDSBVOLUME_MIN)) + KDSBVOLUME_MIN;
00339 m_pDSBuffer->SetVolume( Volume );
00340
00341 }
00342 break;
00343 case KSTF_OUT:
00344 {
00345 if( delta > 1.0f )
00346 {
00347 delta = 1.0f;
00348 m_Fade = KSTF_NONE;
00349
00350 HRESULT hr;
00351 if( FAILED( hr = m_pDSBuffer->Stop() ) )
00352 {
00353 KError::Error( NULL, "KStreamTrack::Manage(...) Stop failed\n%s.", DXGetErrorString9( hr ) );
00354 return false;
00355 }
00356 }
00357
00358 LONG Volume = (LONG)( (1.0f - delta) * (float)(DSBVOLUME_MAX - KDSBVOLUME_MIN)) + KDSBVOLUME_MIN;
00359 m_pDSBuffer->SetVolume( Volume );
00360
00361 }
00362 break;
00363 }
00364
00365 return true;
00366 }
00367
00368
00369
00370
00371 KStreamTrackBank::KStreamTrackBank( KSound* pSound )
00372 {
00373 m_pSound = pSound;
00374 m_nTracks = 0;
00375 }
00376
00377
00378 KStreamTrackBank::~KStreamTrackBank()
00379 {
00380 for(u32 i = 0;i < m_nTracks;i ++)
00381 Deletep( m_pTrack[i] );
00382
00383 m_pTrack.Clear();
00384 }
00385
00386
00387 KStreamTrack* KStreamTrackBank::GetTrack( KSTREAMTRACK TrackId )
00388 {
00389 KASSERT( TrackId < m_nTracks );
00390
00391
00392 return m_pTrack[TrackId];
00393 }
00394
00395
00396 KSTREAMTRACK KStreamTrackBank::LoadTrack( KStr& sFileName )
00397 {
00398 KStr sFullFileName;
00399
00400 for( s32 Path = 0; Path < g_Directory.GetnPath(); Path ++ )
00401 {
00402 sFullFileName = g_Directory.GetPath( KStr( "Sounds" ), Path );
00403 sFullFileName += sFileName;
00404
00405 KStreamTrack* pTrack = NULL;
00406 KSTREAMTRACK TrackId = 0;
00407
00408 pTrack = new KStreamTrack();
00409 if( !pTrack->LoadTrack( this, sFullFileName ) )
00410 {
00411 Deletep( pTrack );
00412 continue;
00413 }
00414
00415 TrackId = m_pTrack.Add( pTrack );
00416 m_nTracks ++;
00417
00418 g_Console << "Sound loaded : " << sFileName.GetpString() << KENDL;
00419
00420 return TrackId;
00421 }
00422
00423 KError::Error( NULL, "KStreamTrackBank::LoadTrack(...) Cannot load sound %s.", sFileName.GetpString() );
00424
00425 return KSTREAMTRACK_NO;
00426 }
00427
00428
00429 bool KStreamTrackBank::UnloadTrack( KSTREAMTRACK& Track )
00430 {
00431 if( Track < 0 )
00432 return false;
00433
00434 if( Track >= m_pTrack.GetSize() )
00435 {
00436 KError::Error( NULL, "KStreamTrackBank::UnloadTrack() : Invalid TrackId : %i", Track );
00437 return false;
00438 }
00439
00440 m_pTrack[Track]->UnloadTrack();
00441 SafeDeletep( m_pTrack[Track] );
00442
00443 Track = KSTREAMTRACK_NO;
00444
00445 return true;
00446 }