OpenBarnyard
 
Loading...
Searching...
No Matches
ASoundManager.cpp
Go to the documentation of this file.
1#include "pch.h"
2#include "ASoundManager.h"
3#include "ASoundLegacy.h"
4#include "ASound.h"
6#include "Tasks/ARootTask.h"
8#include "Memory/AMemory.h"
9#include "AWaveBankFMODFSB.h"
11#include "ALoadScreen.h"
12#include "ARandom.h"
13
15
16#include <fmod/fmod.h>
17
18//-----------------------------------------------------------------------------
19// Enables memory debugging.
20// Note: Should be the last include!
21//-----------------------------------------------------------------------------
22#include <Core/TMemoryDebugOn.h>
23
25
27
28#define MAX_NUM_SOUND_EVENTS 256
29#define MAX_NUM_STREAMS 64
30
32 : m_SoundEventPool( AMemory::GetAllocator( AMemory::POOL_Sound ), MAX_NUM_SOUND_EVENTS ), m_StreamRefPool( AMemory::GetAllocator( AMemory::POOL_Sound ), MAX_NUM_STREAMS ), m_ChannelRefPool( AMemory::GetAllocator( AMemory::POOL_Sound ), MAX_NUM_SOUND_EVENTS ), m_ChannelRefLegacyPool( AMemory::GetAllocator( AMemory::POOL_Sound ), MAX_NUM_SOUND_EVENTS ), m_CategoryIndices( AMemory::GetAllocator( AMemory::POOL_Sound ) ), m_SoundIdToSound( AMemory::GetAllocator( AMemory::POOL_Sound ) ), m_SoundIdToSoundLegacy( AMemory::GetAllocator( AMemory::POOL_Sound ) )
33{
34 TIMPLEMENT();
35 m_iLastAvailableSoundExSlot = -1;
36 m_fCurrentTime = 0.0f;
37
38 m_bMuted = TFALSE;
39 m_bUseMinHardwareChannels = TTRUE;
40 m_iMinHWChannels = 32;
41 m_iNumChannels = 32;
42 m_iGlobalFrequency = 22050;
43
44 ms_pFileSystem = TFileManager::GetSingleton()->FindFileSystem( "local" );
45
46 // Set event handlers
47 m_oEventManager.SetEventHandler( SOUNDEVENT_PlayAudio, &ASoundManager::EventHandler_PlaySound );
48 m_oEventManager.SetEventHandler( SOUNDEVENT_PlayStream, &ASoundManager::EventHandler_PlayStream );
49 m_oEventManager.SetEventHandler( SOUNDEVENT_StopAudio, &ASoundManager::EventHandler_StopAudio );
50}
51
53{
54 TIMPLEMENT();
55
56 m_FreeListS2.Clear();
57
58 FSOUND_Close();
59 m_PauseListener.Disconnect();
60 Reset();
61}
62
64{
65 TIMPLEMENT();
66 return TTRUE;
67}
68
70{
71 Initialise();
72 m_PauseListener.Connect(
73 g_oSystemManager.GetPauseEmitter(),
74 this,
75 []( ASoundManager* a_pSndMngr, TSystemManager* a_pSysMngr, TBOOL* a_pPaused ) {
76 a_pSndMngr->PauseAllCues( *a_pPaused );
77 return TTRUE;
78 },
79 0
80 );
81
82 m_pS4 = new ( AMemory::GetMemBlock( AMemory::POOL_Sound ) ) S4[ 32 ];
83
84 for ( TINT i = 0; i < 32; i++ )
85 {
86 m_FreeListS4.PushBack( &m_pS4[ i ] );
87 }
88
89 for ( TINT i = 0; i < TARRAYSIZE( m_aS2 ); i++ )
90 {
91 m_FreeListS2.PushBack( &m_aS2[ i ] );
92 }
93
94 return TTRUE;
95}
96
98{
99 TIMPLEMENT();
100 m_fCurrentTime += a_fDeltaTime;
101
102 if ( !g_oSystemManager.IsPaused() )
103 {
104 if ( ARootTask::GetSingleton()->IsPaused() && ms_iNumPauses <= 0 )
105 {
107 }
108 else if ( !ARootTask::GetSingleton()->IsPaused() && ms_iNumPauses > 0 )
109 {
111 }
112 }
113
114 TTODO( "FUN_005db310" );
115
116 // Run the event loop
117 while ( !m_QueuedSortedEventLists.IsEmpty() )
118 {
119 SoundEventList& eventList = *m_QueuedSortedEventLists.Front();
120 ASoundManager::SoundEvent* pEarliestEvent = eventList->Front();
121
122 // Skip the list if it's too early to execute it's earliest event
123 if ( pEarliestEvent->fStartTime > m_fCurrentTime )
124 break;
125
126 // Handle events in the list
127 while ( TTRUE )
128 {
129 pEarliestEvent->Remove();
130 m_oEventManager.ExecuteEvent( pEarliestEvent->eEventType, this, pEarliestEvent );
131
132 // Deallocate the event object
133 m_SoundEventPool.DeleteObject( pEarliestEvent );
134
135 if ( !eventList.IsLinked() )
136 break;
137
138 // Check if the list is over
139 if ( eventList->IsEmpty() )
140 {
141 // Unlink the list since it's not used anymore
142 eventList.Remove();
143 break;
144 }
145
146 // Certainly, there are some more events
147 // Let's check if they need to be processed
148 pEarliestEvent = eventList->Front();
149
150 if ( pEarliestEvent->fStartTime > m_fCurrentTime )
151 {
152 // Seems that the other events in the list are not to be executed yet,
153 // so let's reinsert the list to preserve correct order and move on to
154 // the next list.
155
156 m_QueuedSortedEventLists.ReInsert( eventList );
157 break;
158 }
159 }
160 }
161
162 // Update streams
163 for ( auto pStream = m_StreamRefs.Begin(); pStream != m_StreamRefs.End(); )
164 {
165 if ( ( pStream->pUnknown && UpdateStreamActivity( pStream ) ) ||
166 ( pStream->pCue && UpdateStreamCue( pStream ) ) )
167 {
168 auto itNext = m_StreamRefs.Erase( pStream );
169 m_StreamRefPool.DeleteObject( pStream );
170
171 pStream = itNext;
172 }
173 else
174 {
175 pStream = pStream.Next();
176 }
177 }
178
179 // Reset cues that has finished playing
180 for ( TINT i = 0; i < ASOUNDMANAGER_MAX_NUM_CUE; i++ )
181 {
182 TFLOAT fCueStartTime = m_aCues[ i ].fStartTime;
183
184 if ( fCueStartTime > 0.0f && !IsCuePlaying( i ) )
185 {
186 m_aCues[ i ].Reset();
187 }
188 }
189
190 // ...
191
192 // Update sound attributes based on the current camera position
193 // TODO: replace TTRUE with some flag from the AQuestManager
194 if ( ARootTask::GetSingleton()->IsGameSystemCreated() && TTRUE )
195 {
196 ACamera* pCamera = ACameraManager::GetSingleton()->GetCurrentCamera();
197
198 // Get the position
199 m_oCameraData.Position = pCamera->GetMatrix().AsBasisVector4( BASISVECTOR_TRANSLATION );
200
201 // Get the forward vector
202 m_oCameraData.Forward = pCamera->GetMatrix().AsBasisVector4( BASISVECTOR_FORWARD );
203 m_oCameraData.Forward.w = 1.0f;
204
205 // Get the up vector
206 m_oCameraData.Up = pCamera->GetMatrix().AsBasisVector4( BASISVECTOR_UP );
207 m_oCameraData.Up.w = 1.0f;
208
209 // Invert up axis as it needs to be
210 m_oCameraData.Up.x = -m_oCameraData.Up.x;
211 m_oCameraData.Up.y = -m_oCameraData.Up.y;
212 m_oCameraData.Up.z = -m_oCameraData.Up.z;
213
214 TFLOAT aPosition[ 3 ];
215 aPosition[ 0 ] = m_oCameraData.Position.x;
216 aPosition[ 1 ] = m_oCameraData.Position.y;
217 aPosition[ 2 ] = m_oCameraData.Position.z;
218
219 TFLOAT aVelocity[ 3 ];
220 aVelocity[ 0 ] = m_oCameraData.Velocity.x;
221 aVelocity[ 1 ] = m_oCameraData.Velocity.y;
222 aVelocity[ 2 ] = m_oCameraData.Velocity.z;
223
224 FSOUND_3D_Listener_SetAttributes( aPosition, aVelocity, m_oCameraData.Forward.x, m_oCameraData.Forward.y, -m_oCameraData.Forward.z, m_oCameraData.Up.x, m_oCameraData.Up.y, -m_oCameraData.Up.z );
225 }
226
227 FSOUND_Update();
228 return TTRUE;
229}
230
232{
233 m_UnkList1.Clear();
234 m_FreeListS4.Clear();
235 delete[] m_pS4;
236 m_pS4 = TNULL;
237 m_PauseListener.Disconnect();
238}
239
241{
242 return PlayCueEx( a_iSound, 1.0f, TFALSE, 0.0f, -1 );
243}
244
245TINT ASoundManager::PlayCueEx( ASoundId a_iSound, TFLOAT a_fVolume, TBOOL a_bFlag, TFLOAT a_fDelay, TINT a_iTrack )
246{
247 if ( a_iSound == ASOUNDID_INVALID )
248 return -1;
249
250 // Look if the sound is stored to be played
251 auto pFoundNode = m_SoundIdToSound.Find( a_iSound );
252
253 if ( !m_SoundIdToSound.IsValid( pFoundNode ) )
254 return -1;
255
256 // The sound is found, can use it
257 ASound* pSound = pFoundNode->GetSecond();
258
259 // Check if no waves are stored in the sound
260 if ( pSound->m_vecSamples.Size() == 0 )
261 return -1;
262
263 TINT iCueIndex = GetAvailableCueIndex();
264
265 // Check if we can use some cue to play the sound
266 if ( iCueIndex == -1 )
267 return -1;
268
269 Cue* pCue = &m_aCues[ iCueIndex ];
270 pCue->fStartTime = m_fCurrentTime;
271
272 // Add this cue to a category
273 m_aCategories[ pSound->m_uiCategoryIndex ].PlayingCues.PushBack( pCue );
274
275 TINT iFlags = pSound->m_iFlags;
276
277 if ( a_bFlag )
278 {
279 iFlags |= 1;
280 pCue->fStartTime2 = m_fCurrentTime;
281 }
282
283 // Setup basic settings on the cue
284 pCue->fVolume = ( a_fVolume > 1.0f ) ? 1.0f : a_fVolume;
285 pCue->pSound = pSound;
286 pCue->fFrequency = 1.0f;
287 pCue->vecLoopStarts.Copy( pSound->m_vecLoopStarts );
288
289 TINT iSoundNumTracks = pSound->m_vecTracks.Size();
290
291 if ( a_iTrack == -1 )
292 {
293 // Play all the tracks of this sound
294
295 if ( iSoundNumTracks > 0 )
296 {
297 TINT iFirstWaveIndex = 0;
298
299 for ( TINT iTrack = 0; iTrack < iSoundNumTracks; iTrack++ )
300 {
301 if ( pSound->m_TrackLoop.GetBit( iTrack ) != 0 )
302 iFlags |= 2;
303 else
304 iFlags &= ~2;
305
306 CreatePlaySoundEvent(
307 pCue,
308 iTrack,
309 iFirstWaveIndex,
310 pSound->m_vecTracks[ iTrack ] + iFirstWaveIndex,
311 iFlags,
312 a_fDelay,
313 -1.0f
314 );
315
316 iFirstWaveIndex += pSound->m_vecTracks[ iTrack ];
317 }
318 }
319 }
320 else
321 {
322 // Play only the specified track
323
324 TINT iFirstWaveIndex = pSound->GetFirstWaveForTrack( a_iTrack );
325
326 if ( pSound->m_TrackLoop.GetBit( a_iTrack ) != 0 )
327 iFlags |= 2;
328 else
329 iFlags &= ~2;
330
331 CreatePlaySoundEvent(
332 pCue,
333 a_iTrack,
334 iFirstWaveIndex,
335 pSound->m_vecTracks[ a_iTrack ] + iFirstWaveIndex,
336 iFlags,
337 a_fDelay,
338 -1.0f
339 );
340 }
341
342 pCue->bUsed = TTRUE;
343
344 return iCueIndex;
345}
346
347void ASoundManager::StopCue( TINT& a_rCueIndex )
348{
349 StopCueAsync( a_rCueIndex, 0.0f );
350}
351
353{
354 TINT iSlot;
355
356 for ( iSlot = m_iLastAvailableSoundExSlot + 1;; iSlot++ )
357 {
358 if ( iSlot == 128 )
359 iSlot = 0;
360
361 if ( iSlot == m_iLastAvailableSoundExSlot )
362 return -1;
363
364 if ( m_aCues[ iSlot ].fStartTime <= 0.0 )
365 {
366 if ( iSlot == -1 )
367 return iSlot;
368
369 if ( !m_aCues[ iSlot ].bUsed )
370 break;
371 }
372 }
373
374 m_iLastAvailableSoundExSlot = iSlot;
375 return iSlot;
376}
377
379{
380 TASSERT( a_iCueIndex < ASOUNDMANAGER_MAX_NUM_CUE );
381
382 if ( a_iCueIndex == -1 )
383 return TFALSE;
384
385 Cue* pCue = &m_aCues[ a_iCueIndex ];
386
387 if ( pCue->fStartTime2 > 0.0f || !pCue->oEventList->IsEmpty() )
388 return TTRUE;
389
390 if ( pCue->IsUsed() && pCue->pSound != TNULL )
391 {
392 ASound* pSound = pCue->pSound;
393
394 if ( pSound->m_iFlags & 16 )
395 {
396 // Stream
397 T2_FOREACH( pCue->oChannelRefs, channel )
398 {
399 if ( !( channel->iFlags & 0x20 ) || FSOUND_IsPlaying( channel->iFMODChannelHandle ) )
400 {
401 return TTRUE;
402 }
403 }
404 }
405 else
406 {
407 // Loaded data
408 T2_FOREACH( pCue->oChannelRefs, channel )
409 {
410 if ( FSOUND_IsPlaying( channel->iFMODChannelHandle ) )
411 {
412 return TTRUE;
413 }
414 }
415 }
416 }
417
418 return TFALSE;
419}
420
421void ASoundManager::StopCueAsync( TINT& a_rCueIndex, TFLOAT a_fDelay )
422{
423 if ( a_rCueIndex == -1 )
424 return;
425
426 TASSERT( a_rCueIndex >= 0 && a_rCueIndex < ASOUNDMANAGER_MAX_NUM_CUE );
427 Cue* pCue = &m_aCues[ a_rCueIndex ];
428 a_rCueIndex = -1;
429
430 if ( pCue->IsUsed() )
431 {
432 if ( a_fDelay != 0.0f && pCue->oChannelRefs.Size() == 0 )
433 {
434 // No need to remove events or wait for async stop
435 pCue->Reset();
436 }
437 else if ( !pCue->HasEventOfType( SOUNDEVENT_StopAudio ) )
438 {
440
441 T2_FOREACH( pCue->oChannelRefs, channel )
442 {
443 if ( channel->iFMODChannelHandle == -1 )
444 continue;
445
446 // Stop audio for every valid channel
447 CreateSoundEvent( SOUNDEVENT_StopAudio, a_fDelay, pCue, channel->pSample, channel, 0, -1 );
448 }
449 }
450 }
451}
452
453void ASoundManager::CancelCueEvents( Cue* a_pCue, SOUNDEVENT a_eEventType )
454{
455 TVALIDPTR( a_pCue );
456
457 for ( auto it = a_pCue->oEventList->Begin(); it != a_pCue->oEventList->End(); )
458 {
459 auto itNext = it.Next();
460
461 if ( it->eEventType == a_eEventType )
462 {
463 a_pCue->oEventList->Erase( it );
464 m_SoundEventPool.DeleteObject( it );
465 }
466
467 it = itNext;
468 }
469}
470
472{
473 auto pFoundNode = ms_WaveBanks.Find( a_rcName );
474
475 return ( ms_WaveBanks.IsValid( pFoundNode ) ) ? pFoundNode->GetSecond() : TNULL;
476}
477
478AWaveBank* ASoundManager::LoadWaveBankFromAsset( const Toshi::TString8& a_strName, TUINT a_uiForcedFlags )
479{
480 // Generate bank file name
481 TString8 strBankFileName = "Bank_";
482 strBankFileName += a_strName;
483 strBankFileName.MakeLower();
484
485 TPString8 pStrBank( "Bank" );
486
487 // Get PProperties symbol of the currently loaded sound asset file
488 const PBProperties* pProperties =
490 TVALIDPTR( pProperties );
491
492 const PBProperties* pBankProperties = pProperties->Begin()->GetValue()->GetProperties();
493
494 // Get the bank name
495 TPString8 strWaveWankBankName;
496 pBankProperties->GetOptionalPropertyValue( strWaveWankBankName, "name" );
497
498 TINT iNameCmpRslt = strWaveWankBankName.GetString8().Compare( a_strName, -1 );
499 auto pExistingWaveBank = ms_WaveBanks.Find( strWaveWankBankName );
500 auto pWaveBankVersionVal = pBankProperties->GetProperty( "version" );
501
502 // Store wavebank library
503 auto pWaveBankLibraryVal = pBankProperties->GetProperty( "library" );
504 TPString8 strWaveBankLibrary = ( pWaveBankLibraryVal ) ? pWaveBankLibraryVal->GetTPString8() : TPString8();
505
506 // Store wavebank type
507 auto pWaveBankTypeVal = pBankProperties->GetProperty( "type" );
508 TPString8 strWaveBankType = ( pWaveBankTypeVal ) ? pWaveBankTypeVal->GetTPString8() : TPString8();
509
510 // Store wavebank path
511 auto pWaveBankPathVal = pBankProperties->GetProperty( "path" );
512 TPString8 strWaveBankPath = ( pWaveBankPathVal ) ? pWaveBankPathVal->GetTPString8() : TPString8();
513
514 // Store wavebank extension
515 auto pWaveBankExtensionVal = pBankProperties->GetProperty( "extension" );
516 TPString8 strWaveBankExtension = ( pWaveBankExtensionVal ) ? pWaveBankExtensionVal->GetTPString8() : TPString8();
517
518 // Create the actual wavebank from the parameters
519 AWaveBank* pWaveBank = AllocateWaveBank( strWaveWankBankName, strWaveBankLibrary, strWaveBankType, strWaveBankPath );
520
521 pWaveBank->ParseWavesData( pBankProperties, a_uiForcedFlags );
522
523 return pWaveBank;
524}
525
526AWaveBank* ASoundManager::AllocateWaveBank( const Toshi::TPString8& a_strBank, const Toshi::TPString8& a_strLibrary, const Toshi::TPString8& a_strType, const Toshi::TPString8& a_strPath )
527{
528 // Check if we are loading the supported format
529 if ( a_strLibrary != TPString8( "FMOD" ) || a_strType == TPString8( "Dir" ) )
530 {
531 TASSERT( !"Trying to load an unknown non-FSB WaveBank format!" );
532 return TNULL;
533 }
534
535 if ( a_strType == TPString8( "File" ) )
536 {
537 // Load from a file
538 return new AWaveBankFMODFSB( a_strBank, a_strPath );
539 }
540 else if ( a_strType == TPString8( "Stream" ) )
541 {
542 // Load from a stream
543 return new AWaveBankFMODFSBStream( a_strBank, a_strPath );
544 }
545
546 return TNULL;
547}
548
549TBOOL ASoundManager::LoadSoundBankImpl( const TCHAR* a_szName, TBOOL a_bSimpleSound, TBOOL a_bLoadImmediately )
550{
552
553 TString8 strFileName = SOUNDS_BASE_DIRECTORY;
554 strFileName += "soundbank_";
555 strFileName += a_szName;
556 strFileName += ".trb";
557
558 TTRB trb;
559 TTRB::ERROR eTrbLoadResult = trb.Load( strFileName );
560
561 if ( eTrbLoadResult != TTRB::ERROR_OK )
562 {
563 TERROR( "Unable to load soundbank: %s\n", strFileName.GetString() );
564 return TFALSE;
565 }
566
567 auto& rcProperties = *PBProperties::LoadFromTRB( trb );
568
569 // Delete symbol table for some small optimisation
570 trb.DeleteSymbolTable();
571
572 TBOOL bNoErrors = TTRUE;
573
574 T2_FOREACH( rcProperties, soundbank )
575 {
576 const PBProperties* pSoundsProperties = soundbank->GetValue()->GetProperties();
577
578 TINT iNumSounds;
579 TBOOL bHasNumSounds = pSoundsProperties->GetOptionalPropertyValue( iNumSounds, "numsounds" );
580
581 if ( !bHasNumSounds )
582 {
583 TASSERT( !"Invalid format of the soundbank property" );
584 return TFALSE;
585 }
586
587 if ( iNumSounds == 0 )
588 {
589 return TTRUE;
590 }
591
592 // Allocate soundbank
593 ASoundBank* pSoundBank = new ( AMemory::GetMemBlock( AMemory::POOL_Sound ) ) ASoundBank( iNumSounds );
594 m_SoundBanks.PushBack( pSoundBank );
595
596 if ( a_bSimpleSound )
597 {
598 pSoundBank->m_pSounds = new ( AMemory::GetMemBlock( AMemory::POOL_Sound ) ) ASoundLegacy[ iNumSounds ];
599 }
600 else
601 {
602 pSoundBank->m_pSoundsEx = new ( AMemory::GetMemBlock( AMemory::POOL_Sound ) ) ASound[ iNumSounds ];
603 }
604
605 pSoundsProperties->GetOptionalPropertyValue( pSoundBank->m_strName, "name" );
606
607 TINT iLocalised;
608 pSoundsProperties->GetOptionalPropertyValue( iLocalised, "localised" );
609
610 TINT iSoundIndex = 0;
611 T2_FOREACH( *pSoundsProperties, it )
612 {
613 // Skip anything that doesn't even look like 'Sound' property
614 if ( it->GetName().GetString()[ 0 ] != 'S' )
615 continue;
616
617 auto pSoundProperties = it->GetValue()->GetProperties();
618
619 TINT iSoundId;
620 pSoundProperties->GetOptionalPropertyValue( iSoundId, "id" );
621
622 if ( a_bSimpleSound )
623 {
624 // Initialise ASound
625 ASoundLegacy* pSound = &pSoundBank->m_pSounds[ iSoundIndex++ ];
626
627 pSound->m_iId = iSoundId;
628 m_SoundIdToSoundLegacy.Insert( iSoundId, pSound );
629
630 if ( !pSoundProperties->GetOptionalPropertyValue( pSound->m_iFlags, "flags" ) )
631 {
632 bNoErrors = TFALSE;
633 TASSERT( !"No flags property specified in the soundbank" );
634 }
635
636 PBPropertyValueArray* pBanks = TNULL;
637 if ( !pSoundProperties->GetOptionalPropertyValue( pBanks, "banks" ) )
638 {
639 bNoErrors = TFALSE;
640 TASSERT( !"No banks property specified in the soundbank" );
641 continue;
642 }
643
644 PBPropertyValueArray* pWaves;
645 if ( bNoErrors && pSoundProperties->GetOptionalPropertyValue( pWaves, "waves" ) )
646 {
647 TASSERT( pBanks->GetSize() >= 1 );
648 TASSERT( pWaves->GetSize() >= 1 );
649
650 TPString8 strSoundBankName = pBanks->GetValue( 0 )->GetTPString8();
651 AWaveBank* pWaveBank = FindWaveBank( strSoundBankName );
652
653 if ( a_bLoadImmediately )
654 {
655 LoadWaveBankSamples( strSoundBankName, iLocalised != 0 ? AWaveBank::LOADFLAGS_LOCALISE : AWaveBank::LOADFLAGS_NONE, -1 );
656 }
657
658 pSound->m_pWaveBank = pWaveBank;
659 pSound->m_iWaveId = pWaves->GetValue( 0 )->GetInteger();
660 }
661 }
662 else
663 {
664 // Initialise ASoundEx
665 ASound* pSoundEx = &pSoundBank->m_pSoundsEx[ iSoundIndex++ ];
666
667 pSoundEx->m_iId = iSoundId;
668 m_SoundIdToSound.Insert( iSoundId, pSoundEx );
669
670 // Get category
671 TPString8 strCategory;
672 if ( bNoErrors && pSoundProperties->GetOptionalPropertyValue( strCategory, "category" ) )
673 {
674 TPSTRING8_DECLARE( default );
675
676 // Find category and store it's index
677 auto pFoundCategory = m_CategoryIndices.Find(
678 ( strCategory.GetPooledString() || strCategory.GetString8().Length() == 0 ) ? TPS8( default ) : strCategory
679 );
680
681 TASSERT( m_CategoryIndices.IsValid( pFoundCategory ) );
682 pSoundEx->m_uiCategoryIndex = pFoundCategory->GetSecond();
683
684 // Get flags
685 if ( pSoundProperties->GetOptionalPropertyValue( pSoundEx->m_iFlags, "flags" ) )
686 {
687 // Get mindist and priority
688 pSoundProperties->GetOptionalPropertyValue( pSoundEx->m_fMinDist, "mindist" );
689 pSoundProperties->GetOptionalPropertyValue( pSoundEx->m_ui8Priority, "priority" );
690
691 // Get banks and waves
692 PBPropertyValueArray* pBanks;
693 PBPropertyValueArray* pWaves;
694
695 // Load info about the waves
696 if ( pSoundProperties->GetOptionalPropertyValue( pBanks, "banks" ) &&
697 pSoundProperties->GetOptionalPropertyValue( pWaves, "waves" ) )
698 {
699 pSoundEx->m_vecSamples.Reserve( pBanks->GetSize() );
700
701 for ( TUINT i = 0; i < pBanks->GetSize(); i++ )
702 {
703 // Find the wavebank
704 TPString8 strWaveBankName = pBanks->GetValue( i )->GetTPString8();
705 AWaveBank* pWaveBank = FindWaveBank( strWaveBankName );
706 TVALIDPTR( pWaveBank );
707
708 if ( a_bLoadImmediately && !strWaveBankName.IsEmpty() && pWaveBank )
709 {
710 pWaveBank->Load( iLocalised != 0 ? AWaveBank::LOADFLAGS_LOCALISE : AWaveBank::LOADFLAGS_NONE, -1 );
711 }
712
713 if ( pWaveBank != TNULL )
714 {
715 ASound::Sample oWave;
716 oWave.pWaveBank = pWaveBank;
717 oWave.iId = pWaves->GetValue( i )->GetInteger();
718
719 pSoundEx->m_vecSamples.PushBack( oWave );
720
721 if ( pSoundEx->m_iFlags & 4 )
722 pWaveBank->SetWaveFlag2( oWave.iId );
723 else
724 pWaveBank->SetWaveFlag1( oWave.iId );
725 }
726 else
727 {
728 bNoErrors = TFALSE;
729 }
730 }
731
732 // Read volumes of the waves
733 PBPropertyValueArray* pVolumes;
734 if ( bNoErrors && pSoundProperties->GetOptionalPropertyValue( pVolumes, "volumes" ) )
735 {
736 for ( TUINT i = 0; i < pVolumes->GetSize(); i++ )
737 {
738 TFLOAT fVolume = pVolumes->GetValue( i )->GetFloat();
739 pSoundEx->m_vecSamples[ i ].fVolume = fVolume;
740 }
741 }
742 else
743 {
744 TASSERT( !"Error while parsing sound settings" );
745 bNoErrors = TFALSE;
746 continue;
747 }
748
749 // Read randomization settings for the volumes
750 PBPropertyValueArray* pVolrand;
751 if ( pSoundProperties->GetOptionalPropertyValue( pVolrand, "volrand" ) )
752 {
753 for ( TUINT i = 0; i < pVolrand->GetSize(); i += 2 )
754 {
755 TFLOAT fVolMin = pVolrand->GetValue( i + 0 )->GetFloat();
756 TFLOAT fVolMax = pVolrand->GetValue( i + 1 )->GetFloat();
757
758 pSoundEx->m_vecSamples[ i / 2 ].fMinVolumeMultiplier = fVolMin;
759 pSoundEx->m_vecSamples[ i / 2 ].fMaxVolumeMultiplier = fVolMax;
760 }
761 }
762 else
763 {
764 TASSERT( !"Error while parsing sound settings" );
765 bNoErrors = TFALSE;
766 continue;
767 }
768
769 // Read pitches of the waves
770 PBPropertyValueArray* pPitches;
771 if ( pSoundProperties->GetOptionalPropertyValue( pPitches, "pitches" ) )
772 {
773 for ( TUINT i = 0; i < pPitches->GetSize(); i++ )
774 {
775 TFLOAT fPitch = pPitches->GetValue( i )->GetFloat();
776 pSoundEx->m_vecSamples[ i ].fPitch = fPitch;
777 }
778 }
779 else
780 {
781 TASSERT( !"Error while parsing sound settings" );
782 bNoErrors = TFALSE;
783 continue;
784 }
785
786 // Read randomization settings for the pitches
787 PBPropertyValueArray* pPitchrand;
788 if ( pSoundProperties->GetOptionalPropertyValue( pPitchrand, "pitchrand" ) )
789 {
790 for ( TUINT i = 0; i < pPitchrand->GetSize(); i += 2 )
791 {
792 TFLOAT fPitchMin = pPitchrand->GetValue( i + 0 )->GetFloat();
793 TFLOAT fPitchMax = pPitchrand->GetValue( i + 1 )->GetFloat();
794
795 pSoundEx->m_vecSamples[ i / 2 ].fMinPitch = fPitchMin;
796 pSoundEx->m_vecSamples[ i / 2 ].fMaxPitch = fPitchMax;
797 }
798 }
799 else
800 {
801 TASSERT( !"Error while parsing sound settings" );
802 bNoErrors = TFALSE;
803 continue;
804 }
805
806 // Read start offsets of the waves
807 PBPropertyValueArray* pStarts;
808 if ( pSoundProperties->GetOptionalPropertyValue( pStarts, "starts" ) )
809 {
810 for ( TUINT i = 0; i < pStarts->GetSize(); i++ )
811 {
812 TFLOAT fStart = pStarts->GetValue( i )->GetFloat();
813 pSoundEx->m_vecSamples[ i ].fStart = fStart;
814 }
815 }
816 else
817 {
818 TASSERT( !"Error while parsing sound settings" );
819 bNoErrors = TFALSE;
820 continue;
821 }
822
823 // Read var delays of the waves
824 PBPropertyValueArray* pVarDelays;
825 if ( pSoundProperties->GetOptionalPropertyValue( pVarDelays, "vardelays" ) )
826 {
827 for ( TUINT i = 0; i < pVarDelays->GetSize(); i++ )
828 {
829 TFLOAT fVarDelay = pVarDelays->GetValue( i )->GetFloat();
830 pSoundEx->m_vecSamples[ i ].fVarDelay = fVarDelay;
831 }
832 }
833 else
834 {
835 TASSERT( !"Error while parsing sound settings" );
836 bNoErrors = TFALSE;
837 continue;
838 }
839
840 // Read tracks of the waves
841 PBPropertyValueArray* pTracks;
842 if ( pSoundProperties->GetOptionalPropertyValue( pTracks, "tracks" ) )
843 {
844 pSoundEx->m_vecTracks.Reserve( pTracks->GetSize() );
845
846 for ( TUINT i = 0; i < pTracks->GetSize(); i++ )
847 {
848 pSoundEx->m_vecTracks.EmplaceBack( pTracks->GetValue( i )->GetInteger() );
849 }
850 }
851 else
852 {
853 TASSERT( !"Error while parsing sound settings" );
854 bNoErrors = TFALSE;
855 continue;
856 }
857
858 // Read weights of the waves
859 PBPropertyValueArray* pWeights;
860 if ( pSoundProperties->GetOptionalPropertyValue( pWeights, "weights" ) )
861 {
862 for ( TUINT i = 0; i < pWeights->GetSize(); i++ )
863 {
864 TFLOAT fWeight = pVarDelays->GetValue( i )->GetFloat();
865 pSoundEx->m_vecSamples[ i ].iWeight = TMath::Round( fWeight );
866 }
867 }
868 else
869 {
870 TASSERT( !"Error while parsing sound settings" );
871 bNoErrors = TFALSE;
872 continue;
873 }
874
875 // Read trackloop settings of the waves
876 PBPropertyValueArray* pTrackloop;
877 if ( pSoundProperties->GetOptionalPropertyValue( pTrackloop, "trackloop" ) )
878 {
879 // Each bit represents a track and if it's set to 1, loop is enabled
880 pSoundEx->m_TrackLoop.Create( pTrackloop->GetSize(), 0 );
881
882 for ( TUINT i = 0; i < pTrackloop->GetSize(); i++ )
883 {
884 if ( pVarDelays->GetValue( i )->GetRaw() != 0 )
885 {
886 pSoundEx->m_TrackLoop.SetBit( i, 1 );
887 }
888 }
889 }
890 else
891 {
892 TASSERT( !"Error while parsing sound settings" );
893 bNoErrors = TFALSE;
894 continue;
895 }
896
897 // Read loopstarts of the waves
898 PBPropertyValueArray* pLoopStarts;
899 if ( pSoundProperties->GetOptionalPropertyValue( pLoopStarts, "loopstarts" ) )
900 {
901 for ( TUINT i = 0; i < pLoopStarts->GetSize(); i++ )
902 {
903 TINT iLoopStart = pLoopStarts->GetValue( i )->GetInteger();
904 pSoundEx->m_vecLoopStarts.PushBack( iLoopStart );
905 }
906 }
907 else
908 {
909 TASSERT( !"Error while parsing sound settings" );
910 bNoErrors = TFALSE;
911 continue;
912 }
913 }
914 }
915 }
916 }
917 }
918
919 if ( bNoErrors )
920 {
921 if ( a_bLoadImmediately )
922 pSoundBank->Load();
923 }
924 else
925 {
926 pSoundBank->Remove();
927 delete pSoundBank;
928 }
929 }
930
931 TUINT uiCurrentAlloced;
932 TUINT uiMaxAlloced;
933 FSOUND_GetMemoryStats( &uiCurrentAlloced, &uiMaxAlloced );
934 TINFO( "LoadSoundBank result: name=%s; success=%d; currentalloced=%u; maxalloced=%u\n", a_szName, bNoErrors, uiCurrentAlloced, uiMaxAlloced );
935
936 return bNoErrors;
937}
938
939TUINT ASoundManager::GetCueIndex( Cue* a_pCue )
940{
941 return ( TREINTERPRETCAST( TUINTPTR, a_pCue ) - TREINTERPRETCAST( TUINTPTR, ASoundManager::ms_pSingleton ) - TOFFSETOF( ASoundManager, m_aCues ) ) / sizeof( Cue );
942}
943
944TBOOL ASoundManager::Initialise()
945{
946 FSOUND_Init( 44100, m_iMinHWChannels + m_iNumChannels, 0 );
947
948 TINT num2DC, num3DC, numDC;
949 FSOUND_GetNumHWChannels( &num2DC, &num3DC, &numDC );
950 FSOUND_GetMaxChannels();
951 FSOUND_Close();
952
953 TBOOL bRes = FSOUND_SetMinHardwareChannels( m_bUseMinHardwareChannels ? m_iMinHWChannels : 0 );
954 FSOUND_Init( 44100, m_iNumChannels, 0 );
955 FSOUND_GetNumHWChannels( &num2DC, &num3DC, &numDC );
956 FSOUND_GetMaxChannels();
957 FSOUND_Stream_SetBufferSize( 2000 );
958 FSOUND_SetBufferSize( 100 );
959 FSOUND_3D_SetDistanceFactor( 1.0f );
960 FSOUND_3D_SetRolloffFactor( 1.0f );
961 FSOUND_3D_SetDopplerFactor( 1.0f );
962
963 return bRes;
964}
965
967{
968 if ( a_bPause )
969 {
970 // Don't count number of pauses
971 if ( ms_iNumPauses != 0 ) return;
972
973 // Pause cues
974 for ( TINT i = 0; i < ASOUNDMANAGER_MAX_NUM_CUE; i++ )
975 {
976 Cue* pCue = &m_aCues[ i ];
977
978 if ( !pCue->pSound || !m_aCategories[ pCue->pSound->m_uiCategoryIndex ].bPausable )
979 continue;
980
981 T2_FOREACH( pCue->oChannelRefs, channel )
982 {
983 if ( !( channel->iFlags & 1 ) )
984 {
985 FSOUND_SetPaused( channel->iFMODChannelHandle, TTRUE );
986 }
987 }
988 }
989
990 ms_iNumPauses += 1;
991 }
992 else if ( ms_iNumPauses > 0 && --ms_iNumPauses == 0 )
993 {
994 // Unpause cues
995 for ( TINT i = 0; i < ASOUNDMANAGER_MAX_NUM_CUE; i++ )
996 {
997 Cue* pCue = &m_aCues[ i ];
998
999 if ( !pCue->pSound ) continue;
1000
1001 T2_FOREACH( pCue->oChannelRefs, channel )
1002 {
1003 if ( !( channel->iFlags & 1 ) )
1004 {
1005 FSOUND_SetPaused( channel->iFMODChannelHandle, TFALSE );
1006 }
1007 }
1008 }
1009 }
1010}
1011
1013{
1014 TBOOL bOpened = AAssetLoader::Load(
1015 "Data/Assets/lib_wavebank.trb",
1017 TTRUE
1018 );
1019
1020 if ( !bOpened ) return TFALSE;
1021
1022 const PBProperties* pProperties =
1024 TVALIDPTR( pProperties );
1025
1026 auto pWaveBanksVal = pProperties->GetProperty( "Wavebanks" );
1027 TVALIDPTR( pWaveBanksVal );
1028
1029 auto pWaveBanks = pWaveBanksVal->GetArray();
1030
1031 for ( TUINT i = 0; i < pWaveBanks->GetSize(); i++ )
1032 {
1033 TPString8 strWaveBankName = pWaveBanks->GetValue( i )->GetTPString8();
1034
1035 if ( FindWaveBank( strWaveBankName ) == TNULL )
1036 {
1037 LoadWaveBankFromAsset( strWaveBankName.GetString(), 0 );
1038 }
1039 }
1040
1041 auto pCategoriesVal = pProperties->GetProperty( "Categories" );
1042 TVALIDPTR( pCategoriesVal );
1043
1044 auto pCategories = pCategoriesVal->GetArray();
1045
1046 for ( TUINT i = 0; i < pCategories->GetSize(); i++ )
1047 {
1048 TPString8 strCategoryName = pCategories->GetValue( i )->GetTPString8();
1049
1050 m_CategoryIndices.Insert( strCategoryName, m_CategoryIndices.Size() );
1051 }
1052
1054
1055 return TTRUE;
1056}
1057
1058TBOOL ASoundManager::LoadWaveBankSamples( const Toshi::TPString8& a_rcName, AWaveBank::LOADFLAGS a_eLoadFlags, TINT a_iBufferSize )
1059{
1060 if ( a_rcName.GetPooledString() && !a_rcName.GetPooledString()->GetString8().IsEmpty() )
1061 {
1062 AWaveBank* pWaveBank = FindWaveBank( a_rcName );
1063
1064 if ( pWaveBank )
1065 {
1066 return pWaveBank->Load( a_eLoadFlags, a_iBufferSize ) == AWaveBank::LOADRESULT_OK;
1067 }
1068 }
1069
1070 return TFALSE;
1071}
1072
1073ASoundBank* ASoundManager::FindSoundBank( const Toshi::TPString8& a_rcName )
1074{
1075 T2_FOREACH( m_SoundBanks, it )
1076 {
1077 if ( it->m_strName == a_rcName )
1078 return it;
1079 }
1080
1081 return TNULL;
1082}
1083
1084TBOOL ASoundManager::LoadSoundBank( const Toshi::TPString8& a_rcName, TBOOL a_bSoundEx, TBOOL a_bLoadImmediately )
1085{
1086 if ( a_rcName.GetPooledString() && !a_rcName.GetPooledString()->GetString8().IsEmpty() )
1087 {
1088 if ( FindSoundBank( a_rcName ) == TNULL )
1089 {
1090 return LoadSoundBankImpl( a_rcName, a_bSoundEx, a_bLoadImmediately );
1091 }
1092 }
1093
1094 return TFALSE;
1095}
1096
1097void ASoundManager::LoadSoundBankSamples( const Toshi::TPString8& a_rcName )
1098{
1099 if ( ASoundBank* pSoundBank = FindSoundBank( a_rcName ) )
1100 {
1101 pSoundBank->Load();
1102 }
1103}
1104
1105void ASoundManager::CreatePlaySoundEvent( Cue* a_pCue, TINT a_iTrackIndex, TINT a_iFirstWaveIndex, TINT a_iLastWaveIndex, TINT a_iFlags, TFLOAT a_fDelay1, TFLOAT a_fDelay2 )
1106{
1107 TVALIDPTR( a_pCue );
1108
1109 ASound* pSound = a_pCue->pSound;
1110 TVALIDPTR( pSound );
1111
1112 TINT iFlags = a_iFlags;
1113
1114 TINT iLoopStart = pSound->m_vecLoopStarts[ a_iTrackIndex ];
1115 if ( iLoopStart > 0 || iLoopStart == -1 )
1116 iFlags &= ~2;
1117
1118 TRandom* pRandom = &ARandom::GetSingleton()->m_oRandom;
1119
1120 if ( !HASANYFLAG( iFlags, 8 ) )
1121 {
1122 // Play multiple sounds
1123 TASSERT( a_iFirstWaveIndex <= a_iLastWaveIndex );
1124
1125 if ( pSound->m_vecTracks[ a_iTrackIndex ] < 2 )
1126 {
1127 TINT iNumLeftWaves = a_iLastWaveIndex - a_iFirstWaveIndex;
1128
1129 for ( TINT i = a_iFirstWaveIndex; iNumLeftWaves > 0; iNumLeftWaves-- )
1130 {
1131 ASound::Sample* pSample = &pSound->m_vecSamples[ i ];
1132
1133 TFLOAT fVolumeMultiplier = pRandom->GetFloatMinMax( pSample->fMinVolumeMultiplier, pSample->fMaxVolumeMultiplier );
1134 TFLOAT fVolume = fVolumeMultiplier * pSample->fVolume;
1135 TMath::Clip( fVolume, 0.0f, 1.0f );
1136
1137 EventParameters oParams;
1138 oParams[ 0 ] = fVolume;
1139 oParams[ 1 ] = pRandom->GetFloatMinMax( pSample->fMinPitch, pSample->fMaxPitch );
1140 oParams[ 2 ] = 0.0f;
1141
1142 TFLOAT fStartDelay = pSample->fStart + pRandom->GetFloat() * pSample->fVarDelay;
1143 if ( a_fDelay1 != -1.0f ) fStartDelay += a_fDelay1;
1144 if ( a_fDelay2 != -1.0f ) fStartDelay += a_fDelay2;
1145
1146 SoundEvent* pEvent = CreateSoundEvent(
1147 ( iFlags & 16 ) ? SOUNDEVENT_PlayStream : SOUNDEVENT_PlayAudio,
1148 fStartDelay,
1149 a_pCue,
1150 pSample,
1151 oParams,
1152 TNULL,
1153 iFlags,
1154 a_iTrackIndex
1155 );
1156
1157 TVALIDPTR( pEvent );
1158 }
1159 }
1160 }
1161 else
1162 {
1163 // Play single sound
1164
1165 TINT iSampleIndex = ( a_iFlags < 0 && pSound->m_vecTracks[ a_iTrackIndex ] > 1 ) ?
1166 pSound->GetRandomSampleWeighted( a_iTrackIndex, a_iFirstWaveIndex, a_iLastWaveIndex ) :
1167 pSound->GetRandomSample( a_iFirstWaveIndex, a_iLastWaveIndex );
1168
1169 ASound::Sample* pSample = &pSound->m_vecSamples[ iSampleIndex ];
1170
1171 TFLOAT fVolumeMultiplier = pRandom->GetFloatMinMax( pSample->fMinVolumeMultiplier, pSample->fMaxVolumeMultiplier );
1172 TFLOAT fVolume = fVolumeMultiplier * pSample->fVolume;
1173 TMath::Clip( fVolume, 0.0f, 1.0f );
1174
1175 EventParameters oParams;
1176 oParams[ 0 ] = fVolume;
1177 oParams[ 1 ] = pRandom->GetFloatMinMax( pSample->fMinPitch, pSample->fMaxPitch );
1178 oParams[ 2 ] = 0.0f;
1179
1180 TFLOAT fStartDelay = pSample->fStart + pRandom->GetFloatMinMax( 0.0f, pSample->fVarDelay );
1181 if ( a_fDelay1 != -1.0f ) fStartDelay += a_fDelay1;
1182 if ( a_fDelay2 != -1.0f ) fStartDelay += a_fDelay2;
1183
1184 SoundEvent* pEvent = CreateSoundEvent(
1185 ( iFlags & 16 ) ? SOUNDEVENT_PlayStream : SOUNDEVENT_PlayAudio,
1186 fStartDelay,
1187 a_pCue,
1188 pSample,
1189 oParams,
1190 TNULL,
1191 iFlags,
1192 a_iTrackIndex
1193 );
1194
1195 TVALIDPTR( pEvent );
1196 }
1197}
1198
1199ASoundManager::SoundEvent* ASoundManager::CreateSoundEvent( SOUNDEVENT a_eEventType, TFLOAT a_fDelay, Cue* a_pCue, ASound::Sample* a_pSample, ChannelRef* a_pChannel, TINT a_iFlags, TINT a_iTrackIndex )
1200{
1201 TVALIDPTR( a_pCue );
1202 TASSERT( m_SoundEventPool.CanAllocate() );
1203
1204 if ( m_SoundEventPool.CanAllocate() )
1205 {
1206 SoundEvent* pEvent = m_SoundEventPool.NewObject( a_eEventType, m_fCurrentTime + a_fDelay, a_pCue, a_pSample, a_pChannel, a_iFlags, a_iTrackIndex );
1207 TVALIDPTR( pEvent );
1208
1209 AddEventToCue( a_pCue, pEvent );
1210 return pEvent;
1211 }
1212
1213 return TNULL;
1214}
1215
1216ASoundManager::SoundEvent* ASoundManager::CreateSoundEvent( SOUNDEVENT a_eEventType, TFLOAT a_fDelay, Cue* a_pCue, ASound::Sample* a_pSample, TFLOAT a_fCustomParam1, ChannelRef* a_pChannel, TINT a_iFlags, TINT a_iTrackIndex )
1217{
1218 TVALIDPTR( a_pCue );
1219 TASSERT( m_SoundEventPool.CanAllocate() );
1220
1221 if ( m_SoundEventPool.CanAllocate() )
1222 {
1223 SoundEvent* pEvent = m_SoundEventPool.NewObject( a_eEventType, m_fCurrentTime + a_fDelay, a_pCue, a_pSample, a_fCustomParam1, a_pChannel, a_iFlags, a_iTrackIndex );
1224 TVALIDPTR( pEvent );
1225
1226 AddEventToCue( a_pCue, pEvent );
1227 return pEvent;
1228 }
1229
1230 return TNULL;
1231}
1232
1233ASoundManager::SoundEvent* ASoundManager::CreateSoundEvent( SOUNDEVENT a_eEventType, TFLOAT a_fDelay, Cue* a_pCue, ASound::Sample* a_pSample, const EventParameters& a_rcCustomParams, ChannelRef* a_pChannel, TINT a_iFlags, TINT a_iTrackIndex )
1234{
1235 TVALIDPTR( a_pCue );
1236 TASSERT( m_SoundEventPool.CanAllocate() );
1237
1238 if ( m_SoundEventPool.CanAllocate() )
1239 {
1240 SoundEvent* pEvent = m_SoundEventPool.NewObject( a_eEventType, m_fCurrentTime + a_fDelay, a_pCue, a_pSample, a_rcCustomParams, a_pChannel, a_iFlags, a_iTrackIndex );
1241 TVALIDPTR( pEvent );
1242
1243 AddEventToCue( a_pCue, pEvent );
1244 return pEvent;
1245 }
1246
1247 return TNULL;
1248}
1249
1250void ASoundManager::AddEventToCue( Cue* a_pCue, SoundEvent* a_pSoundEvent )
1251{
1252 TVALIDPTR( a_pCue );
1253 TVALIDPTR( a_pSoundEvent );
1254
1255 SoundEvent* pFirstEvent = ( !a_pCue->oEventList->IsEmpty() ) ? a_pCue->oEventList->Begin() : TNULL;
1256 a_pCue->oEventList->Push( a_pSoundEvent );
1257
1258 // If first event in the list changed, reinsert the list in m_QueuedEventLists
1259 // to make sure the ordering is right. It's important because the sorting method
1260 // is taking the first event into account when sorting the lists
1261 if ( pFirstEvent != a_pCue->oEventList->Begin() )
1262 {
1263 m_QueuedSortedEventLists.ReInsert( a_pCue->oEventList );
1264 }
1265}
1266
1267TBOOL ASoundManager::UpdateStreamActivity( StreamRef* a_pStream )
1268{
1269 TASSERT( !"Not implemented" );
1270 return TFALSE;
1271}
1272
1273TBOOL ASoundManager::UpdateStreamCue( StreamRef* a_pStream )
1274{
1275 TVALIDPTR( a_pStream );
1276
1277 Cue* pCue = a_pStream->pCue;
1278 ASound* pSound = pCue->pSound;
1279
1280 if ( pSound )
1281 {
1282 ChannelRef* pChannel = a_pStream->pChannelRef;
1283 AWaveBank* pWaveBank = pChannel->pSample->pWaveBank;
1284 FSOUND_STREAM* pStreamHandle = (FSOUND_STREAM*)pWaveBank->CreateWaveSample( pChannel->pSample->iId, 0 );
1285
1286 if ( !( pSound->m_iFlags & 0x40 ) )
1287 {
1288 TINT iOpenState = FSOUND_Stream_GetOpenState( pStreamHandle );
1289
1290 if ( iOpenState == -2 ) return TFALSE;
1291 FSOUND_Stream_GetNumSubStreams( pStreamHandle );
1292 FSOUND_Stream_SetSubStream( pStreamHandle, pWaveBank->GetWaveId( pChannel->pSample->iId ) );
1293
1294 pSound->m_iFlags |= 0x40;
1295 }
1296
1297 TINT iOpenState = FSOUND_Stream_GetOpenState( pStreamHandle );
1298
1299 if ( iOpenState != -1 )
1300 {
1301 if ( iOpenState == -2 )
1302 return TFALSE;
1303
1304 if ( iOpenState != -3 )
1305 {
1306 if ( iOpenState != 0 )
1307 return TTRUE;
1308
1309 pSound->m_iFlags &= ~0x40;
1310
1311 TINT iChannelHandle = FSOUND_Stream_PlayEx( FSOUND_FREE, pStreamHandle, TNULL, TTRUE );
1312 pChannel->iFMODChannelHandle = iChannelHandle;
1313 TASSERT( iChannelHandle != -1 );
1314
1315 if ( iChannelHandle == -1 )
1316 return TTRUE;
1317
1318 pChannel->iFlags = pChannel->iFlags | 0x20;
1319 pSound->m_iFlags |= 0x20;
1320
1321 TINT iVolume = ( m_bMuted ) ? 0 : TINT( pChannel->fVolume * 255.0f );
1322
1323 FSOUND_SetVolume( iChannelHandle, iVolume );
1324 FSOUND_SetFrequency( iChannelHandle, pChannel->iFrequency );
1325 FSOUND_SetPriority( iChannelHandle, TINT( pSound->m_ui8Priority ) );
1326
1327 TINT iStreamMode = FSOUND_Stream_GetMode( pStreamHandle );
1328
1329 if ( pChannel->iFlags & 2 )
1330 {
1331 iStreamMode = iStreamMode & 0xfffffffa | 2;
1332 FSOUND_SetReserved( iChannelHandle, TTRUE );
1333 }
1334 else
1335 {
1336 iStreamMode = iStreamMode & 0xfffffff9 | 1;
1337 }
1338
1339 if ( pChannel->iFlags & 4 )
1340 iStreamMode = iStreamMode & 0xfff7dfff | 0x1000;
1341 else
1342 iStreamMode = iStreamMode & 0xffffcfff | 0x80000;
1343
1344 FSOUND_Stream_SetMode( pStreamHandle, iStreamMode );
1345
1346 if ( pChannel->iFlags & 4 )
1347 {
1348 TFLOAT aPos[ 3 ];
1349 aPos[ 0 ] = ( pCue->vecPosition ).x;
1350 aPos[ 1 ] = ( pCue->vecPosition ).y;
1351 aPos[ 2 ] = -( pCue->vecPosition ).z;
1352
1353 FSOUND_3D_SetMinMaxDistance( iChannelHandle, pSound->m_fMinDist, 10000.0f );
1354 FSOUND_3D_SetAttributes( iChannelHandle, aPos, TNULL );
1355 }
1356 else
1357 {
1358 FSOUND_SetPan( iChannelHandle, 128 );
1359 }
1360
1361 if ( !HASANYFLAG( pChannel->iFlags, 1 ) )
1362 {
1363 FSOUND_SetPaused( iChannelHandle, TFALSE );
1364 }
1365 else if ( pCue->oEventList.IsLinked() )
1366 {
1367 pCue->oEventList.Remove();
1368 }
1369
1370 T2_FOREACH( pCue->aChannelRefsLegacy[ 0 ], it )
1371 {
1372 it->fnCallback( 0, GetCueIndex( pCue ), it->pUserData );
1373 }
1374
1375 return TTRUE;
1376 }
1377 }
1378
1379 pSound->m_iFlags = pSound->m_iFlags & 0xffffffbf;
1380 pCue->Reset();
1381 }
1382
1383 return TTRUE;
1384}
1385
1386void ASoundManager::EventHandler_PlaySound( SoundEvent* a_pEvent )
1387{
1388 TVALIDPTR( a_pEvent );
1389 TASSERT( TTRUE == m_ChannelRefPool.CanAllocate() );
1390
1391 Cue* pCue = a_pEvent->pCue;
1392 ASound* pSound = pCue->pSound;
1393
1394 if ( pSound && m_ChannelRefPool.CanAllocate() )
1395 {
1396 // Allocate new ChannelRef object from the pool
1397 ChannelRef* pChannelRef = m_ChannelRefPool.NewObject();
1398
1399 // Push the channelref to the cue
1400 pCue->iNumChannelRefs += 1;
1401 pCue->oChannelRefs.PushBack( pChannelRef );
1402
1403 TFLOAT fCategoryVolume = m_aCategories[ pCue->pSound->m_uiCategoryIndex ].fVolumeMultiplier;
1404
1405 pChannelRef->pSample = a_pEvent->pSample;
1406 pChannelRef->fVolume = fCategoryVolume * pCue->fVolume * a_pEvent->oParameters[ 0 ];
1407 TMath::Clip( pChannelRef->fVolume, 0.0f, 1.0f );
1408
1409 ASound::Sample* pWave = pChannelRef->pSample;
1410 pChannelRef->iFlags = a_pEvent->iFlags;
1411 pChannelRef->iFrequency = TINT( pWave->iFrequency * a_pEvent->oParameters[ 1 ] );
1412
1413 FSOUND_SAMPLE* pSample = (FSOUND_SAMPLE*)pWave->pWaveBank->GetWave( pWave->iId )->pSampleHandle;
1414
1415 TINT iSampleMode = FSOUND_Sample_GetMode( pSample );
1416
1417 if ( pChannelRef->iFlags & 2 )
1418 iSampleMode = iSampleMode & 0xfffffffa | 2;
1419 else
1420 iSampleMode = iSampleMode & 0xfffffff9 | 1;
1421
1422 FSOUND_Sample_SetMode( pSample, iSampleMode );
1423
1424 TINT iChannelHandle = FSOUND_PlaySoundEx( FSOUND_FREE, pSample, TNULL, TTRUE );
1425 pChannelRef->iFMODChannelHandle = iChannelHandle;
1426 TASSERT( iChannelHandle != -1 );
1427
1428 if ( iChannelHandle != -1 )
1429 {
1430 // No errors
1431 TINT iVolume = ( m_bMuted ) ? 0 : TINT( pChannelRef->fVolume * 255.0f );
1432
1433 FSOUND_SetVolume( iChannelHandle, iVolume );
1434 FSOUND_SetFrequency( iChannelHandle, pChannelRef->iFrequency );
1435 FSOUND_SetPriority( iChannelHandle, TINT( pSound->m_ui8Priority ) );
1436
1437 if ( pChannelRef->iFlags & 4 )
1438 {
1439 TFLOAT aPos[ 3 ];
1440 aPos[ 0 ] = ( pCue->vecPosition ).x;
1441 aPos[ 1 ] = ( pCue->vecPosition ).y;
1442 aPos[ 2 ] = -( pCue->vecPosition ).z;
1443
1444 FSOUND_3D_SetMinMaxDistance( iChannelHandle, pSound->m_fMinDist, 10000.0f );
1445 FSOUND_3D_SetAttributes( iChannelHandle, aPos, TNULL );
1446 }
1447 else
1448 {
1449 FSOUND_SetPan( iChannelHandle, 128 );
1450 }
1451
1452 if ( !HASANYFLAG( pChannelRef->iFlags, 1 ) )
1453 {
1454 FSOUND_SetPaused( iChannelHandle, TFALSE );
1455 }
1456 else if ( pCue->oEventList.IsLinked() )
1457 {
1458 pCue->oEventList.Remove();
1459 }
1460
1461 pSound->m_iFlags |= 32;
1462 pChannelRef->iFlags |= 32;
1463
1464 ASoundManager* pSoundManager = ASoundManager::GetSingleton();
1465
1466 T2_FOREACH( pCue->aChannelRefsLegacy[ 0 ], it )
1467 {
1468 it->fnCallback( 0, GetCueIndex( pCue ), it->pUserData );
1469 }
1470
1471 TINT iTrackIndex = a_pEvent->iTrackIndex;
1472
1473 if ( iTrackIndex != -1 )
1474 {
1475 TINT iLoopStart = pCue->vecLoopStarts[ iTrackIndex ];
1476
1477 if ( iLoopStart == -1 )
1478 {
1479 TINT iFirstWave = pSound->GetFirstWaveForTrack( iTrackIndex );
1480
1481 // Remove channel refs which has finished playing
1482 T2_FOREACH( pCue->oChannelRefs, it )
1483 {
1484 if ( !FSOUND_IsPlaying( it->iFMODChannelHandle ) )
1485 {
1486 // NOTE: Seems to be a bug that presents in the original game.
1487 // Erase returns next node after removed one so it will be skipped
1488 // since the code just overrides current iterator
1489 it = pCue->oChannelRefs.Erase( it );
1490 m_ChannelRefPool.FreeObject( it );
1491 }
1492 }
1493
1494 CreatePlaySoundEvent(
1495 pCue,
1496 iTrackIndex,
1497 iFirstWave,
1498 pSound->m_vecTracks[ iTrackIndex ] + iFirstWave,
1499 a_pEvent->iFlags,
1500 0.0f,
1501 pChannelRef->pSample->pWaveBank->GetWave( pChannelRef->pSample->iId )->fLength
1502 );
1503 }
1504
1505 if ( iLoopStart > 0 )
1506 {
1507 pCue->vecLoopStarts[ iTrackIndex ] -= 1;
1508 TINT iFirstWave = pSound->GetFirstWaveForTrack( iTrackIndex );
1509
1510 CreatePlaySoundEvent(
1511 pCue,
1512 iTrackIndex,
1513 iFirstWave,
1514 pSound->m_vecTracks[ iTrackIndex ] + iFirstWave,
1515 a_pEvent->iFlags,
1516 0.0f,
1517 pChannelRef->pSample->pWaveBank->GetWave( pChannelRef->pSample->iId )->fLength
1518 );
1519 }
1520 }
1521 }
1522 else
1523 {
1524 // Error occured while playing
1525 TASSERT( !"Couldn't play sound sample" );
1526 pCue->Reset();
1527 }
1528 }
1529}
1530
1531void ASoundManager::EventHandler_PlayStream( SoundEvent* a_pEvent )
1532{
1533 TVALIDPTR( a_pEvent );
1534 TASSERT( TTRUE == m_ChannelRefPool.CanAllocate() );
1535
1536 Cue* pCue = a_pEvent->pCue;
1537 ASound* pSound = pCue->pSound;
1538
1539 if ( pSound && m_ChannelRefPool.CanAllocate() )
1540 {
1541 // Allocate new ChannelRef object from the pool
1542 ChannelRef* pChannelRef = m_ChannelRefPool.NewObject();
1543
1544 // Push the channelref to the cue
1545 pCue->iNumChannelRefs += 1;
1546 pCue->oChannelRefs.PushBack( pChannelRef );
1547
1548 TFLOAT fCategoryVolume = m_aCategories[ pCue->pSound->m_uiCategoryIndex ].fVolumeMultiplier;
1549
1550 pChannelRef->pSample = a_pEvent->pSample;
1551 pChannelRef->fVolume = fCategoryVolume * pCue->fVolume * a_pEvent->oParameters[ 0 ];
1552 TMath::Clip( pChannelRef->fVolume, 0.0f, 1.0f );
1553
1554 ASound::Sample* pWave = pChannelRef->pSample;
1555 pChannelRef->iFlags = a_pEvent->iFlags & ( ~32 );
1556 pChannelRef->iFrequency = TINT( pWave->iFrequency * a_pEvent->oParameters[ 1 ] );
1557
1558 TASSERT( TTRUE == m_StreamRefPool.CanAllocate() );
1559
1560 if ( m_StreamRefPool.CanAllocate() )
1561 {
1562 StreamRef* pStreamRef = m_StreamRefPool.NewObject();
1563 pStreamRef->pChannelRef = pChannelRef;
1564 pStreamRef->pCue = pCue;
1565
1566 pChannelRef->iFMODChannelHandle = -1;
1567 m_StreamRefs.PushBack( pStreamRef );
1568 }
1569 }
1570}
1571
1572void ASoundManager::EventHandler_StopAudio( SoundEvent* a_pEvent )
1573{
1574 TVALIDPTR( a_pEvent );
1575
1576 Cue* pCue = a_pEvent->pCue;
1577 ASound* pSound = pCue->pSound;
1578
1579 if ( pSound )
1580 {
1581 ChannelRef* pChannel = a_pEvent->pChannel;
1582 TBOOL bReserved = FSOUND_GetReserved( pChannel->iFMODChannelHandle );
1583
1584 if ( bReserved )
1585 FSOUND_SetReserved( pChannel->iFMODChannelHandle, TFALSE );
1586
1587 FSOUND_StopSound( pChannel->iFMODChannelHandle );
1588
1589 if ( pSound->m_iFlags & 0x10 )
1590 {
1591 FSOUND_STREAM* pStreamHandle = (FSOUND_STREAM*)pChannel->pSample->pWaveBank->GetWave( pChannel->pSample->iId )->pSampleHandle;
1592 FSOUND_Stream_Stop( pStreamHandle );
1593 }
1594
1595 pChannel->pSample->pWaveBank->ResetWave( pChannel->pSample->iId );
1596 pCue->iNumChannelRefs -= 1;
1597
1598 pChannel->Remove();
1599 m_ChannelRefPool.DeleteObject( pChannel );
1600 }
1601}
1602
1603void ASoundManager::EventHandler_UpdateChannelVolume( SoundEvent* a_pEvent )
1604{
1605 TVALIDPTR( a_pEvent );
1606
1607 Cue* pCue = a_pEvent->pCue;
1608 ASound* pSound = pCue->pSound;
1609
1610 if ( pSound )
1611 {
1612 ChannelRef* pChannel = a_pEvent->pChannel;
1613
1614 pChannel->fVolume = m_aCategories[ pSound->m_uiCategoryIndex ].fVolumeMultiplier * pChannel->pSample->fVolume * a_pEvent->oParameters[ 0 ];
1615 TMath::Clip( pChannel->fVolume, 0.0f, 1.0f );
1616
1617 pCue->fVolume = a_pEvent->oParameters[ 0 ];
1618
1619 FSOUND_SetVolume( pChannel->iFMODChannelHandle, ( !m_bMuted ) ? TINT( pChannel->fVolume * 255.0f ) : 0 );
1620 }
1621}
1622
1623void ASoundManager::EventHandler_UpdateChannelFrequency( SoundEvent* a_pEvent )
1624{
1625 TVALIDPTR( a_pEvent );
1626
1627 Cue* pCue = a_pEvent->pCue;
1628 ASound* pSound = pCue->pSound;
1629
1630 if ( pSound )
1631 {
1632 ChannelRef* pChannel = a_pEvent->pChannel;
1633
1634 pChannel->iFrequency = TINT( a_pEvent->pSample->iFrequency * pCue->fFrequency * a_pEvent->oParameters[ 0 ] );
1635 FSOUND_SetFrequency( pChannel->iFMODChannelHandle, pChannel->iFrequency );
1636 }
1637}
1638
1639void ASoundManager::EventHandler_UpdatePosition( SoundEvent* a_pEvent )
1640{
1641 TVALIDPTR( a_pEvent );
1642
1643 Cue* pCue = a_pEvent->pCue;
1644 ASound* pSound = pCue->pSound;
1645
1646 if ( pSound )
1647 {
1648 ChannelRef* pChannel = a_pEvent->pChannel;
1649
1650 FSOUND_3D_SetAttributes( pChannel->iFMODChannelHandle, a_pEvent->oParameters.aParams, TNULL );
1651 }
1652}
1653
1655{
1656
1657 bUsed = TFALSE;
1658 pSound = TNULL;
1659 fStartTime = 0.0f;
1660 fStartTime2 = 0.0f;
1662 fVolume = 1.0f;
1663 fFrequency = 1.0f;
1664 oEventList = new ( AMemory::GetMemBlock( AMemory::POOL_Sound ) ) SoundEventList::Type();
1665}
1666
1668{
1669 if ( oEventList.GetNodeValue() )
1670 delete oEventList.GetNodeValue();
1671}
1672
1674{
1675 ASoundManager* pSoundManager = ASoundManager::GetSingleton();
1676
1677 T2_FOREACH( aChannelRefsLegacy[ 1 ], it )
1678 {
1679 it->fnCallback( 1, GetCueIndex( this ), it->pUserData );
1680 }
1681
1682 bUsed = TFALSE;
1683 fStartTime = -1.0f;
1684 fStartTime2 = -1.0f;
1685 pSound = TNULL;
1686
1687 // Reset waves used by the channel refs
1688 T2_FOREACH( oChannelRefs, channelRef )
1689 {
1690 channelRef->pSample->pWaveBank->ResetWave( channelRef->pSample->iId );
1691 }
1692
1693 // Delete allocated sound events
1694 while ( !oEventList->IsEmpty() )
1695 {
1696 SoundEvent* pSoundEvent = oEventList->PopFront();
1697 pSoundManager->m_SoundEventPool.FreeObject( pSoundEvent );
1698 }
1699
1700 if ( oEventList.IsLinked() )
1701 oEventList.Remove();
1702
1703 // Delete all channel refs of Type2
1704 for ( TINT i = 0; i < TARRAYSIZE( aChannelRefsLegacy ); i++ )
1705 {
1706 while ( !aChannelRefsLegacy[ i ].IsEmpty() )
1707 {
1708 ChannelRefLegacy* pChannelRef = aChannelRefsLegacy[ i ].PopFront();
1709 pSoundManager->m_ChannelRefLegacyPool.DeleteObject( pChannelRef );
1710 }
1711 }
1712
1713 iNumChannelRefs = 0;
1714
1715 while ( !oChannelRefs.IsEmpty() )
1716 {
1717 ChannelRef* pChannelRef = oChannelRefs.PopFront();
1718 pSoundManager->m_ChannelRefPool.DeleteObject( pChannelRef );
1719 }
1720
1721 vecLoopStarts.Clear();
1722
1723 if ( IsLinked() )
1724 Remove();
1725}
1726
1728{
1729 T2_FOREACH( *oEventList.GetNodeValue(), it )
1730 {
1731 if ( it->eEventType == a_eEventType )
1732 return TTRUE;
1733 }
1734
1735 return TFALSE;
1736}
1737
1738ASoundManager::SoundEvent::SoundEvent( SOUNDEVENT a_eEventType, TFLOAT a_fStartTime, Cue* a_pCue, ASound::Sample* a_pWave, ChannelRef* a_pChannel, TINT a_iFlags, TINT a_iTrackIndex )
1739 : pSample( a_pWave ), eEventType( a_eEventType ), pChannel( a_pChannel ), iFlags( a_iFlags ), pCue( a_pCue ), fStartTime( a_fStartTime ), iTrackIndex( a_iTrackIndex )
1740{
1741}
1742
1743ASoundManager::SoundEvent::SoundEvent( SOUNDEVENT a_eEventType, TFLOAT a_fStartTime, Cue* a_pCue, ASound::Sample* a_pWave, TFLOAT a_fCustomParam1, ChannelRef* a_pChannel, TINT a_iFlags, TINT a_iTrackIndex )
1744 : pSample( a_pWave ), eEventType( a_eEventType ), pChannel( a_pChannel ), iFlags( a_iFlags ), pCue( a_pCue ), fStartTime( a_fStartTime ), iTrackIndex( a_iTrackIndex )
1745{
1746 oParameters[ 0 ] = a_fCustomParam1;
1747}
1748
1749ASoundManager::SoundEvent::SoundEvent( SOUNDEVENT a_eEventType, TFLOAT a_fStartTime, Cue* a_pCue, ASound::Sample* a_pWave, const EventParameters& a_rcCustomParams, ChannelRef* a_pChannel, TINT a_iFlags, TINT a_iTrackIndex )
1750 : pSample( a_pWave ), eEventType( a_eEventType ), pChannel( a_pChannel ), iFlags( a_iFlags ), pCue( a_pCue ), fStartTime( a_fStartTime ), iTrackIndex( a_iTrackIndex ), oParameters( a_rcCustomParams )
1751{
1752}
1753
1754void ASoundManager::SoundEventManager::SetEventHandler( SOUNDEVENT a_eEventType, EventHandler::Callback_t a_fnHandler )
1755{
1756 TASSERT( a_eEventType >= 0 && a_eEventType < SOUNDEVENT_NUMOF );
1757 m_aEventHandlers[ a_eEventType ].Unused = 0;
1758 m_aEventHandlers[ a_eEventType ].fnCallback = a_fnHandler;
1759}
1760
1762{
1763 TASSERT( a_eEventType >= 0 && a_eEventType < SOUNDEVENT_NUMOF );
1764
1765 EventHandler::Callback_t fnEventCallback = m_aEventHandlers[ a_eEventType ].fnCallback;
1766
1767 TASSERT( fnEventCallback != TNULL );
1768
1769 // Execute event callback
1770 ( a_pSoundManager->*fnEventCallback )( a_pEvent );
1771}
@ BASISVECTOR_TRANSLATION
Definition TMatrix44.h:28
@ BASISVECTOR_UP
Definition TMatrix44.h:26
@ BASISVECTOR_FORWARD
Definition TMatrix44.h:27
#define TIMPLEMENT()
Definition Defines.h:136
#define TASSERT(X,...)
Definition Defines.h:138
#define TERROR(...)
Definition Defines.h:153
#define TOFFSETOF(CLASS, MEMBER)
Definition Defines.h:71
#define HASANYFLAG(STATE, FLAG)
Definition Defines.h:5
#define TREINTERPRETCAST(TYPE, VALUE)
Definition Defines.h:68
#define TOSHI_NAMESPACE_USING
Definition Defines.h:46
#define TINFO(...)
Definition Defines.h:151
#define TTODO(DESC)
Definition Defines.h:134
#define TARRAYSIZE(ARRAY)
Definition Defines.h:70
#define TVALIDPTR(PTR)
Definition Defines.h:139
#define T2_FOREACH(vecName, iteratorName)
Definition T2Iterator.h:4
#define TDEFINE_CLASS(...)
Definition TObject.h:120
#define TPSTRING8_DECLARE(STR)
Definition TPString8.h:15
#define TPS8(STR)
Definition TPString8.h:16
unsigned int TUINT
Definition Typedefs.h:8
uintptr_t TUINTPTR
Definition Typedefs.h:18
char TCHAR
Definition Typedefs.h:20
float TFLOAT
Definition Typedefs.h:4
#define TNULL
Definition Typedefs.h:23
int TINT
Definition Typedefs.h:7
#define TFALSE
Definition Typedefs.h:24
#define TTRUE
Definition Typedefs.h:25
bool TBOOL
Definition Typedefs.h:6
ALoadScreen g_oLoadScreen
@ AAssetType_WaveBank
Definition AAssetLoader.h:9
TINT32 ASoundId
Definition ASoundLegacy.h:5
#define ASOUNDID_INVALID
Definition ASoundLegacy.h:3
#define MAX_NUM_STREAMS
#define MAX_NUM_SOUND_EVENTS
#define ASOUNDMANAGER_MAX_NUM_CUE
TSystemManager g_oSystemManager
Definition TSystem.cpp:15
TFORCEINLINE void Clip(T &rVal, const T &Min, const T &Max)
TFORCEINLINE TINT Round(TFLOAT a_fVal)
Definition TMathInline.h:97
TFileSystem * FindFileSystem(const TString8 &name)
void DeleteSymbolTable()
Definition TTRB.cpp:319
ERROR Load(const TCHAR *a_szFilePath, TUINT32 a_uiUnknown=0)
Definition TTRB.cpp:38
@ ERROR_OK
Definition TTRB.h:258
TUINT8 ERROR
Definition TTRB.h:255
TFLOAT GetFloat()
Definition TRandom.cpp:183
TFLOAT GetFloatMinMax(TFLOAT a_fLower, TFLOAT a_fUpper)
Definition TRandom.cpp:189
static const constinit TVector4 VEC_ZERO
Definition TVector4.h:358
const class PBProperties * GetProperties() const
void * GetRaw() const
TINT GetInteger() const
TFLOAT GetFloat() const
PBPropertyValue * GetValue(TSIZE a_iIndex)
TUINT32 GetSize() const
PBProperty * Begin()
static constexpr const TCHAR * TRB_SECTION_NAME
const PBPropertyValue * GetProperty(const TCHAR *a_szName) const
TBOOL GetOptionalPropertyValue(T &a_rOutValue, const TCHAR *a_szName) const
PBPropertyValue * GetValue()
TFORCEINLINE const TString8 & GetString8() const
Definition TPString8.h:172
TFORCEINLINE const TPooledString8 * GetPooledString() const
Definition TPString8.h:177
TFORCEINLINE TBOOL IsEmpty() const
Definition TPString8.h:182
TFORCEINLINE const TCHAR * GetString() const
Definition TPString8.h:167
static TFORCEINLINE TFileManager * GetSingleton()
Definition TSingleton.h:49
TString8 & MakeLower()
Definition TString8.h:87
TINT Compare(const TCHAR *a_szString, TINT a_iLength=-1) const
Definition TString8.cpp:362
TINT Length() const
Definition TString8.h:93
const TCHAR * GetString(TINT a_iIndex=0) const
Definition TString8.cpp:286
void Update(TFLOAT a_fDeltaTime=1.0f, TBOOL a_bRender=true)
static TBOOL Load(const TCHAR *a_szFileName, AAssetType a_eAssetType, TBOOL a_bStream)
static void Close(AAssetType a_eAssetType)
static T * CastSymbol(const TCHAR *a_szFileName, const TCHAR *a_szSymbolName, AAssetType a_eAssetType)
Toshi::TMatrix44 & GetMatrix()
Definition ACamera.cpp:58
@ POOL_Sound
Definition AMemory.h:37
static Toshi::TMemory::MemBlock * GetMemBlock(POOL a_ePool)
Definition AMemory.cpp:38
TINT GetRandomSample(TINT a_iWaveIndexMin, TINT a_iWaveIndexMax)
Definition ASound.cpp:26
TINT GetFirstWaveForTrack(TINT a_iTrack) const
Definition ASound.cpp:17
TINT GetRandomSampleWeighted(TINT a_iTrackIndex, TINT a_iWaveIndexMin, TINT a_iWaveIndexMax)
Definition ASound.cpp:31
TFLOAT fMinPitch
Definition ASound.h:25
TFLOAT fVolume
Definition ASound.h:21
TFLOAT fVarDelay
Definition ASound.h:29
TFLOAT fMinVolumeMultiplier
Definition ASound.h:22
TFLOAT fMaxPitch
Definition ASound.h:26
TFLOAT fMaxVolumeMultiplier
Definition ASound.h:23
TINT iFrequency
Definition ASound.h:27
TFLOAT fStart
Definition ASound.h:28
AWaveBank * pWaveBank
Definition ASound.h:19
void Load()
Definition ASoundBank.h:27
Toshi::T2DListNodeWrapper< Toshi::T2SortedList< SoundEvent, Toshi::T2DList< SoundEvent >, SoundEventSortResults > > SoundEventList
virtual TBOOL OnCreate() override
void CancelCueEvents(Cue *a_pCue, SOUNDEVENT a_eEventType)
TINT GetAvailableCueIndex()
TBOOL LoadWaveBankSamples(const Toshi::TPString8 &a_rcName, AWaveBank::LOADFLAGS a_eLoadFlags, TINT a_iBufferSize)
TINT PlayCueEx(ASoundId a_iSound, TFLOAT a_fVolume, TBOOL a_bFlag, TFLOAT a_fDelay, TINT a_iTrack)
AWaveBank * FindWaveBank(const Toshi::TPString8 &a_rcName)
virtual TBOOL OnUpdate(TFLOAT a_fDeltaTime) override
virtual void OnDestroy() override
ASoundBank * FindSoundBank(const Toshi::TPString8 &a_rcName)
static constexpr const TCHAR * SOUNDS_BASE_DIRECTORY
TBOOL IsCuePlaying(TINT a_iCueIndex)
void LoadSoundBankSamples(const Toshi::TPString8 &a_rcName)
void StopCue(TINT &a_rCueIndex)
void StopCueAsync(TINT &a_rCueIndex, TFLOAT a_fDelay)
TBOOL LoadSoundBank(const Toshi::TPString8 &a_rcName, TBOOL a_bSimpleSound, TBOOL a_bLoadImmediately)
TINT PlayCue(ASoundId a_iSound)
virtual TBOOL Reset() override
TBOOL LoadWaveBanksInfo(const TCHAR *a_szFileName)
void PauseAllCues(TBOOL a_bPause)
ASound::Sample * pSample
SoundEvent(SOUNDEVENT a_eEventType, TFLOAT a_fStartTime, Cue *a_pCue, ASound::Sample *a_pWave, ChannelRef *a_pChannel, TINT a_iFlags, TINT a_iTrackIndex)
EventParameters oParameters
Toshi::TVector4 vecPosition
TBOOL IsUsed() const
Toshi::T2DList< ChannelRef > oChannelRefs
Toshi::T2DList< ChannelRefLegacy > aChannelRefsLegacy[2]
SoundEventList oEventList
TBOOL HasEventOfType(SOUNDEVENT a_eEventType) const
Toshi::T2Vector< TINT, 15 > vecLoopStarts
void SetEventHandler(SOUNDEVENT a_eEventType, EventHandler::Callback_t a_fnHandler)
void ExecuteEvent(SOUNDEVENT a_eEventType, ASoundManager *a_pSoundManager, SoundEvent *a_pEvent)
AWaveSampleHandle pSampleHandle
Definition AWave.h:18
virtual LOADRESULT Load(LOADFLAGS a_uiFlags, TINT a_iBufferSize)=0
TUINT32 LOADFLAGS
Definition AWaveBank.h:13
AWaveSampleHandle CreateWaveSample(TINT a_iWaveIndex, TINT a_iUnused)
Definition AWaveBank.cpp:65
void SetWaveFlag1(TINT a_iWaveIndex)
Definition AWaveBank.cpp:77
@ LOADRESULT_OK
Definition AWaveBank.h:23
@ LOADFLAGS_LOCALISE
Definition AWaveBank.h:17
@ LOADFLAGS_NONE
Definition AWaveBank.h:16
TINT GetWaveId(TINT a_iWaveIndex)
Definition AWaveBank.cpp:53
void ParseWavesData(const PBProperties *a_pBankProperties, TUINT a_uiForcedFlags)
Definition AWaveBank.cpp:91
AWave * GetWave(TINT a_iWaveIndex)
Definition AWaveBank.cpp:47
void SetWaveFlag2(TINT a_iWaveIndex)
Definition AWaveBank.cpp:84