00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "Common/Error.h"
00012 #include "Common/Assert.h"
00013
00014 #include "Sound/SoundDS.h"
00015
00016
00017 KSound::KSound( HINSTANCE hInstance, HWND hWnd )
00018 : KThread()
00019 {
00020 m_hInstance = hInstance;
00021 m_hWnd = hWnd;
00022 m_pTrackBank = NULL;
00023 m_pStreamTrackBank = NULL;
00024 m_pDS = NULL;
00025 m_pDSL = NULL;
00026 m_pDSPrimary = NULL;
00027 m_fVolume = 1.0f ;
00028 }
00029
00030
00031 KSound::~KSound()
00032 {
00033 }
00034
00035
00036 bool KSound::Init()
00037 {
00038 HRESULT hr;
00039
00040
00041 if( FAILED( hr = DirectSoundCreate8( NULL, &m_pDS, NULL ) ) )
00042 {
00043 KError::FatalError( m_hWnd, "KSound::Init() : DirectSoundCreate8(..) %s", DXGetErrorString9( hr ) );
00044 return false;
00045 }
00046
00047 if( FAILED( hr = m_pDS->SetCooperativeLevel( m_hWnd, DSSCL_PRIORITY ) ) )
00048 {
00049 KError::FatalError( m_hWnd, "KSound::Init() : SetCooperativeLevel(...) %s", DXGetErrorString9( hr ) );
00050 return false;
00051 }
00052
00053 DSBUFFERDESC dsbd;
00054 LPDIRECTSOUND3DLISTENER8 lp3DListener = NULL;
00055
00056 ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
00057 dsbd.dwSize = sizeof(DSBUFFERDESC);
00058 dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME;
00059
00060 if( SUCCEEDED( hr = m_pDS->CreateSoundBuffer( &dsbd, &m_pDSPrimary, NULL ) ) )
00061 {
00062 hr = m_pDSPrimary->QueryInterface( IID_IDirectSound3DListener8, (LPVOID*)&m_pDSL );
00063 }
00064
00065 m_pTrackBank = new KTrackBank( this );
00066 m_pStreamTrackBank = new KStreamTrackBank( this );
00067
00068
00069
00070 StartThread();
00071
00072
00073
00074 return true;
00075 }
00076
00077
00078 bool KSound::End()
00079 {
00080 StopThread();
00081
00082 SafeDeletep( m_pTrackBank );
00083 SafeRelease( m_pDSL );
00084 SafeRelease( m_pDSPrimary );
00085 SafeRelease( m_pDS );
00086
00087 return true;
00088 }
00089
00090
00091 bool KSound::Play( KTRACK TrackId, bool bLooping )
00092 {
00093 if( TrackId == KTRACK_NO )
00094 return false;
00095 KASSERT( m_pTrackBank );
00096
00097 KTrack* pTrack = m_pTrackBank->GetTrack( TrackId );
00098
00099 if( pTrack )
00100 {
00101
00102 if( pTrack->IsPlaying() )
00103 {
00104 pTrack->Stop();
00105 pTrack->SetPlayPos( 0 );
00106 }
00107
00108
00109 pTrack->Play( bLooping );
00110 }
00111
00112 return true;
00113 }
00114
00115
00116 bool KSound::Stop( KTRACK TrackId )
00117 {
00118 KASSERT( m_pTrackBank );
00119
00120 KTrack* pTrack = m_pTrackBank->GetTrack( TrackId );
00121
00122 if( pTrack )
00123 pTrack->Stop();
00124
00125 return true;
00126 }
00127
00128
00129 KTRACK KSound::LoadTrack( KStr& sFileName, KSTRACKTYPE TrackType )
00130 {
00131 KASSERT( m_pTrackBank );
00132 return m_pTrackBank->LoadTrack( sFileName, TrackType );
00133 }
00134
00135
00136 bool KSound::UnloadTrack( KTRACK& Track )
00137 {
00138 return m_pTrackBank->UnloadTrack( Track );
00139 }
00140
00141
00142 void KSound::SetPosition( KTRACK TrackId, KVector& Position )
00143 {
00144 KASSERT( m_pTrackBank );
00145
00146 KTrack* pTrack = m_pTrackBank->GetTrack( TrackId );
00147
00148 if( pTrack )
00149 pTrack->SetPosition( Position );
00150 }
00151
00152
00153 void KSound::SetDistance( KTRACK TrackId, float Min, float Max )
00154 {
00155 KASSERT( m_pTrackBank );
00156
00157 KTrack* pTrack = m_pTrackBank->GetTrack( TrackId );
00158
00159 if( pTrack )
00160 pTrack->SetDistance( Min, Max );
00161 }
00162
00163
00164 void KSound::SetPosition( KVector& Position )
00165 {
00166 KASSERT( m_pDSL );
00167
00168 m_pDSL->SetPosition( Position.x, Position.z, Position.y, DS3D_DEFERRED );
00169 }
00170
00171
00172 void KSound::SetOrientation( KVector& Front, KVector& Top )
00173 {
00174 KASSERT( m_pDSL );
00175
00176 m_pDSL->SetOrientation( Front.x, Front.z, Front.y, Top.x, Top.z, Top.y, DS3D_DEFERRED );
00177 }
00178
00179
00180 void KSound::Manage3DSound( KVector& Position, KVector& Front, KVector& Top )
00181 {
00182 KASSERT( m_pDSL );
00183
00184 m_pDSL->CommitDeferredSettings();
00185 SetPosition( Position );
00186 SetOrientation( Front, Top );
00187 }
00188
00189
00190 void KSound::SetVolume( float Volume )
00191 {
00192 if( Volume < 0.0f )
00193 Volume = 0.0f;
00194
00195 if( Volume > 1.0f )
00196 Volume = 1.0f;
00197
00198 m_fVolume = Volume ;
00199
00200 LONG lVolume = (LONG)( Volume * (float)(DSBVOLUME_MAX - KDSBVOLUME_MIN)) + KDSBVOLUME_MIN;
00201
00202 m_pDSPrimary->SetVolume( lVolume );
00203 }
00204
00205
00206
00207
00208
00209 KSTREAMTRACK KSound::LoadStreamTrack( KStr& sFileName )
00210 {
00211 KSTREAMTRACK Track;
00212
00213
00214 m_StreamTrackBankMutex.Lock();
00215
00216 KASSERT( m_pStreamTrackBank );
00217
00218 Track = m_pStreamTrackBank->LoadTrack( sFileName );
00219
00220
00221 m_StreamTrackBankMutex.Unlock();
00222
00223 return Track;
00224 }
00225
00226
00227 bool KSound::UnloadStreamTrack( KSTREAMTRACK& Track )
00228 {
00229 bool Result;
00230
00231
00232 m_StreamTrackBankMutex.Lock();
00233
00234 KASSERT( m_pStreamTrackBank );
00235
00236 Result = m_pStreamTrackBank->UnloadTrack( Track );
00237
00238
00239 m_StreamTrackBankMutex.Unlock();
00240
00241 return Result;
00242 }
00243
00244
00245 bool KSound::PlayStreamTrack( KSTREAMTRACK TrackId, bool bFadeIn, KTIME FadeTime )
00246 {
00247 if( TrackId == KSTREAMTRACK_NO )
00248 return false;
00249
00250
00251 m_StreamTrackBankMutex.Lock();
00252
00253 KASSERT( m_pStreamTrackBank );
00254
00255 KStreamTrack* pTrack = m_pStreamTrackBank->GetTrack( TrackId );
00256
00257 if( pTrack )
00258 {
00259
00260 if( pTrack->IsPlaying() )
00261 {
00262 pTrack->Stop();
00263 pTrack->SetPlayPos( 0 );
00264 }
00265
00266
00267 pTrack->Play( bFadeIn, FadeTime );
00268 }
00269
00270
00271 m_StreamTrackBankMutex.Unlock();
00272
00273 return true;
00274 }
00275
00276
00277 bool KSound::StopStreamTrack( KTRACK TrackId, bool bFadeIn, KTIME FadeTime )
00278 {
00279
00280 m_StreamTrackBankMutex.Lock();
00281
00282 KASSERT( m_pStreamTrackBank );
00283
00284 KStreamTrack* pTrack = m_pStreamTrackBank->GetTrack( TrackId );
00285
00286 if( pTrack )
00287 pTrack->Stop( bFadeIn, FadeTime );
00288
00289
00290 m_StreamTrackBankMutex.Unlock();
00291
00292 return true;
00293 }
00294
00295
00296 bool KSound::ProcessStreamTrack()
00297 {
00298
00299 m_StreamTrackBankMutex.Lock();
00300
00301 KASSERT( m_pStreamTrackBank );
00302
00303
00304
00305
00306 KSTREAMTRACK TrackId;
00307 for( TrackId = 0; TrackId < m_pStreamTrackBank->GetnTracks(); TrackId ++ )
00308 {
00309
00310 KStreamTrack* pTrack = m_pStreamTrackBank->GetTrack( TrackId );
00311 if( !pTrack )
00312 continue;
00313
00314 bool bStop1 = ( WaitForSingleObject( pTrack->GethStopEvent1(), 0 ) == WAIT_OBJECT_0 ) ? true : false;
00315 bool bStop2 = ( WaitForSingleObject( pTrack->GethStopEvent2(), 0 ) == WAIT_OBJECT_0 ) ? true : false;
00316
00317 if( bStop1 )
00318 {
00319
00320 pTrack->CopyNextBlock( 0 );
00321
00322 }
00323
00324 if( bStop2 )
00325 {
00326
00327 pTrack->CopyNextBlock( 1 );
00328
00329 }
00330
00331
00332 pTrack->Manage();
00333 }
00334
00335
00336 m_StreamTrackBankMutex.Unlock();
00337
00338 return true;
00339 }
00340
00341
00342 u32 KSound::ThreadProc()
00343 {
00344 while( IsThreadRunning() )
00345 {
00346
00347 ProcessStreamTrack();
00348 Sleep( 10 );
00349 }
00350
00351 return 0;
00352 }
00353
00354
00355 KStreamTrackBank* KSound::LockStreamTrackBank()
00356 {
00357 m_StreamTrackBankMutex.Lock();
00358
00359 return m_pStreamTrackBank;
00360 }
00361
00362
00363 void KSound::UnlockStreamTrackBank( KStreamTrackBank** pStreamTrackBank )
00364 {
00365 KASSERT( *pStreamTrackBank == m_pStreamTrackBank );
00366
00367 *pStreamTrackBank = NULL;
00368
00369 m_StreamTrackBankMutex.Unlock();
00370 }