28#define MAX_NUM_SOUND_EVENTS 256
29#define MAX_NUM_STREAMS 64
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 ) )
35 m_iLastAvailableSoundExSlot = -1;
36 m_fCurrentTime = 0.0f;
39 m_bUseMinHardwareChannels =
TTRUE;
40 m_iMinHWChannels = 32;
42 m_iGlobalFrequency = 22050;
59 m_PauseListener.Disconnect();
72 m_PauseListener.Connect(
76 a_pSndMngr->PauseAllCues( *a_pPaused );
84 for (
TINT i = 0; i < 32; i++ )
86 m_FreeListS4.PushBack( &m_pS4[ i ] );
91 m_FreeListS2.PushBack( &m_aS2[ i ] );
100 m_fCurrentTime += a_fDeltaTime;
104 if ( ARootTask::GetSingleton()->IsPaused() && ms_iNumPauses <= 0 )
108 else if ( !ARootTask::GetSingleton()->IsPaused() && ms_iNumPauses > 0 )
114 TTODO(
"FUN_005db310" );
117 while ( !m_QueuedSortedEventLists.IsEmpty() )
123 if ( pEarliestEvent->
fStartTime > m_fCurrentTime )
129 pEarliestEvent->Remove();
130 m_oEventManager.ExecuteEvent( pEarliestEvent->
eEventType,
this, pEarliestEvent );
133 m_SoundEventPool.DeleteObject( pEarliestEvent );
135 if ( !eventList.IsLinked() )
139 if ( eventList->IsEmpty() )
148 pEarliestEvent = eventList->Front();
150 if ( pEarliestEvent->
fStartTime > m_fCurrentTime )
156 m_QueuedSortedEventLists.ReInsert( eventList );
163 for (
auto pStream = m_StreamRefs.Begin(); pStream != m_StreamRefs.End(); )
165 if ( ( pStream->pUnknown && UpdateStreamActivity( pStream ) ) ||
166 ( pStream->pCue && UpdateStreamCue( pStream ) ) )
168 auto itNext = m_StreamRefs.Erase( pStream );
169 m_StreamRefPool.DeleteObject( pStream );
175 pStream = pStream.Next();
182 TFLOAT fCueStartTime = m_aCues[ i ].fStartTime;
186 m_aCues[ i ].Reset();
194 if ( ARootTask::GetSingleton()->IsGameSystemCreated() &&
TTRUE )
196 ACamera* pCamera = ACameraManager::GetSingleton()->GetCurrentCamera();
203 m_oCameraData.Forward.w = 1.0f;
207 m_oCameraData.Up.w = 1.0f;
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;
215 aPosition[ 0 ] = m_oCameraData.Position.x;
216 aPosition[ 1 ] = m_oCameraData.Position.y;
217 aPosition[ 2 ] = m_oCameraData.Position.z;
220 aVelocity[ 0 ] = m_oCameraData.Velocity.x;
221 aVelocity[ 1 ] = m_oCameraData.Velocity.y;
222 aVelocity[ 2 ] = m_oCameraData.Velocity.z;
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 );
234 m_FreeListS4.Clear();
237 m_PauseListener.Disconnect();
251 auto pFoundNode = m_SoundIdToSound.Find( a_iSound );
253 if ( !m_SoundIdToSound.IsValid( pFoundNode ) )
257 ASound* pSound = pFoundNode->GetSecond();
260 if ( pSound->m_vecSamples.Size() == 0 )
266 if ( iCueIndex == -1 )
269 Cue* pCue = &m_aCues[ iCueIndex ];
273 m_aCategories[ pSound->m_uiCategoryIndex ].PlayingCues.PushBack( pCue );
275 TINT iFlags = pSound->m_iFlags;
284 pCue->
fVolume = ( a_fVolume > 1.0f ) ? 1.0f : a_fVolume;
289 TINT iSoundNumTracks = pSound->m_vecTracks.Size();
291 if ( a_iTrack == -1 )
295 if ( iSoundNumTracks > 0 )
297 TINT iFirstWaveIndex = 0;
299 for (
TINT iTrack = 0; iTrack < iSoundNumTracks; iTrack++ )
301 if ( pSound->m_TrackLoop.GetBit( iTrack ) != 0 )
306 CreatePlaySoundEvent(
310 pSound->m_vecTracks[ iTrack ] + iFirstWaveIndex,
316 iFirstWaveIndex += pSound->m_vecTracks[ iTrack ];
326 if ( pSound->m_TrackLoop.GetBit( a_iTrack ) != 0 )
331 CreatePlaySoundEvent(
335 pSound->m_vecTracks[ a_iTrack ] + iFirstWaveIndex,
356 for ( iSlot = m_iLastAvailableSoundExSlot + 1;; iSlot++ )
361 if ( iSlot == m_iLastAvailableSoundExSlot )
364 if ( m_aCues[ iSlot ].fStartTime <= 0.0 )
369 if ( !m_aCues[ iSlot ].bUsed )
374 m_iLastAvailableSoundExSlot = iSlot;
382 if ( a_iCueIndex == -1 )
385 Cue* pCue = &m_aCues[ a_iCueIndex ];
394 if ( pSound->m_iFlags & 16 )
399 if ( !( channel->iFlags & 0x20 ) || FSOUND_IsPlaying( channel->iFMODChannelHandle ) )
410 if ( FSOUND_IsPlaying( channel->iFMODChannelHandle ) )
423 if ( a_rCueIndex == -1 )
427 Cue* pCue = &m_aCues[ a_rCueIndex ];
432 if ( a_fDelay != 0.0f && pCue->
oChannelRefs.Size() == 0 )
443 if ( channel->iFMODChannelHandle == -1 )
459 auto itNext = it.Next();
461 if ( it->eEventType == a_eEventType )
464 m_SoundEventPool.DeleteObject( it );
473 auto pFoundNode = ms_WaveBanks.Find( a_rcName );
475 return ( ms_WaveBanks.IsValid( pFoundNode ) ) ? pFoundNode->GetSecond() :
TNULL;
478AWaveBank* ASoundManager::LoadWaveBankFromAsset(
const Toshi::TString8& a_strName,
TUINT a_uiForcedFlags )
482 strBankFileName += a_strName;
499 auto pExistingWaveBank = ms_WaveBanks.Find( strWaveWankBankName );
500 auto pWaveBankVersionVal = pBankProperties->
GetProperty(
"version" );
503 auto pWaveBankLibraryVal = pBankProperties->
GetProperty(
"library" );
504 TPString8 strWaveBankLibrary = ( pWaveBankLibraryVal ) ? pWaveBankLibraryVal->GetTPString8() :
TPString8();
507 auto pWaveBankTypeVal = pBankProperties->
GetProperty(
"type" );
508 TPString8 strWaveBankType = ( pWaveBankTypeVal ) ? pWaveBankTypeVal->GetTPString8() :
TPString8();
511 auto pWaveBankPathVal = pBankProperties->
GetProperty(
"path" );
512 TPString8 strWaveBankPath = ( pWaveBankPathVal ) ? pWaveBankPathVal->GetTPString8() :
TPString8();
515 auto pWaveBankExtensionVal = pBankProperties->
GetProperty(
"extension" );
516 TPString8 strWaveBankExtension = ( pWaveBankExtensionVal ) ? pWaveBankExtensionVal->GetTPString8() :
TPString8();
519 AWaveBank* pWaveBank = AllocateWaveBank( strWaveWankBankName, strWaveBankLibrary, strWaveBankType, strWaveBankPath );
526AWaveBank* ASoundManager::AllocateWaveBank(
const Toshi::TPString8& a_strBank,
const Toshi::TPString8& a_strLibrary,
const Toshi::TPString8& a_strType,
const Toshi::TPString8& a_strPath )
529 if ( a_strLibrary != TPString8(
"FMOD" ) || a_strType == TPString8(
"Dir" ) )
531 TASSERT( !
"Trying to load an unknown non-FSB WaveBank format!" );
535 if ( a_strType == TPString8(
"File" ) )
538 return new AWaveBankFMODFSB( a_strBank, a_strPath );
540 else if ( a_strType == TPString8(
"Stream" ) )
543 return new AWaveBankFMODFSBStream( a_strBank, a_strPath );
549TBOOL ASoundManager::LoadSoundBankImpl(
const TCHAR* a_szName,
TBOOL a_bSimpleSound,
TBOOL a_bLoadImmediately )
554 strFileName +=
"soundbank_";
555 strFileName += a_szName;
556 strFileName +=
".trb";
567 auto& rcProperties = *PBProperties::LoadFromTRB( trb );
576 const PBProperties* pSoundsProperties = soundbank->GetValue()->GetProperties();
581 if ( !bHasNumSounds )
583 TASSERT( !
"Invalid format of the soundbank property" );
587 if ( iNumSounds == 0 )
594 m_SoundBanks.PushBack( pSoundBank );
596 if ( a_bSimpleSound )
610 TINT iSoundIndex = 0;
614 if ( it->GetName().GetString()[ 0 ] !=
'S' )
617 auto pSoundProperties = it->GetValue()->GetProperties();
620 pSoundProperties->GetOptionalPropertyValue( iSoundId,
"id" );
622 if ( a_bSimpleSound )
625 ASoundLegacy* pSound = &pSoundBank->m_pSounds[ iSoundIndex++ ];
627 pSound->m_iId = iSoundId;
628 m_SoundIdToSoundLegacy.Insert( iSoundId, pSound );
630 if ( !pSoundProperties->GetOptionalPropertyValue( pSound->m_iFlags,
"flags" ) )
633 TASSERT( !
"No flags property specified in the soundbank" );
636 PBPropertyValueArray* pBanks =
TNULL;
637 if ( !pSoundProperties->GetOptionalPropertyValue( pBanks,
"banks" ) )
640 TASSERT( !
"No banks property specified in the soundbank" );
644 PBPropertyValueArray* pWaves;
645 if ( bNoErrors && pSoundProperties->GetOptionalPropertyValue( pWaves,
"waves" ) )
650 TPString8 strSoundBankName = pBanks->
GetValue( 0 )->GetTPString8();
653 if ( a_bLoadImmediately )
658 pSound->m_pWaveBank = pWaveBank;
665 ASound* pSoundEx = &pSoundBank->m_pSoundsEx[ iSoundIndex++ ];
667 pSoundEx->m_iId = iSoundId;
668 m_SoundIdToSound.Insert( iSoundId, pSoundEx );
671 TPString8 strCategory;
672 if ( bNoErrors && pSoundProperties->GetOptionalPropertyValue( strCategory,
"category" ) )
677 auto pFoundCategory = m_CategoryIndices.Find(
681 TASSERT( m_CategoryIndices.IsValid( pFoundCategory ) );
682 pSoundEx->m_uiCategoryIndex = pFoundCategory->GetSecond();
685 if ( pSoundProperties->GetOptionalPropertyValue( pSoundEx->m_iFlags,
"flags" ) )
688 pSoundProperties->GetOptionalPropertyValue( pSoundEx->m_fMinDist,
"mindist" );
689 pSoundProperties->GetOptionalPropertyValue( pSoundEx->m_ui8Priority,
"priority" );
692 PBPropertyValueArray* pBanks;
693 PBPropertyValueArray* pWaves;
696 if ( pSoundProperties->GetOptionalPropertyValue( pBanks,
"banks" ) &&
697 pSoundProperties->GetOptionalPropertyValue( pWaves,
"waves" ) )
699 pSoundEx->m_vecSamples.Reserve( pBanks->
GetSize() );
704 TPString8 strWaveBankName = pBanks->
GetValue( i )->GetTPString8();
708 if ( a_bLoadImmediately && !strWaveBankName.
IsEmpty() && pWaveBank )
713 if ( pWaveBank !=
TNULL )
715 ASound::Sample oWave;
719 pSoundEx->m_vecSamples.PushBack( oWave );
721 if ( pSoundEx->m_iFlags & 4 )
733 PBPropertyValueArray* pVolumes;
734 if ( bNoErrors && pSoundProperties->GetOptionalPropertyValue( pVolumes,
"volumes" ) )
739 pSoundEx->m_vecSamples[ i ].fVolume = fVolume;
744 TASSERT( !
"Error while parsing sound settings" );
750 PBPropertyValueArray* pVolrand;
751 if ( pSoundProperties->GetOptionalPropertyValue( pVolrand,
"volrand" ) )
758 pSoundEx->m_vecSamples[ i / 2 ].fMinVolumeMultiplier = fVolMin;
759 pSoundEx->m_vecSamples[ i / 2 ].fMaxVolumeMultiplier = fVolMax;
764 TASSERT( !
"Error while parsing sound settings" );
770 PBPropertyValueArray* pPitches;
771 if ( pSoundProperties->GetOptionalPropertyValue( pPitches,
"pitches" ) )
776 pSoundEx->m_vecSamples[ i ].fPitch = fPitch;
781 TASSERT( !
"Error while parsing sound settings" );
787 PBPropertyValueArray* pPitchrand;
788 if ( pSoundProperties->GetOptionalPropertyValue( pPitchrand,
"pitchrand" ) )
795 pSoundEx->m_vecSamples[ i / 2 ].fMinPitch = fPitchMin;
796 pSoundEx->m_vecSamples[ i / 2 ].fMaxPitch = fPitchMax;
801 TASSERT( !
"Error while parsing sound settings" );
807 PBPropertyValueArray* pStarts;
808 if ( pSoundProperties->GetOptionalPropertyValue( pStarts,
"starts" ) )
813 pSoundEx->m_vecSamples[ i ].fStart = fStart;
818 TASSERT( !
"Error while parsing sound settings" );
824 PBPropertyValueArray* pVarDelays;
825 if ( pSoundProperties->GetOptionalPropertyValue( pVarDelays,
"vardelays" ) )
830 pSoundEx->m_vecSamples[ i ].fVarDelay = fVarDelay;
835 TASSERT( !
"Error while parsing sound settings" );
841 PBPropertyValueArray* pTracks;
842 if ( pSoundProperties->GetOptionalPropertyValue( pTracks,
"tracks" ) )
844 pSoundEx->m_vecTracks.Reserve( pTracks->
GetSize() );
853 TASSERT( !
"Error while parsing sound settings" );
859 PBPropertyValueArray* pWeights;
860 if ( pSoundProperties->GetOptionalPropertyValue( pWeights,
"weights" ) )
865 pSoundEx->m_vecSamples[ i ].iWeight =
TMath::Round( fWeight );
870 TASSERT( !
"Error while parsing sound settings" );
876 PBPropertyValueArray* pTrackloop;
877 if ( pSoundProperties->GetOptionalPropertyValue( pTrackloop,
"trackloop" ) )
880 pSoundEx->m_TrackLoop.Create( pTrackloop->
GetSize(), 0 );
886 pSoundEx->m_TrackLoop.SetBit( i, 1 );
892 TASSERT( !
"Error while parsing sound settings" );
898 PBPropertyValueArray* pLoopStarts;
899 if ( pSoundProperties->GetOptionalPropertyValue( pLoopStarts,
"loopstarts" ) )
904 pSoundEx->m_vecLoopStarts.PushBack( iLoopStart );
909 TASSERT( !
"Error while parsing sound settings" );
921 if ( a_bLoadImmediately )
926 pSoundBank->Remove();
931 TUINT uiCurrentAlloced;
933 FSOUND_GetMemoryStats( &uiCurrentAlloced, &uiMaxAlloced );
934 TINFO(
"LoadSoundBank result: name=%s; success=%d; currentalloced=%u; maxalloced=%u\n", a_szName, bNoErrors, uiCurrentAlloced, uiMaxAlloced );
939TUINT ASoundManager::GetCueIndex( Cue* a_pCue )
944TBOOL ASoundManager::Initialise()
946 FSOUND_Init( 44100, m_iMinHWChannels + m_iNumChannels, 0 );
948 TINT num2DC, num3DC, numDC;
949 FSOUND_GetNumHWChannels( &num2DC, &num3DC, &numDC );
950 FSOUND_GetMaxChannels();
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 );
971 if ( ms_iNumPauses != 0 )
return;
976 Cue* pCue = &m_aCues[ i ];
978 if ( !pCue->
pSound || !m_aCategories[ pCue->
pSound->m_uiCategoryIndex ].bPausable )
983 if ( !( channel->iFlags & 1 ) )
985 FSOUND_SetPaused( channel->iFMODChannelHandle,
TTRUE );
992 else if ( ms_iNumPauses > 0 && --ms_iNumPauses == 0 )
997 Cue* pCue = &m_aCues[ i ];
999 if ( !pCue->
pSound )
continue;
1003 if ( !( channel->iFlags & 1 ) )
1005 FSOUND_SetPaused( channel->iFMODChannelHandle,
TFALSE );
1015 "Data/Assets/lib_wavebank.trb",
1020 if ( !bOpened )
return TFALSE;
1026 auto pWaveBanksVal = pProperties->
GetProperty(
"Wavebanks" );
1029 auto pWaveBanks = pWaveBanksVal->GetArray();
1031 for (
TUINT i = 0; i < pWaveBanks->GetSize(); i++ )
1033 TPString8 strWaveBankName = pWaveBanks->GetValue( i )->GetTPString8();
1037 LoadWaveBankFromAsset( strWaveBankName.
GetString(), 0 );
1041 auto pCategoriesVal = pProperties->
GetProperty(
"Categories" );
1044 auto pCategories = pCategoriesVal->GetArray();
1046 for (
TUINT i = 0; i < pCategories->GetSize(); i++ )
1048 TPString8 strCategoryName = pCategories->GetValue( i )->GetTPString8();
1050 m_CategoryIndices.Insert( strCategoryName, m_CategoryIndices.Size() );
1060 if ( a_rcName.GetPooledString() && !a_rcName.GetPooledString()->GetString8().IsEmpty() )
1077 if ( it->m_strName == a_rcName )
1086 if ( a_rcName.GetPooledString() && !a_rcName.GetPooledString()->GetString8().IsEmpty() )
1090 return LoadSoundBankImpl( a_rcName, a_bSoundEx, a_bLoadImmediately );
1105void ASoundManager::CreatePlaySoundEvent( Cue* a_pCue,
TINT a_iTrackIndex,
TINT a_iFirstWaveIndex,
TINT a_iLastWaveIndex,
TINT a_iFlags,
TFLOAT a_fDelay1,
TFLOAT a_fDelay2 )
1109 ASound* pSound = a_pCue->pSound;
1112 TINT iFlags = a_iFlags;
1114 TINT iLoopStart = pSound->m_vecLoopStarts[ a_iTrackIndex ];
1115 if ( iLoopStart > 0 || iLoopStart == -1 )
1118 TRandom* pRandom = &ARandom::GetSingleton()->m_oRandom;
1123 TASSERT( a_iFirstWaveIndex <= a_iLastWaveIndex );
1125 if ( pSound->m_vecTracks[ a_iTrackIndex ] < 2 )
1127 TINT iNumLeftWaves = a_iLastWaveIndex - a_iFirstWaveIndex;
1129 for (
TINT i = a_iFirstWaveIndex; iNumLeftWaves > 0; iNumLeftWaves-- )
1137 EventParameters oParams;
1138 oParams[ 0 ] = fVolume;
1140 oParams[ 2 ] = 0.0f;
1143 if ( a_fDelay1 != -1.0f ) fStartDelay += a_fDelay1;
1144 if ( a_fDelay2 != -1.0f ) fStartDelay += a_fDelay2;
1146 SoundEvent* pEvent = CreateSoundEvent(
1165 TINT iSampleIndex = ( a_iFlags < 0 && pSound->m_vecTracks[ a_iTrackIndex ] > 1 ) ?
1169 ASound::Sample* pSample = &pSound->m_vecSamples[ iSampleIndex ];
1176 oParams[ 0 ] = fVolume;
1178 oParams[ 2 ] = 0.0f;
1181 if ( a_fDelay1 != -1.0f ) fStartDelay += a_fDelay1;
1182 if ( a_fDelay2 != -1.0f ) fStartDelay += a_fDelay2;
1202 TASSERT( m_SoundEventPool.CanAllocate() );
1204 if ( m_SoundEventPool.CanAllocate() )
1206 SoundEvent* pEvent = m_SoundEventPool.NewObject( a_eEventType, m_fCurrentTime + a_fDelay, a_pCue, a_pSample, a_pChannel, a_iFlags, a_iTrackIndex );
1209 AddEventToCue( a_pCue, pEvent );
1219 TASSERT( m_SoundEventPool.CanAllocate() );
1221 if ( m_SoundEventPool.CanAllocate() )
1223 SoundEvent* pEvent = m_SoundEventPool.NewObject( a_eEventType, m_fCurrentTime + a_fDelay, a_pCue, a_pSample, a_fCustomParam1, a_pChannel, a_iFlags, a_iTrackIndex );
1226 AddEventToCue( a_pCue, pEvent );
1236 TASSERT( m_SoundEventPool.CanAllocate() );
1238 if ( m_SoundEventPool.CanAllocate() )
1240 SoundEvent* pEvent = m_SoundEventPool.NewObject( a_eEventType, m_fCurrentTime + a_fDelay, a_pCue, a_pSample, a_rcCustomParams, a_pChannel, a_iFlags, a_iTrackIndex );
1243 AddEventToCue( a_pCue, pEvent );
1250void ASoundManager::AddEventToCue( Cue* a_pCue, SoundEvent* a_pSoundEvent )
1255 SoundEvent* pFirstEvent = ( !a_pCue->oEventList->IsEmpty() ) ? a_pCue->oEventList->Begin() :
TNULL;
1256 a_pCue->oEventList->Push( a_pSoundEvent );
1261 if ( pFirstEvent != a_pCue->oEventList->Begin() )
1263 m_QueuedSortedEventLists.ReInsert( a_pCue->oEventList );
1267TBOOL ASoundManager::UpdateStreamActivity( StreamRef* a_pStream )
1269 TASSERT( !
"Not implemented" );
1273TBOOL ASoundManager::UpdateStreamCue( StreamRef* a_pStream )
1277 Cue* pCue = a_pStream->pCue;
1278 ASound* pSound = pCue->pSound;
1282 ChannelRef* pChannel = a_pStream->pChannelRef;
1283 AWaveBank* pWaveBank = pChannel->pSample->pWaveBank;
1284 FSOUND_STREAM* pStreamHandle = (FSOUND_STREAM*)pWaveBank->
CreateWaveSample( pChannel->pSample->iId, 0 );
1286 if ( !( pSound->m_iFlags & 0x40 ) )
1288 TINT iOpenState = FSOUND_Stream_GetOpenState( pStreamHandle );
1290 if ( iOpenState == -2 )
return TFALSE;
1291 FSOUND_Stream_GetNumSubStreams( pStreamHandle );
1292 FSOUND_Stream_SetSubStream( pStreamHandle, pWaveBank->
GetWaveId( pChannel->pSample->iId ) );
1294 pSound->m_iFlags |= 0x40;
1297 TINT iOpenState = FSOUND_Stream_GetOpenState( pStreamHandle );
1299 if ( iOpenState != -1 )
1301 if ( iOpenState == -2 )
1304 if ( iOpenState != -3 )
1306 if ( iOpenState != 0 )
1309 pSound->m_iFlags &= ~0x40;
1311 TINT iChannelHandle = FSOUND_Stream_PlayEx( FSOUND_FREE, pStreamHandle,
TNULL,
TTRUE );
1312 pChannel->iFMODChannelHandle = iChannelHandle;
1313 TASSERT( iChannelHandle != -1 );
1315 if ( iChannelHandle == -1 )
1318 pChannel->iFlags = pChannel->iFlags | 0x20;
1319 pSound->m_iFlags |= 0x20;
1321 TINT iVolume = ( m_bMuted ) ? 0 :
TINT( pChannel->fVolume * 255.0f );
1323 FSOUND_SetVolume( iChannelHandle, iVolume );
1324 FSOUND_SetFrequency( iChannelHandle, pChannel->iFrequency );
1325 FSOUND_SetPriority( iChannelHandle,
TINT( pSound->m_ui8Priority ) );
1327 TINT iStreamMode = FSOUND_Stream_GetMode( pStreamHandle );
1329 if ( pChannel->iFlags & 2 )
1331 iStreamMode = iStreamMode & 0xfffffffa | 2;
1332 FSOUND_SetReserved( iChannelHandle,
TTRUE );
1336 iStreamMode = iStreamMode & 0xfffffff9 | 1;
1339 if ( pChannel->iFlags & 4 )
1340 iStreamMode = iStreamMode & 0xfff7dfff | 0x1000;
1342 iStreamMode = iStreamMode & 0xffffcfff | 0x80000;
1344 FSOUND_Stream_SetMode( pStreamHandle, iStreamMode );
1346 if ( pChannel->iFlags & 4 )
1349 aPos[ 0 ] = ( pCue->vecPosition ).x;
1350 aPos[ 1 ] = ( pCue->vecPosition ).y;
1351 aPos[ 2 ] = -( pCue->vecPosition ).z;
1353 FSOUND_3D_SetMinMaxDistance( iChannelHandle, pSound->m_fMinDist, 10000.0f );
1354 FSOUND_3D_SetAttributes( iChannelHandle, aPos,
TNULL );
1358 FSOUND_SetPan( iChannelHandle, 128 );
1363 FSOUND_SetPaused( iChannelHandle,
TFALSE );
1365 else if ( pCue->oEventList.IsLinked() )
1367 pCue->oEventList.Remove();
1370 T2_FOREACH( pCue->aChannelRefsLegacy[ 0 ], it )
1372 it->fnCallback( 0, GetCueIndex( pCue ), it->pUserData );
1379 pSound->m_iFlags = pSound->m_iFlags & 0xffffffbf;
1386void ASoundManager::EventHandler_PlaySound( SoundEvent* a_pEvent )
1391 Cue* pCue = a_pEvent->pCue;
1392 ASound* pSound = pCue->pSound;
1394 if ( pSound && m_ChannelRefPool.CanAllocate() )
1397 ChannelRef* pChannelRef = m_ChannelRefPool.NewObject();
1400 pCue->iNumChannelRefs += 1;
1401 pCue->oChannelRefs.PushBack( pChannelRef );
1403 TFLOAT fCategoryVolume = m_aCategories[ pCue->pSound->m_uiCategoryIndex ].fVolumeMultiplier;
1405 pChannelRef->
pSample = a_pEvent->pSample;
1406 pChannelRef->
fVolume = fCategoryVolume * pCue->fVolume * a_pEvent->oParameters[ 0 ];
1409 ASound::Sample* pWave = pChannelRef->pSample;
1410 pChannelRef->iFlags = a_pEvent->iFlags;
1411 pChannelRef->iFrequency =
TINT( pWave->
iFrequency * a_pEvent->oParameters[ 1 ] );
1415 TINT iSampleMode = FSOUND_Sample_GetMode( pSample );
1417 if ( pChannelRef->iFlags & 2 )
1418 iSampleMode = iSampleMode & 0xfffffffa | 2;
1420 iSampleMode = iSampleMode & 0xfffffff9 | 1;
1422 FSOUND_Sample_SetMode( pSample, iSampleMode );
1424 TINT iChannelHandle = FSOUND_PlaySoundEx( FSOUND_FREE, pSample,
TNULL,
TTRUE );
1425 pChannelRef->iFMODChannelHandle = iChannelHandle;
1426 TASSERT( iChannelHandle != -1 );
1428 if ( iChannelHandle != -1 )
1431 TINT iVolume = ( m_bMuted ) ? 0 :
TINT( pChannelRef->fVolume * 255.0f );
1433 FSOUND_SetVolume( iChannelHandle, iVolume );
1434 FSOUND_SetFrequency( iChannelHandle, pChannelRef->iFrequency );
1435 FSOUND_SetPriority( iChannelHandle,
TINT( pSound->m_ui8Priority ) );
1437 if ( pChannelRef->iFlags & 4 )
1440 aPos[ 0 ] = ( pCue->vecPosition ).x;
1441 aPos[ 1 ] = ( pCue->vecPosition ).y;
1442 aPos[ 2 ] = -( pCue->vecPosition ).z;
1444 FSOUND_3D_SetMinMaxDistance( iChannelHandle, pSound->m_fMinDist, 10000.0f );
1445 FSOUND_3D_SetAttributes( iChannelHandle, aPos,
TNULL );
1449 FSOUND_SetPan( iChannelHandle, 128 );
1454 FSOUND_SetPaused( iChannelHandle,
TFALSE );
1456 else if ( pCue->oEventList.IsLinked() )
1458 pCue->oEventList.Remove();
1461 pSound->m_iFlags |= 32;
1462 pChannelRef->iFlags |= 32;
1464 ASoundManager* pSoundManager = ASoundManager::GetSingleton();
1466 T2_FOREACH( pCue->aChannelRefsLegacy[ 0 ], it )
1468 it->fnCallback( 0, GetCueIndex( pCue ), it->pUserData );
1471 TINT iTrackIndex = a_pEvent->iTrackIndex;
1473 if ( iTrackIndex != -1 )
1475 TINT iLoopStart = pCue->vecLoopStarts[ iTrackIndex ];
1477 if ( iLoopStart == -1 )
1484 if ( !FSOUND_IsPlaying( it->iFMODChannelHandle ) )
1489 it = pCue->oChannelRefs.Erase( it );
1490 m_ChannelRefPool.FreeObject( it );
1494 CreatePlaySoundEvent(
1498 pSound->m_vecTracks[ iTrackIndex ] + iFirstWave,
1501 pChannelRef->pSample->pWaveBank->GetWave( pChannelRef->pSample->iId )->fLength
1505 if ( iLoopStart > 0 )
1507 pCue->vecLoopStarts[ iTrackIndex ] -= 1;
1510 CreatePlaySoundEvent(
1514 pSound->m_vecTracks[ iTrackIndex ] + iFirstWave,
1517 pChannelRef->pSample->pWaveBank->GetWave( pChannelRef->pSample->iId )->fLength
1525 TASSERT( !
"Couldn't play sound sample" );
1531void ASoundManager::EventHandler_PlayStream( SoundEvent* a_pEvent )
1536 Cue* pCue = a_pEvent->pCue;
1537 ASound* pSound = pCue->pSound;
1539 if ( pSound && m_ChannelRefPool.CanAllocate() )
1542 ChannelRef* pChannelRef = m_ChannelRefPool.NewObject();
1545 pCue->iNumChannelRefs += 1;
1546 pCue->oChannelRefs.PushBack( pChannelRef );
1548 TFLOAT fCategoryVolume = m_aCategories[ pCue->pSound->m_uiCategoryIndex ].fVolumeMultiplier;
1550 pChannelRef->
pSample = a_pEvent->pSample;
1551 pChannelRef->
fVolume = fCategoryVolume * pCue->fVolume * a_pEvent->oParameters[ 0 ];
1554 ASound::Sample* pWave = pChannelRef->pSample;
1555 pChannelRef->iFlags = a_pEvent->iFlags & ( ~32 );
1560 if ( m_StreamRefPool.CanAllocate() )
1562 StreamRef* pStreamRef = m_StreamRefPool.NewObject();
1564 pStreamRef->pCue = pCue;
1567 m_StreamRefs.PushBack( pStreamRef );
1572void ASoundManager::EventHandler_StopAudio( SoundEvent* a_pEvent )
1576 Cue* pCue = a_pEvent->pCue;
1577 ASound* pSound = pCue->pSound;
1582 TBOOL bReserved = FSOUND_GetReserved( pChannel->iFMODChannelHandle );
1585 FSOUND_SetReserved( pChannel->iFMODChannelHandle,
TFALSE );
1587 FSOUND_StopSound( pChannel->iFMODChannelHandle );
1589 if ( pSound->m_iFlags & 0x10 )
1591 FSOUND_STREAM* pStreamHandle = (FSOUND_STREAM*)pChannel->pSample->pWaveBank->GetWave( pChannel->pSample->iId )->pSampleHandle;
1592 FSOUND_Stream_Stop( pStreamHandle );
1595 pChannel->pSample->pWaveBank->ResetWave( pChannel->pSample->iId );
1596 pCue->iNumChannelRefs -= 1;
1599 m_ChannelRefPool.DeleteObject( pChannel );
1603void ASoundManager::EventHandler_UpdateChannelVolume( SoundEvent* a_pEvent )
1607 Cue* pCue = a_pEvent->pCue;
1608 ASound* pSound = pCue->pSound;
1614 pChannel->
fVolume = m_aCategories[ pSound->m_uiCategoryIndex ].fVolumeMultiplier * pChannel->pSample->fVolume * a_pEvent->oParameters[ 0 ];
1617 pCue->fVolume = a_pEvent->oParameters[ 0 ];
1619 FSOUND_SetVolume( pChannel->iFMODChannelHandle, ( !m_bMuted ) ?
TINT( pChannel->fVolume * 255.0f ) : 0 );
1623void ASoundManager::EventHandler_UpdateChannelFrequency( SoundEvent* a_pEvent )
1627 Cue* pCue = a_pEvent->pCue;
1628 ASound* pSound = pCue->pSound;
1634 pChannel->
iFrequency =
TINT( a_pEvent->pSample->iFrequency * pCue->fFrequency * a_pEvent->oParameters[ 0 ] );
1635 FSOUND_SetFrequency( pChannel->iFMODChannelHandle, pChannel->iFrequency );
1639void ASoundManager::EventHandler_UpdatePosition( SoundEvent* a_pEvent )
1643 Cue* pCue = a_pEvent->pCue;
1644 ASound* pSound = pCue->pSound;
1650 FSOUND_3D_SetAttributes( pChannel->iFMODChannelHandle, a_pEvent->oParameters.aParams,
TNULL );
1675 ASoundManager* pSoundManager = ASoundManager::GetSingleton();
1679 it->fnCallback( 1, GetCueIndex(
this ), it->pUserData );
1690 channelRef->pSample->pWaveBank->ResetWave( channelRef->pSample->iId );
1697 pSoundManager->m_SoundEventPool.FreeObject( pSoundEvent );
1709 pSoundManager->m_ChannelRefLegacyPool.DeleteObject( pChannelRef );
1718 pSoundManager->m_ChannelRefPool.DeleteObject( pChannelRef );
1731 if ( it->eEventType == a_eEventType )
1757 m_aEventHandlers[ a_eEventType ].Unused = 0;
1758 m_aEventHandlers[ a_eEventType ].fnCallback = a_fnHandler;
1765 EventHandler::Callback_t fnEventCallback = m_aEventHandlers[ a_eEventType ].fnCallback;
1770 ( a_pSoundManager->*fnEventCallback )( a_pEvent );
@ BASISVECTOR_TRANSLATION
#define TOFFSETOF(CLASS, MEMBER)
#define HASANYFLAG(STATE, FLAG)
#define TREINTERPRETCAST(TYPE, VALUE)
#define TOSHI_NAMESPACE_USING
#define TARRAYSIZE(ARRAY)
#define T2_FOREACH(vecName, iteratorName)
#define TDEFINE_CLASS(...)
#define TPSTRING8_DECLARE(STR)
ALoadScreen g_oLoadScreen
#define MAX_NUM_SOUND_EVENTS
#define ASOUNDMANAGER_MAX_NUM_CUE
TSystemManager g_oSystemManager
TFORCEINLINE void Clip(T &rVal, const T &Min, const T &Max)
TFORCEINLINE TINT Round(TFLOAT a_fVal)
TFileSystem * FindFileSystem(const TString8 &name)
ERROR Load(const TCHAR *a_szFilePath, TUINT32 a_uiUnknown=0)
TFLOAT GetFloatMinMax(TFLOAT a_fLower, TFLOAT a_fUpper)
static const constinit TVector4 VEC_ZERO
const class PBProperties * GetProperties() const
PBPropertyValue * GetValue(TSIZE a_iIndex)
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
TFORCEINLINE const TPooledString8 * GetPooledString() const
TFORCEINLINE TBOOL IsEmpty() const
TFORCEINLINE const TCHAR * GetString() const
static TFORCEINLINE TFileManager * GetSingleton()
TINT Compare(const TCHAR *a_szString, TINT a_iLength=-1) const
const TCHAR * GetString(TINT a_iIndex=0) const
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()
static Toshi::TMemory::MemBlock * GetMemBlock(POOL a_ePool)
TINT GetRandomSample(TINT a_iWaveIndexMin, TINT a_iWaveIndexMax)
TINT GetFirstWaveForTrack(TINT a_iTrack) const
TINT GetRandomSampleWeighted(TINT a_iTrackIndex, TINT a_iWaveIndexMin, TINT a_iWaveIndexMax)
TFLOAT fMinVolumeMultiplier
TFLOAT fMaxVolumeMultiplier
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)
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
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
virtual LOADRESULT Load(LOADFLAGS a_uiFlags, TINT a_iBufferSize)=0
AWaveSampleHandle CreateWaveSample(TINT a_iWaveIndex, TINT a_iUnused)
void SetWaveFlag1(TINT a_iWaveIndex)
TINT GetWaveId(TINT a_iWaveIndex)
void ParseWavesData(const PBProperties *a_pBankProperties, TUINT a_uiForcedFlags)
AWave * GetWave(TINT a_iWaveIndex)
void SetWaveFlag2(TINT a_iWaveIndex)