Audio refactoring:

* renamed tSound fields, added descriptions for each field
* getting rid of term 'intensity' in favour of 'max distance'
* renamed two cAudioManager fields
* fix volume not being reduced for stopping sounds that are looped
This commit is contained in:
Sergeanur 2021-08-20 14:28:55 +03:00
parent c8623cfe09
commit a401f926d3
5 changed files with 670 additions and 647 deletions

View File

@ -263,13 +263,13 @@ cAudioManager::SetUpOneShotCollisionSound(const cAudioCollision &col)
m_sQueueSample.m_vecPos = col.m_vecPosition; m_sQueueSample.m_vecPos = col.m_vecPosition;
m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_bIs2D = FALSE; m_sQueueSample.m_bIs2D = FALSE;
m_sQueueSample.m_nReleasingVolumeModificator = 11; m_sQueueSample.m_nPriority = 11;
m_sQueueSample.m_nLoopCount = 1; m_sQueueSample.m_nLoopCount = 1;
SET_EMITTING_VOLUME(emittingVol); SET_EMITTING_VOLUME(emittingVol);
RESET_LOOP_OFFSETS RESET_LOOP_OFFSETS
m_sQueueSample.m_fSpeedMultiplier = 4.0f; m_sQueueSample.m_fSpeedMultiplier = 4.0f;
m_sQueueSample.m_SoundIntensity = CollisionSoundIntensity; m_sQueueSample.m_MaxDistance = CollisionSoundIntensity;
m_sQueueSample.m_bReleasingSoundFlag = TRUE; m_sQueueSample.m_bStatic = TRUE;
SET_SOUND_REVERB(TRUE); SET_SOUND_REVERB(TRUE);
SET_SOUND_REFLECTION(FALSE); SET_SOUND_REFLECTION(FALSE);
AddSampleToRequestedQueue(); AddSampleToRequestedQueue();
@ -292,14 +292,14 @@ cAudioManager::SetUpLoopingCollisionSound(const cAudioCollision &col, uint8 coun
m_sQueueSample.m_vecPos = col.m_vecPosition; m_sQueueSample.m_vecPos = col.m_vecPosition;
m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_bIs2D = FALSE; m_sQueueSample.m_bIs2D = FALSE;
m_sQueueSample.m_nReleasingVolumeModificator = 7; m_sQueueSample.m_nPriority = 7;
m_sQueueSample.m_nLoopCount = 0; m_sQueueSample.m_nLoopCount = 0;
SET_EMITTING_VOLUME(emittingVol); SET_EMITTING_VOLUME(emittingVol);
SET_LOOP_OFFSETS(m_sQueueSample.m_nSampleIndex) SET_LOOP_OFFSETS(m_sQueueSample.m_nSampleIndex)
m_sQueueSample.m_fSpeedMultiplier = 4.0f; m_sQueueSample.m_fSpeedMultiplier = 4.0f;
m_sQueueSample.m_SoundIntensity = CollisionSoundIntensity; m_sQueueSample.m_MaxDistance = CollisionSoundIntensity;
m_sQueueSample.m_bReleasingSoundFlag = FALSE; m_sQueueSample.m_bStatic = FALSE;
m_sQueueSample.m_nReleasingVolumeDivider = 5; m_sQueueSample.m_nFramesToPlay = 5;
SET_SOUND_REVERB(TRUE); SET_SOUND_REVERB(TRUE);
SET_SOUND_REFLECTION(FALSE); SET_SOUND_REFLECTION(FALSE);
AddSampleToRequestedQueue(); AddSampleToRequestedQueue();

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@ cAudioManager AudioManager;
cAudioManager::cAudioManager() cAudioManager::cAudioManager()
{ {
m_bIsInitialised = FALSE; m_bIsInitialised = FALSE;
m_bReverb = TRUE; m_bIsSurround = TRUE;
field_6 = 0; field_6 = 0;
m_fSpeedOfSound = SPEED_OF_SOUND / TIME_SPENT; m_fSpeedOfSound = SPEED_OF_SOUND / TIME_SPENT;
m_nTimeSpent = TIME_SPENT; m_nTimeSpent = TIME_SPENT;
@ -42,7 +42,7 @@ cAudioManager::cAudioManager()
} }
m_nAudioEntitiesTotal = 0; m_nAudioEntitiesTotal = 0;
m_FrameCounter = 0; m_FrameCounter = 0;
m_bFifthFrameFlag = FALSE; m_bReduceReleasingPriority = FALSE;
m_bTimerJustReset = FALSE; m_bTimerJustReset = FALSE;
m_nTimer = 0; m_nTimer = 0;
} }
@ -491,7 +491,7 @@ cAudioManager::ServiceSoundEffects()
#ifdef FIX_BUGS #ifdef FIX_BUGS
if(CTimer::GetLogicalFramesPassed() != 0) if(CTimer::GetLogicalFramesPassed() != 0)
#endif #endif
m_bFifthFrameFlag = (m_FrameCounter++ % 5) == 0; m_bReduceReleasingPriority = (m_FrameCounter++ % 5) == 0;
if (m_nUserPause && !m_nPreviousUserPause) { if (m_nUserPause && !m_nPreviousUserPause) {
for (int32 i = 0; i < NUM_CHANNELS; i++) for (int32 i = 0; i < NUM_CHANNELS; i++)
SampleManager.StopChannel(i); SampleManager.StopChannel(i);
@ -510,7 +510,7 @@ cAudioManager::ServiceSoundEffects()
} }
m_nActiveSampleQueue = m_nActiveSampleQueue == 1 ? 0 : 1; m_nActiveSampleQueue = m_nActiveSampleQueue == 1 ? 0 : 1;
#ifdef AUDIO_REVERB #ifdef AUDIO_REVERB
if(m_bReverb) ProcessReverb(); if(m_bIsSurround) ProcessReverb();
#endif #endif
ProcessSpecial(); ProcessSpecial();
ClearRequestedQueue(); ClearRequestedQueue();
@ -537,20 +537,20 @@ cAudioManager::ServiceSoundEffects()
} }
uint8 uint8
cAudioManager::ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) cAudioManager::ComputeVolume(uint8 emittingVolume, float maxDistance, float distance)
{ {
float newSoundIntensity; float minDistance;
float newEmittingVolume; uint8 newEmittingVolume;
if (soundIntensity <= 0.0f) if (maxDistance <= 0.0f)
return 0; return 0;
newSoundIntensity = soundIntensity / 5.0f; minDistance = maxDistance / 5.0f;
if (newSoundIntensity > distance) if (minDistance > distance)
return emittingVolume; return emittingVolume;
newEmittingVolume = emittingVolume * SQR((soundIntensity - newSoundIntensity - (distance - newSoundIntensity)) newEmittingVolume = emittingVolume * SQR((maxDistance - minDistance - (distance - minDistance))
/ (soundIntensity - newSoundIntensity)); / (maxDistance - minDistance));
return Min(127, newEmittingVolume); return Min(127, newEmittingVolume);
} }
@ -636,42 +636,42 @@ cAudioManager::InterrogateAudioEntities()
void void
cAudioManager::AddSampleToRequestedQueue() cAudioManager::AddSampleToRequestedQueue()
{ {
uint32 calculatedVolume; uint32 finalPriority;
uint8 sampleIndex; uint8 sampleIndex;
#ifdef AUDIO_REFLECTIONS #ifdef AUDIO_REFLECTIONS
bool8 bReflections; bool8 bReflections;
#endif #endif
if (m_sQueueSample.m_nSampleIndex < TOTAL_AUDIO_SAMPLES) { if (m_sQueueSample.m_nSampleIndex < TOTAL_AUDIO_SAMPLES) {
calculatedVolume = m_sQueueSample.m_nReleasingVolumeModificator * (MAX_VOLUME - m_sQueueSample.m_nVolume); finalPriority = m_sQueueSample.m_nPriority * (MAX_VOLUME - m_sQueueSample.m_nVolume);
sampleIndex = m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; sampleIndex = m_SampleRequestQueuesStatus[m_nActiveSampleQueue];
if (sampleIndex >= m_nActiveSamples) { if (sampleIndex >= m_nActiveSamples) {
sampleIndex = m_abSampleQueueIndexTable[m_nActiveSampleQueue][m_nActiveSamples - 1]; sampleIndex = m_abSampleQueueIndexTable[m_nActiveSampleQueue][m_nActiveSamples - 1];
if (m_asSamples[m_nActiveSampleQueue][sampleIndex].m_nCalculatedVolume <= calculatedVolume) if (m_asSamples[m_nActiveSampleQueue][sampleIndex].m_nFinalPriority <= finalPriority)
return; return;
} else { } else {
++m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; ++m_SampleRequestQueuesStatus[m_nActiveSampleQueue];
} }
m_sQueueSample.m_nCalculatedVolume = calculatedVolume; m_sQueueSample.m_nFinalPriority = finalPriority;
m_sQueueSample.m_bLoopEnded = FALSE; m_sQueueSample.m_bIsPlayingFinished = FALSE;
#ifdef AUDIO_REFLECTIONS #ifdef AUDIO_REFLECTIONS
if (m_sQueueSample.m_bIs2D || CCullZones::InRoomForAudio()) { if (m_sQueueSample.m_bIs2D || CCullZones::InRoomForAudio()) {
m_sQueueSample.m_bRequireReflection = FALSE; m_sQueueSample.m_bReflections = FALSE;
m_sQueueSample.m_nLoopsRemaining = 0; m_sQueueSample.m_nReflectionDelay = 0;
} }
if (m_bDynamicAcousticModelingStatus && m_sQueueSample.m_nLoopCount > 0) { if (m_bDynamicAcousticModelingStatus && m_sQueueSample.m_nLoopCount > 0) {
bReflections = m_sQueueSample.m_bRequireReflection; bReflections = m_sQueueSample.m_bReflections;
} else { } else {
bReflections = FALSE; bReflections = FALSE;
m_sQueueSample.m_nLoopsRemaining = 0; m_sQueueSample.m_nReflectionDelay = 0;
} }
m_sQueueSample.m_bRequireReflection = FALSE; m_sQueueSample.m_bReflections = FALSE;
if ( m_bReverb && m_sQueueSample.m_bIs2D ) if ( m_bIsSurround && m_sQueueSample.m_bIs2D )
m_sQueueSample.m_nFrontRearOffset = 30; m_sQueueSample.m_nFrontRearPan = 30;
#ifdef AUDIO_REVERB #ifdef AUDIO_REVERB
if (!m_bDynamicAcousticModelingStatus) if (!m_bDynamicAcousticModelingStatus)
m_sQueueSample.m_bReverbFlag = FALSE; m_sQueueSample.m_bReverb = FALSE;
#endif #endif
#endif #endif
@ -691,8 +691,8 @@ cAudioManager::AddDetailsToRequestedOrderList(uint8 sample)
uint32 i = 0; uint32 i = 0;
if (sample > 0) { if (sample > 0) {
for (; i < sample; i++) { for (; i < sample; i++) {
if (m_asSamples[m_nActiveSampleQueue][m_abSampleQueueIndexTable[m_nActiveSampleQueue][i]].m_nCalculatedVolume > if (m_asSamples[m_nActiveSampleQueue][m_abSampleQueueIndexTable[m_nActiveSampleQueue][i]].m_nFinalPriority >
m_asSamples[m_nActiveSampleQueue][sample].m_nCalculatedVolume) m_asSamples[m_nActiveSampleQueue][sample].m_nFinalPriority)
break; break;
} }
if (i < sample) { if (i < sample) {
@ -724,7 +724,7 @@ cAudioManager::AddReflectionsToRequestedQueue()
} else { } else {
emittingVolume = (9 * m_sQueueSample.m_nVolume) / 16; emittingVolume = (9 * m_sQueueSample.m_nVolume) / 16;
} }
m_sQueueSample.m_SoundIntensity /= 2.f; m_sQueueSample.m_MaxDistance /= 2.f;
uint32 halfOldFreq = oldFreq >> 1; uint32 halfOldFreq = oldFreq >> 1;
@ -733,12 +733,12 @@ cAudioManager::AddReflectionsToRequestedQueue()
m_afReflectionsDistances[i] = (m_anRandomTable[i % 4] % 3) * 100.f / 8.f; m_afReflectionsDistances[i] = (m_anRandomTable[i % 4] % 3) * 100.f / 8.f;
reflectionDistance = m_afReflectionsDistances[i]; reflectionDistance = m_afReflectionsDistances[i];
if (reflectionDistance > 0.0f && reflectionDistance < 100.f && reflectionDistance < m_sQueueSample.m_SoundIntensity) { if (reflectionDistance > 0.0f && reflectionDistance < 100.f && reflectionDistance < m_sQueueSample.m_MaxDistance) {
m_sQueueSample.m_nLoopsRemaining = CTimer::GetIsSlowMotionActive() ? (reflectionDistance * 800.f / 1029.f) : (reflectionDistance * 500.f / 1029.f); m_sQueueSample.m_nReflectionDelay = CTimer::GetIsSlowMotionActive() ? (reflectionDistance * 800.f / 1029.f) : (reflectionDistance * 500.f / 1029.f);
if (m_sQueueSample.m_nLoopsRemaining > 3) { if (m_sQueueSample.m_nReflectionDelay > 3) {
m_sQueueSample.m_fDistance = m_afReflectionsDistances[i]; m_sQueueSample.m_fDistance = m_afReflectionsDistances[i];
SET_EMITTING_VOLUME(emittingVolume); SET_EMITTING_VOLUME(emittingVolume);
m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, m_sQueueSample.m_SoundIntensity, m_sQueueSample.m_fDistance); m_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, m_sQueueSample.m_MaxDistance, m_sQueueSample.m_fDistance);
if (m_sQueueSample.m_nVolume > emittingVolume / 16) { if (m_sQueueSample.m_nVolume > emittingVolume / 16) {
m_sQueueSample.m_nCounter = oldCounter + (i + 1) * 256; m_sQueueSample.m_nCounter = oldCounter + (i + 1) * 256;
@ -753,7 +753,7 @@ cAudioManager::AddReflectionsToRequestedQueue()
m_sQueueSample.m_nFrequency += noise; m_sQueueSample.m_nFrequency += noise;
} }
} }
m_sQueueSample.m_nReleasingVolumeModificator += 20; m_sQueueSample.m_nPriority += 20;
m_sQueueSample.m_vecPos = m_avecReflectionsPos[i]; m_sQueueSample.m_vecPos = m_avecReflectionsPos[i];
AddSampleToRequestedQueue(); AddSampleToRequestedQueue();
} }
@ -901,7 +901,7 @@ cAudioManager::AddReleasingSounds()
for (int32 i = 0; i < m_SampleRequestQueuesStatus[queue]; i++) { for (int32 i = 0; i < m_SampleRequestQueuesStatus[queue]; i++) {
tSound &sample = m_asSamples[queue][m_abSampleQueueIndexTable[queue][i]]; tSound &sample = m_asSamples[queue][m_abSampleQueueIndexTable[queue][i]];
if (sample.m_bLoopEnded) if (sample.m_bIsPlayingFinished)
continue; continue;
toProcess[i] = FALSE; toProcess[i] = FALSE;
@ -914,32 +914,44 @@ cAudioManager::AddReleasingSounds()
} }
if(!toProcess[i]) { if(!toProcess[i]) {
#ifdef AUDIO_REFLECTIONS #ifdef AUDIO_REFLECTIONS
if(sample.m_nCounter <= 255 || sample.m_nLoopsRemaining == 0) // check if not reflection if(sample.m_nCounter <= 255 || sample.m_nReflectionDelay == 0) // check if not delayed reflection
#endif #endif
{ {
if (sample.m_nReleasingVolumeDivider == 0) if (sample.m_nFramesToPlay == 0)
continue; continue;
if (sample.m_nLoopCount == 0) { if (sample.m_nLoopCount == 0) {
if (sample.m_nVolumeChange == -1) { if (sample.m_nVolumeChange == -1) {
sample.m_nVolumeChange = sample.m_nVolume / sample.m_nReleasingVolumeDivider; #if defined(FIX_BUGS) && defined(EXTERNAL_3D_SOUND)
sample.m_nVolumeChange = sample.m_nEmittingVolume / sample.m_nFramesToPlay;
#else
sample.m_nVolumeChange = sample.m_nVolume / sample.m_nFramesToPlay;
#endif
if (sample.m_nVolumeChange <= 0) if (sample.m_nVolumeChange <= 0)
sample.m_nVolumeChange = 1; sample.m_nVolumeChange = 1;
} }
#if defined(FIX_BUGS) && defined(EXTERNAL_3D_SOUND)
if (sample.m_nEmittingVolume <= sample.m_nVolumeChange) {
#else
if (sample.m_nVolume <= sample.m_nVolumeChange) { if (sample.m_nVolume <= sample.m_nVolumeChange) {
sample.m_nReleasingVolumeDivider = 0; #endif
sample.m_nFramesToPlay = 0;
continue; continue;
} }
#if defined(FIX_BUGS) && defined(EXTERNAL_3D_SOUND)
sample.m_nEmittingVolume -= sample.m_nVolumeChange;
#else
sample.m_nVolume -= sample.m_nVolumeChange; sample.m_nVolume -= sample.m_nVolumeChange;
#endif
} }
#ifdef FIX_BUGS #ifdef FIX_BUGS
if(CTimer::GetLogicalFramesPassed() != 0) if(CTimer::GetLogicalFramesPassed() != 0)
#endif #endif
--sample.m_nReleasingVolumeDivider; --sample.m_nFramesToPlay;
if (m_bFifthFrameFlag) { if (m_bReduceReleasingPriority) {
if (sample.m_nReleasingVolumeModificator < 20) if (sample.m_nPriority < 20)
++sample.m_nReleasingVolumeModificator; ++sample.m_nPriority;
} }
sample.m_bReleasingSoundFlag = FALSE; sample.m_bStatic = FALSE;
} }
memcpy(&m_sQueueSample, &sample, sizeof(tSound)); memcpy(&m_sQueueSample, &sample, sizeof(tSound));
AddSampleToRequestedQueue(); AddSampleToRequestedQueue();
@ -971,8 +983,8 @@ cAudioManager::ProcessActiveQueues()
bool8 missionState; bool8 missionState;
for (int32 i = 0; i < m_nActiveSamples; i++) { for (int32 i = 0; i < m_nActiveSamples; i++) {
m_asSamples[m_nActiveSampleQueue][i].m_bIsProcessed = FALSE; m_asSamples[m_nActiveSampleQueue][i].m_bIsBeingPlayed = FALSE;
m_asActiveSamples[i].m_bIsProcessed = FALSE; m_asActiveSamples[i].m_bIsBeingPlayed = FALSE;
} }
for (int32 i = 0; i < m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; i++) { for (int32 i = 0; i < m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; i++) {
@ -988,19 +1000,19 @@ cAudioManager::ProcessActiveQueues()
flag = !(j & 1); flag = !(j & 1);
if (flag && !SampleManager.GetChannelUsedFlag(j)) { if (flag && !SampleManager.GetChannelUsedFlag(j)) {
sample.m_bLoopEnded = TRUE; sample.m_bIsPlayingFinished = TRUE;
m_asActiveSamples[j].m_bLoopEnded = TRUE; m_asActiveSamples[j].m_bIsPlayingFinished = TRUE;
m_asActiveSamples[j].m_nSampleIndex = NO_SAMPLE; m_asActiveSamples[j].m_nSampleIndex = NO_SAMPLE;
m_asActiveSamples[j].m_nEntityIndex = AEHANDLE_NONE; m_asActiveSamples[j].m_nEntityIndex = AEHANDLE_NONE;
continue; continue;
} }
if (sample.m_nReleasingVolumeDivider == 0) if (sample.m_nFramesToPlay == 0)
sample.m_nReleasingVolumeDivider = 1; sample.m_nFramesToPlay = 1;
} }
sample.m_bIsProcessed = TRUE; sample.m_bIsBeingPlayed = TRUE;
m_asActiveSamples[j].m_bIsProcessed = TRUE; m_asActiveSamples[j].m_bIsBeingPlayed = TRUE;
sample.m_nVolumeChange = -1; sample.m_nVolumeChange = -1;
if (!sample.m_bReleasingSoundFlag) { if (!sample.m_bStatic) {
if (sample.m_bIs2D) { if (sample.m_bIs2D) {
#ifdef EXTERNAL_3D_SOUND #ifdef EXTERNAL_3D_SOUND
emittingVol = m_bDoubleVolume ? 2 * Min(63, sample.m_nEmittingVolume) : sample.m_nEmittingVolume; emittingVol = m_bDoubleVolume ? 2 * Min(63, sample.m_nEmittingVolume) : sample.m_nEmittingVolume;
@ -1011,7 +1023,7 @@ cAudioManager::ProcessActiveQueues()
#ifdef EXTERNAL_3D_SOUND #ifdef EXTERNAL_3D_SOUND
SampleManager.SetChannelEmittingVolume(j, emittingVol); SampleManager.SetChannelEmittingVolume(j, emittingVol);
#else #else
SampleManager.SetChannelPan(j, sample.m_nOffset); SampleManager.SetChannelPan(j, sample.m_nPan);
SampleManager.SetChannelVolume(j, emittingVol); SampleManager.SetChannelVolume(j, emittingVol);
#endif #endif
} else { } else {
@ -1058,26 +1070,26 @@ cAudioManager::ProcessActiveQueues()
TranslateEntity(&sample.m_vecPos, &position); TranslateEntity(&sample.m_vecPos, &position);
#ifdef EXTERNAL_3D_SOUND #ifdef EXTERNAL_3D_SOUND
SampleManager.SetChannel3DPosition(j, position.x, position.y, position.z); SampleManager.SetChannel3DPosition(j, position.x, position.y, position.z);
SampleManager.SetChannel3DDistances(j, sample.m_SoundIntensity, 0.25f * sample.m_SoundIntensity); SampleManager.SetChannel3DDistances(j, sample.m_MaxDistance, 0.25f * sample.m_MaxDistance);
#else #else
sample.m_nOffset = ComputePan(sample.m_fDistance, &position); sample.m_nPan = ComputePan(sample.m_fDistance, &position);
SampleManager.SetChannelPan(j, sample.m_nOffset); SampleManager.SetChannelPan(j, sample.m_nPan);
#endif #endif
} }
#if !defined(GTA_PS2) || defined(AUDIO_REVERB) #if !defined(GTA_PS2) || defined(AUDIO_REVERB)
SampleManager.SetChannelReverbFlag(j, sample.m_bReverbFlag); SampleManager.SetChannelReverbFlag(j, sample.m_bReverb);
#endif #endif
break; //continue for i break; //continue for i
} }
sample.m_bIsProcessed = FALSE; sample.m_bIsBeingPlayed = FALSE;
m_asActiveSamples[j].m_bIsProcessed = FALSE; m_asActiveSamples[j].m_bIsBeingPlayed = FALSE;
//continue for j //continue for j
} }
} }
} }
} }
for (int32 i = 0; i < m_nActiveSamples; i++) { for (int32 i = 0; i < m_nActiveSamples; i++) {
if (m_asActiveSamples[i].m_nSampleIndex != NO_SAMPLE && !m_asActiveSamples[i].m_bIsProcessed) { if (m_asActiveSamples[i].m_nSampleIndex != NO_SAMPLE && !m_asActiveSamples[i].m_bIsBeingPlayed) {
SampleManager.StopChannel(i); SampleManager.StopChannel(i);
m_asActiveSamples[i].m_nSampleIndex = NO_SAMPLE; m_asActiveSamples[i].m_nSampleIndex = NO_SAMPLE;
m_asActiveSamples[i].m_nEntityIndex = AEHANDLE_NONE; m_asActiveSamples[i].m_nEntityIndex = AEHANDLE_NONE;
@ -1085,29 +1097,29 @@ cAudioManager::ProcessActiveQueues()
} }
for (uint8 i = 0; i < m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; i++) { for (uint8 i = 0; i < m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; i++) {
tSound &sample = m_asSamples[m_nActiveSampleQueue][m_abSampleQueueIndexTable[m_nActiveSampleQueue][i]]; tSound &sample = m_asSamples[m_nActiveSampleQueue][m_abSampleQueueIndexTable[m_nActiveSampleQueue][i]];
if (!sample.m_bIsProcessed && !sample.m_bLoopEnded && m_asAudioEntities[sample.m_nEntityIndex].m_bIsUsed && sample.m_nSampleIndex < NO_SAMPLE) { if (!sample.m_bIsBeingPlayed && !sample.m_bIsPlayingFinished && m_asAudioEntities[sample.m_nEntityIndex].m_bIsUsed && sample.m_nSampleIndex < NO_SAMPLE) {
#ifdef AUDIO_REFLECTIONS #ifdef AUDIO_REFLECTIONS
if (sample.m_nCounter > 255 && sample.m_nLoopCount > 0 && sample.m_nLoopsRemaining > 0) { // check if reflection if (sample.m_nCounter > 255 && sample.m_nLoopCount > 0 && sample.m_nReflectionDelay > 0) { // check if reflection
sample.m_nLoopsRemaining--; sample.m_nReflectionDelay--;
sample.m_nReleasingVolumeDivider = 1; sample.m_nFramesToPlay = 1;
} else } else
#endif #endif
{ {
for (uint8 j = 0; j < m_nActiveSamples; j++) { for (uint8 j = 0; j < m_nActiveSamples; j++) {
uint8 k = (j + field_6) % m_nActiveSamples; uint8 k = (j + field_6) % m_nActiveSamples;
if (!m_asActiveSamples[k].m_bIsProcessed) { if (!m_asActiveSamples[k].m_bIsBeingPlayed) {
if (sample.m_nLoopCount > 0) { if (sample.m_nLoopCount > 0) {
samplesPerFrame = sample.m_nFrequency / m_nTimeSpent; samplesPerFrame = sample.m_nFrequency / m_nTimeSpent;
samplesToPlay = sample.m_nLoopCount * SampleManager.GetSampleLength(sample.m_nSampleIndex); samplesToPlay = sample.m_nLoopCount * SampleManager.GetSampleLength(sample.m_nSampleIndex);
if (samplesPerFrame == 0) if (samplesPerFrame == 0)
continue; continue;
sample.m_nReleasingVolumeDivider = samplesToPlay / samplesPerFrame + 1; sample.m_nFramesToPlay = samplesToPlay / samplesPerFrame + 1;
} }
memcpy(&m_asActiveSamples[k], &sample, sizeof(tSound)); memcpy(&m_asActiveSamples[k], &sample, sizeof(tSound));
if (!m_asActiveSamples[k].m_bIs2D) { if (!m_asActiveSamples[k].m_bIs2D) {
TranslateEntity(&m_asActiveSamples[k].m_vecPos, &position); TranslateEntity(&m_asActiveSamples[k].m_vecPos, &position);
#ifndef EXTERNAL_3D_SOUND #ifndef EXTERNAL_3D_SOUND
m_asActiveSamples[j].m_nOffset = ComputePan(m_asActiveSamples[j].m_fDistance, &position); m_asActiveSamples[j].m_nPan = ComputePan(m_asActiveSamples[j].m_fDistance, &position);
#endif #endif
} }
#ifdef EXTERNAL_3D_SOUND #ifdef EXTERNAL_3D_SOUND
@ -1140,18 +1152,18 @@ cAudioManager::ProcessActiveQueues()
SampleManager.SetChannelEmittingVolume(k, vol); SampleManager.SetChannelEmittingVolume(k, vol);
#else #else
SampleManager.SetChannelVolume(j, emittingVol); SampleManager.SetChannelVolume(j, emittingVol);
SampleManager.SetChannelPan(j, m_asActiveSamples[j].m_nOffset); SampleManager.SetChannelPan(j, m_asActiveSamples[j].m_nPan);
#endif #endif
#ifndef GTA_PS2 #ifndef GTA_PS2
SampleManager.SetChannelLoopPoints(k, m_asActiveSamples[k].m_nLoopStart, m_asActiveSamples[k].m_nLoopEnd); SampleManager.SetChannelLoopPoints(k, m_asActiveSamples[k].m_nLoopStart, m_asActiveSamples[k].m_nLoopEnd);
SampleManager.SetChannelLoopCount(k, m_asActiveSamples[k].m_nLoopCount); SampleManager.SetChannelLoopCount(k, m_asActiveSamples[k].m_nLoopCount);
#endif #endif
#if !defined(GTA_PS2) || defined(AUDIO_REVERB) #if !defined(GTA_PS2) || defined(AUDIO_REVERB)
SampleManager.SetChannelReverbFlag(k, m_asActiveSamples[k].m_bReverbFlag); SampleManager.SetChannelReverbFlag(k, m_asActiveSamples[k].m_bReverb);
#endif #endif
#ifdef EXTERNAL_3D_SOUND #ifdef EXTERNAL_3D_SOUND
if (m_asActiveSamples[k].m_bIs2D) { if (m_asActiveSamples[k].m_bIs2D) {
uint8 offset = m_asActiveSamples[k].m_nOffset; uint8 offset = m_asActiveSamples[k].m_nPan;
if (offset == 63) if (offset == 63)
x = 0.0f; x = 0.0f;
else if (offset >= 63) else if (offset >= 63)
@ -1161,19 +1173,19 @@ cAudioManager::ProcessActiveQueues()
usedX = x; usedX = x;
usedY = 0.0f; usedY = 0.0f;
usedZ = 0.0f; usedZ = 0.0f;
m_asActiveSamples[k].m_SoundIntensity = 100000.0f; m_asActiveSamples[k].m_MaxDistance = 100000.0f;
} else { } else {
usedX = position.x; usedX = position.x;
usedY = position.y; usedY = position.y;
usedZ = position.z; usedZ = position.z;
} }
SampleManager.SetChannel3DPosition(k, usedX, usedY, usedZ); SampleManager.SetChannel3DPosition(k, usedX, usedY, usedZ);
SampleManager.SetChannel3DDistances(k, m_asActiveSamples[k].m_SoundIntensity, 0.25f * m_asActiveSamples[k].m_SoundIntensity); SampleManager.SetChannel3DDistances(k, m_asActiveSamples[k].m_MaxDistance, 0.25f * m_asActiveSamples[k].m_MaxDistance);
#endif #endif
SampleManager.StartChannel(k); SampleManager.StartChannel(k);
} }
m_asActiveSamples[k].m_bIsProcessed = TRUE; m_asActiveSamples[k].m_bIsBeingPlayed = TRUE;
sample.m_bIsProcessed = TRUE; sample.m_bIsBeingPlayed = TRUE;
sample.m_nVolumeChange = -1; sample.m_nVolumeChange = -1;
break; break;
} }
@ -1202,34 +1214,34 @@ cAudioManager::ClearActiveSamples()
m_asActiveSamples[i].m_nSampleIndex = NO_SAMPLE; m_asActiveSamples[i].m_nSampleIndex = NO_SAMPLE;
m_asActiveSamples[i].m_nBankIndex = INVALID_SFX_BANK; m_asActiveSamples[i].m_nBankIndex = INVALID_SFX_BANK;
m_asActiveSamples[i].m_bIs2D = FALSE; m_asActiveSamples[i].m_bIs2D = FALSE;
m_asActiveSamples[i].m_nReleasingVolumeModificator = 5; m_asActiveSamples[i].m_nPriority = 5;
m_asActiveSamples[i].m_nFrequency = 0; m_asActiveSamples[i].m_nFrequency = 0;
m_asActiveSamples[i].m_nVolume = 0; m_asActiveSamples[i].m_nVolume = 0;
#ifdef EXTERNAL_3D_SOUND #ifdef EXTERNAL_3D_SOUND
m_asActiveSamples[i].m_nEmittingVolume = 0; m_asActiveSamples[i].m_nEmittingVolume = 0;
#endif #endif
m_asActiveSamples[i].m_fDistance = 0.0f; m_asActiveSamples[i].m_fDistance = 0.0f;
m_asActiveSamples[i].m_bIsProcessed = FALSE; m_asActiveSamples[i].m_bIsBeingPlayed = FALSE;
m_asActiveSamples[i].m_bLoopEnded = FALSE; m_asActiveSamples[i].m_bIsPlayingFinished = FALSE;
m_asActiveSamples[i].m_nLoopCount = 1; m_asActiveSamples[i].m_nLoopCount = 1;
#ifndef GTA_PS2 #ifndef GTA_PS2
m_asActiveSamples[i].m_nLoopStart = 0; m_asActiveSamples[i].m_nLoopStart = 0;
m_asActiveSamples[i].m_nLoopEnd = -1; m_asActiveSamples[i].m_nLoopEnd = -1;
#endif #endif
m_asActiveSamples[i].m_fSpeedMultiplier = 0.0f; m_asActiveSamples[i].m_fSpeedMultiplier = 0.0f;
m_asActiveSamples[i].m_SoundIntensity = 200.0f; m_asActiveSamples[i].m_MaxDistance = 200.0f;
m_asActiveSamples[i].m_nOffset = 63; m_asActiveSamples[i].m_nPan = 63;
m_asActiveSamples[i].m_bReleasingSoundFlag = FALSE; m_asActiveSamples[i].m_bStatic = FALSE;
m_asActiveSamples[i].m_nCalculatedVolume = 0; m_asActiveSamples[i].m_nFinalPriority = 0;
m_asActiveSamples[i].m_nReleasingVolumeDivider = 0; m_asActiveSamples[i].m_nFramesToPlay = 0;
m_asActiveSamples[i].m_nVolumeChange = -1; m_asActiveSamples[i].m_nVolumeChange = -1;
m_asActiveSamples[i].m_vecPos = CVector(0.0f, 0.0f, 0.0f); m_asActiveSamples[i].m_vecPos = CVector(0.0f, 0.0f, 0.0f);
#ifdef AUDIO_REVERB #ifdef AUDIO_REVERB
m_asActiveSamples[i].m_bReverbFlag = FALSE; m_asActiveSamples[i].m_bReverb = FALSE;
#endif // AUDIO_REVERB #endif // AUDIO_REVERB
#ifdef AUDIO_REFLECTIONS #ifdef AUDIO_REFLECTIONS
m_asActiveSamples[i].m_nLoopsRemaining = 0; m_asActiveSamples[i].m_nReflectionDelay = 0;
m_asActiveSamples[i].m_bRequireReflection = FALSE; m_asActiveSamples[i].m_bReflections = FALSE;
#endif // AUDIO_REFLECTIONS #endif // AUDIO_REFLECTIONS
} }
} }
@ -1257,17 +1269,17 @@ cAudioManager::AdjustSamplesVolume()
tSound *pSample = &m_asSamples[m_nActiveSampleQueue][m_abSampleQueueIndexTable[m_nActiveSampleQueue][i]]; tSound *pSample = &m_asSamples[m_nActiveSampleQueue][m_abSampleQueueIndexTable[m_nActiveSampleQueue][i]];
if (!pSample->m_bIs2D) if (!pSample->m_bIs2D)
pSample->m_nEmittingVolume = ComputeEmittingVolume(pSample->m_nEmittingVolume, pSample->m_SoundIntensity, pSample->m_fDistance); pSample->m_nEmittingVolume = ComputeEmittingVolume(pSample->m_nEmittingVolume, pSample->m_MaxDistance, pSample->m_fDistance);
} }
} }
uint8 uint8
cAudioManager::ComputeEmittingVolume(uint8 emittingVolume, float intensity, float dist) cAudioManager::ComputeEmittingVolume(uint8 emittingVolume, float maxDistance, float distance)
{ {
float quatIntensity = intensity / 4.0f; float minDistance = maxDistance / 4.0f;
float diffIntensity = intensity - quatIntensity; float diffDistance = maxDistance - minDistance;
if (dist > diffIntensity) if (distance > diffDistance)
return (quatIntensity - (dist - diffIntensity)) * (float)emittingVolume / quatIntensity; return (minDistance - (distance - diffDistance)) * (float)emittingVolume / minDistance;
return emittingVolume; return emittingVolume;
} }
#endif #endif

View File

@ -9,41 +9,49 @@
class tSound class tSound
{ {
public: public:
int32 m_nEntityIndex; int32 m_nEntityIndex; // audio entity index
uint32 m_nCounter; uint32 m_nCounter; // I'm not sure what this is but it looks like a virtual counter to determine the same sound in queue
uint32 m_nSampleIndex; // Values higher than 255 are used by reflections
uint8 m_nBankIndex; uint32 m_nSampleIndex; // An index of sample from AudioSamples.h
bool8 m_bIs2D; uint8 m_nBankIndex; // A sound bank index. IDK what's the point of it here since samples are hardcoded anyway
uint32 m_nReleasingVolumeModificator; bool8 m_bIs2D; // If TRUE then sound is played in 2D space (such as frontend or police radio)
uint32 m_nFrequency; uint32 m_nPriority; // The multiplier for the sound priority (see m_nFinalPriority below). Lesser value means higher priority
uint8 m_nVolume; uint32 m_nFrequency; // Sound frequency, plain and simple
float m_fDistance; uint8 m_nVolume; // Sound volume (0..127), only used as an actual volume without EXTERNAL_3D_SOUND (see m_nEmittingVolume)
uint32 m_nLoopCount; float m_fDistance; // Distance to camera (useless if m_bIs2D == TRUE)
uint32 m_nLoopCount; // 0 - always loop, 1 - don't loop, other values never seen
#ifndef GTA_PS2 #ifndef GTA_PS2
// Loop offsets
uint32 m_nLoopStart; uint32 m_nLoopStart;
int32 m_nLoopEnd; int32 m_nLoopEnd;
#endif #endif
#ifdef EXTERNAL_3D_SOUND #ifdef EXTERNAL_3D_SOUND
uint8 m_nEmittingVolume; uint8 m_nEmittingVolume; // The volume in 3D space, provided to 3D audio engine
#endif #endif
float m_fSpeedMultiplier; float m_fSpeedMultiplier; // Used for doppler effect. 0.0f - unaffected by doppler
float m_SoundIntensity; float m_MaxDistance; // The maximum distance at which sound could be heard. Minimum distance = MaxDistance / 5 or MaxDistance / 4 in case of emitting volume (useless if m_bIs2D == TRUE)
bool8 m_bReleasingSoundFlag; bool8 m_bStatic; // If TRUE then sound parameters cannot be changed during playback (frequency, position, etc.)
CVector m_vecPos; CVector m_vecPos; // Position of sound in 3D space. Unused if m_bIs2D == TRUE
#if !defined(GTA_PS2) || defined(AUDIO_REVERB) // GTA_PS2 because this field exists on mobile but not on PS2 #if !defined(GTA_PS2) || defined(AUDIO_REVERB) // GTA_PS2 because this field exists on mobile but not on PS2
bool8 m_bReverbFlag; bool8 m_bReverb; // Toggles reverb effect
#endif #endif
#ifdef AUDIO_REFLECTIONS #ifdef AUDIO_REFLECTIONS
uint8 m_nLoopsRemaining; uint8 m_nReflectionDelay; // Number of frames before reflection could be played. This is calculated internally by AudioManager and shouldn't be set by queued sample
bool8 m_bRequireReflection; // Used for oneshots bool8 m_bReflections; // Add sound reflections
#endif #endif
uint8 m_nOffset; uint8 m_nPan; // Sound panning (0-127). Controls the volume of the playback coming from left and right speaker. Calculated internally unless m_bIs2D==TRUE.
uint8 m_nFrontRearOffset; // 0 = L 100% R 0%
uint32 m_nReleasingVolumeDivider; // 63 = L 100% R 100%
bool8 m_bIsProcessed; // 127 = L 0% R 100%
bool8 m_bLoopEnded; uint8 m_nFrontRearPan; // Used on PS2 for surround panning
uint32 m_nCalculatedVolume; uint32 m_nFramesToPlay; // Number of frames the sound would be played (if it stops being queued).
int8 m_nVolumeChange; // This one is being set by queued sample for looping sounds, otherwise calculated inside AudioManager
// all fields below are internal to AudioManager calculations and aren't set by queued sample
bool8 m_bIsBeingPlayed; // Set to TRUE when the sound was added or changed on current frame to avoid it being overwritten
bool8 m_bIsPlayingFinished; // Not sure about the name. Set to TRUE when sampman channel becomes free
uint32 m_nFinalPriority; // Actual value used to compare priority, calculated using volume and m_nPriority. Lesser value means higher priority
int8 m_nVolumeChange; // How much m_nVolume should reduce per each frame.
}; };
VALIDATE_SIZE(tSound, 96); VALIDATE_SIZE(tSound, 96);
@ -227,8 +235,8 @@ class cAudioManager
{ {
public: public:
bool8 m_bIsInitialised; bool8 m_bIsInitialised;
bool8 m_bReverb; // unused bool8 m_bIsSurround; // used on PS2
bool8 m_bFifthFrameFlag; bool8 m_bReduceReleasingPriority;
uint8 m_nActiveSamples; uint8 m_nActiveSamples;
bool8 m_bDoubleVolume; // unused bool8 m_bDoubleVolume; // unused
bool8 m_bDynamicAcousticModelingStatus; bool8 m_bDynamicAcousticModelingStatus;
@ -320,7 +328,7 @@ public:
#endif #endif
void ServiceSoundEffects(); void ServiceSoundEffects();
uint8 ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance); uint8 ComputeVolume(uint8 emittingVolume, float maxDistance, float distance);
void TranslateEntity(Const CVector *v1, CVector *v2); void TranslateEntity(Const CVector *v1, CVector *v2);
int32 ComputeFrontRearMix(float, CVector *); int32 ComputeFrontRearMix(float, CVector *);
int32 ComputePan(float, CVector *); int32 ComputePan(float, CVector *);
@ -342,7 +350,7 @@ public:
#ifdef EXTERNAL_3D_SOUND // actually must have been && AUDIO_MSS as well #ifdef EXTERNAL_3D_SOUND // actually must have been && AUDIO_MSS as well
void AdjustSamplesVolume(); // inlined void AdjustSamplesVolume(); // inlined
uint8 ComputeEmittingVolume(uint8 emittingVolume, float intensity, float dist); // inlined uint8 ComputeEmittingVolume(uint8 emittingVolume, float maxDistance, float distance); // inlined
#endif #endif
// audio logic // audio logic
@ -612,12 +620,12 @@ public:
#define SET_EMITTING_VOLUME(vol) #define SET_EMITTING_VOLUME(vol)
#endif #endif
#ifdef AUDIO_REFLECTIONS #ifdef AUDIO_REFLECTIONS
#define SET_SOUND_REFLECTION(b) m_sQueueSample.m_bRequireReflection = b #define SET_SOUND_REFLECTION(b) m_sQueueSample.m_bReflections = b
#else #else
#define SET_SOUND_REFLECTION(b) #define SET_SOUND_REFLECTION(b)
#endif #endif
#ifdef AUDIO_REVERB #ifdef AUDIO_REVERB
#define SET_SOUND_REVERB(b) m_sQueueSample.m_bReverbFlag = b #define SET_SOUND_REVERB(b) m_sQueueSample.m_bReverb = b
#else #else
#define SET_SOUND_REVERB(b) #define SET_SOUND_REVERB(b)
#endif #endif

View File

@ -104,16 +104,16 @@ cAudioManager::DoPoliceRadioCrackle()
m_sQueueSample.m_nSampleIndex = SFX_POLICE_RADIO_CRACKLE; m_sQueueSample.m_nSampleIndex = SFX_POLICE_RADIO_CRACKLE;
m_sQueueSample.m_nBankIndex = SFX_BANK_0; m_sQueueSample.m_nBankIndex = SFX_BANK_0;
m_sQueueSample.m_bIs2D = TRUE; m_sQueueSample.m_bIs2D = TRUE;
m_sQueueSample.m_nReleasingVolumeModificator = 10; m_sQueueSample.m_nPriority = 10;
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_RADIO_CRACKLE); m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_RADIO_CRACKLE);
m_sQueueSample.m_nVolume = m_anRandomTable[2] % 20 + 15; m_sQueueSample.m_nVolume = m_anRandomTable[2] % 20 + 15;
m_sQueueSample.m_nLoopCount = 0; m_sQueueSample.m_nLoopCount = 0;
SET_EMITTING_VOLUME(m_sQueueSample.m_nVolume); SET_EMITTING_VOLUME(m_sQueueSample.m_nVolume);
SET_LOOP_OFFSETS(SFX_POLICE_RADIO_CRACKLE) SET_LOOP_OFFSETS(SFX_POLICE_RADIO_CRACKLE)
m_sQueueSample.m_bReleasingSoundFlag = FALSE; m_sQueueSample.m_bStatic = FALSE;
SET_SOUND_REVERB(FALSE); SET_SOUND_REVERB(FALSE);
m_sQueueSample.m_nOffset = 63; m_sQueueSample.m_nPan = 63;
m_sQueueSample.m_nReleasingVolumeDivider = 3; m_sQueueSample.m_nFramesToPlay = 3;
SET_SOUND_REFLECTION(FALSE); SET_SOUND_REFLECTION(FALSE);
AddSampleToRequestedQueue(); AddSampleToRequestedQueue();
} }