summaryrefslogtreecommitdiffstats
path: root/src/audio/AudioManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/audio/AudioManager.cpp186
1 files changed, 142 insertions, 44 deletions
diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp
index f92e15fc..e46bc07e 100644
--- a/src/audio/AudioManager.cpp
+++ b/src/audio/AudioManager.cpp
@@ -135,8 +135,47 @@ cAudioManager::CreateEntity(eAudioType type, void *entity)
return AEHANDLE_ERROR_NOENTITY;
if (type >= TOTAL_AUDIO_TYPES)
return AEHANDLE_ERROR_BADAUDIOTYPE;
+
+#ifdef FIX_BUGS
+ // since sound could still play after entity deletion let's make sure we don't override one that is in use
+ // find all the free entity IDs that are being used by queued samples
+ int32 stillUsedEntities[NUM_CHANNELS_GENERIC * NUM_SOUNDS_SAMPLES_BANKS];
+ uint32 stillUsedEntitiesCount = 0;
+
+ for (uint8 i = 0; i < NUM_SOUNDS_SAMPLES_BANKS; i++)
+ for (uint8 j = 0; j < m_SampleRequestQueuesStatus[i]; j++) {
+ tSound &sound = m_asSamples[i][m_abSampleQueueIndexTable[i][j]];
+ if (sound.m_nEntityIndex < 0) continue;
+ if (!m_asAudioEntities[sound.m_nEntityIndex].m_bIsUsed) {
+ bool found = false;
+ for (uint8 k = 0; k < stillUsedEntitiesCount; k++) {
+ if (stillUsedEntities[k] == sound.m_nEntityIndex) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ stillUsedEntities[stillUsedEntitiesCount++] = sound.m_nEntityIndex;
+ }
+ }
+#endif
+
for (uint32 i = 0; i < ARRAY_SIZE(m_asAudioEntities); i++) {
if (!m_asAudioEntities[i].m_bIsUsed) {
+#ifdef FIX_BUGS
+ // skip if ID is still used by queued sample
+ bool skip = false;
+ for (uint8 j = 0; j < stillUsedEntitiesCount; j++) {
+ if (stillUsedEntities[j] == i) {
+ //debug("audio entity %i still used, skipping\n", i);
+ skip = true;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+#endif
+
m_asAudioEntities[i].m_bIsUsed = TRUE;
m_asAudioEntities[i].m_bStatus = FALSE;
m_asAudioEntities[i].m_nType = type;
@@ -936,39 +975,92 @@ cAudioManager::AddReleasingSounds()
if(sample.m_nCounter <= 255 || sample.m_nReflectionDelay == 0) // check if not delayed reflection
#endif
{
- if (sample.m_nFramesToPlay == 0)
+#ifdef ATTACH_RELEASING_SOUNDS_TO_ENTITIES
+ if (sample.m_nCounter <= 255 && !sample.m_bIs2D) { // check if not reflection and is a 3D sound
+ CEntity* entity = (CEntity*)GetEntityPointer(sample.m_nEntityIndex);
+ if (entity && m_asAudioEntities[sample.m_nEntityIndex].m_nType == AUDIOTYPE_PHYSICAL) {
+ sample.m_vecPos = entity->GetPosition();
+ float oldDistance = sample.m_fDistance;
+ sample.m_fDistance = Sqrt(GetDistanceSquared(sample.m_vecPos));
+ if (sample.m_nSampleIndex >= SAMPLEBANK_PED_START && sample.m_nSampleIndex <= SAMPLEBANK_PED_END) { // check if it's ped comment
+ uint8 vol;
+ if (CWorld::GetIsLineOfSightClear(TheCamera.GetPosition(), sample.m_vecPos, true, false, false, false, false, false))
+ vol = MAX_VOLUME;
+ else
+ vol = 31;
+#ifdef EXTERNAL_3D_SOUND
+ sample.m_nEmittingVolume = vol;
+#endif
+ sample.m_nVolume = ComputeVolume(vol, sample.m_MaxDistance, sample.m_fDistance);
+ } else {
+ // calculate new volume with changed distance
+ float volumeDiff = sq((sample.m_MaxDistance - sample.m_fDistance) / (sample.m_MaxDistance - oldDistance));
+ if (volumeDiff > 0.0f) {
+ uint8 newVolume = volumeDiff * sample.m_nVolume;
+ if (sample.m_nVolumeChange > 0)
+ sample.m_nVolumeChange = volumeDiff * sample.m_nVolumeChange;
+#if defined(FIX_BUGS) && defined(EXTERNAL_3D_SOUND)
+ if (sample.m_nEmittingVolumeChange > 0)
+ sample.m_nEmittingVolumeChange = volumeDiff * sample.m_nEmittingVolumeChange;
+#endif
+ sample.m_nVolume = Min(127, newVolume);
+ }
+ }
+ if (sample.m_nVolume == 0)
+ sample.m_nFramesToPlay = 0;
+ }
+ }
+#endif
+#ifdef FIX_BUGS
+ if (sample.m_nFramesToPlay <= 0)
continue;
if (sample.m_nLoopCount == 0) {
if (sample.m_nVolumeChange == -1) {
-#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)
sample.m_nVolumeChange = 1;
+#ifdef EXTERNAL_3D_SOUND
+ sample.m_nEmittingVolumeChange = sample.m_nEmittingVolume / sample.m_nFramesToPlay;
+ if (sample.m_nEmittingVolumeChange <= 0)
+ sample.m_nEmittingVolumeChange = 1;
+#endif
}
-#if defined(FIX_BUGS) && defined(EXTERNAL_3D_SOUND)
- if (sample.m_nEmittingVolume <= sample.m_nVolumeChange) {
+ if (sample.m_nVolume <= sample.m_nVolumeChange * CTimer::GetTimeStepFix()) {
+ sample.m_nFramesToPlay = 0;
+ continue;
+ }
+ sample.m_nVolume -= sample.m_nVolumeChange * CTimer::GetTimeStepFix();
+#ifdef EXTERNAL_3D_SOUND
+ if (sample.m_nEmittingVolume <= sample.m_nEmittingVolumeChange * CTimer::GetTimeStepFix()) {
+ sample.m_nFramesToPlay = 0;
+ continue;
+ }
+ sample.m_nEmittingVolume -= sample.m_nEmittingVolumeChange * CTimer::GetTimeStepFix();
+#endif
+ }
+ sample.m_nFramesToPlay -= CTimer::GetTimeStepFix();
+ if (sample.m_nFramesToPlay < 0)
+ sample.m_nFramesToPlay = 0;
#else
+ if (sample.m_nFramesToPlay == 0)
+ continue;
+ if (sample.m_nLoopCount == 0) {
+ if (sample.m_nVolumeChange == -1) {
+ sample.m_nVolumeChange = sample.m_nVolume / sample.m_nFramesToPlay;
+ if (sample.m_nVolumeChange <= 0)
+ sample.m_nVolumeChange = 1;
+ }
if (sample.m_nVolume <= sample.m_nVolumeChange) {
-#endif
sample.m_nFramesToPlay = 0;
continue;
}
-#if defined(FIX_BUGS) && defined(EXTERNAL_3D_SOUND)
- sample.m_nEmittingVolume -= sample.m_nVolumeChange;
-#else
sample.m_nVolume -= sample.m_nVolumeChange;
-#endif
}
-#ifdef FIX_BUGS
- if(CTimer::GetLogicalFramesPassed() != 0)
+ sample.m_nFramesToPlay--;
#endif
- --sample.m_nFramesToPlay;
if (m_bReduceReleasingPriority) {
if (sample.m_nPriority < 20)
- ++sample.m_nPriority;
+ sample.m_nPriority++;
}
sample.m_bStatic = FALSE;
}
@@ -1002,6 +1094,16 @@ cAudioManager::ProcessActiveQueues()
bool8 isPhoneCall;
uint8 channelOffset = 0;
+#ifdef EXTERNAL_3D_SOUND
+ #define WORKING_VOLUME_FIELD m_nEmittingVolume
+#else
+ #define WORKING_VOLUME_FIELD m_nVolume
+#endif
+
+#ifdef USE_TIME_SCALE_FOR_AUDIO
+ float timeScale = m_nUserPause ? 1.0f : CTimer::GetTimeScale();
+#endif
+
for (int32 i = 0; i < m_nActiveSamples; i++) {
m_asSamples[m_nActiveSampleQueue][i].m_bIsBeingPlayed = FALSE;
m_asActiveSamples[i].m_bIsBeingPlayed = FALSE;
@@ -1034,12 +1136,12 @@ cAudioManager::ProcessActiveQueues()
sample.m_nVolumeChange = -1;
if (!sample.m_bStatic) {
if (sample.m_bIs2D) {
-#ifdef EXTERNAL_3D_SOUND
- emittingVol = m_bDoubleVolume ? 2 * Min(63, sample.m_nEmittingVolume) : sample.m_nEmittingVolume;
+ emittingVol = m_bDoubleVolume ? 2 * Min(63, sample.WORKING_VOLUME_FIELD) : sample.WORKING_VOLUME_FIELD;
+#ifdef USE_TIME_SCALE_FOR_AUDIO
+ SampleManager.SetChannelFrequency(j, sample.m_nFrequency * timeScale);
#else
- emittingVol = m_bDoubleVolume ? 2 * Min(63, sample.m_nVolume) : sample.m_nVolume;
-#endif
SampleManager.SetChannelFrequency(j, sample.m_nFrequency);
+#endif
#ifdef EXTERNAL_3D_SOUND
SampleManager.SetChannelEmittingVolume(j, emittingVol);
#else
@@ -1047,24 +1149,6 @@ cAudioManager::ProcessActiveQueues()
SampleManager.SetChannelVolume(j, emittingVol);
#endif
} else {
-#ifdef ATTACH_PED_COMMENTS_TO_ENTITIES
- if (sample.m_nCounter <= 255 && sample.m_nSampleIndex >= SAMPLEBANK_PED_START && sample.m_nSampleIndex <= SAMPLEBANK_PED_END) {
- CEntity* entity = (CEntity*)GetEntityPointer(sample.m_nEntityIndex);
- if (entity && m_asAudioEntities[sample.m_nEntityIndex].m_nType == AUDIOTYPE_PHYSICAL) {
- sample.m_vecPos = entity->GetPosition();
- sample.m_fDistance = Sqrt(GetDistanceSquared(sample.m_vecPos));
- uint8 vol;
- if (CWorld::GetIsLineOfSightClear(TheCamera.GetPosition(), sample.m_vecPos, true, false, false, false, false, false))
- vol = MAX_VOLUME;
- else
- vol = 31;
-#ifdef EXTERNAL_3D_SOUND
- sample.m_nEmittingVolume = vol;
-#endif
- sample.m_nVolume = ComputeVolume(vol, sample.m_MaxDistance, sample.m_fDistance);
- }
- }
-#endif
position2 = sample.m_fDistance;
position1 = m_asActiveSamples[j].m_fDistance;
m_asActiveSamples[j].m_fDistance = sample.m_fDistance;
@@ -1072,7 +1156,11 @@ cAudioManager::ProcessActiveQueues()
if (sample.m_nFrequency != m_asActiveSamples[j].m_nFrequency) {
uint32 freq = Clamp2((int32)sample.m_nFrequency, (int32)m_asActiveSamples[j].m_nFrequency, 6000);
m_asActiveSamples[j].m_nFrequency = freq;
+#ifdef USE_TIME_SCALE_FOR_AUDIO
+ SampleManager.SetChannelFrequency(j, freq * timeScale);
+#else
SampleManager.SetChannelFrequency(j, freq);
+#endif
}
#ifdef EXTERNAL_3D_SOUND
if (sample.m_nEmittingVolume != m_asActiveSamples[j].m_nEmittingVolume) {
@@ -1160,18 +1248,18 @@ cAudioManager::ProcessActiveQueues()
m_asActiveSamples[j].m_nPan = ComputePan(m_asActiveSamples[j].m_fDistance, &position);
#endif
}
-#ifdef EXTERNAL_3D_SOUND
- emittingVol = m_bDoubleVolume ? 2 * Min(63, m_asActiveSamples[j].m_nEmittingVolume) : m_asActiveSamples[j].m_nEmittingVolume;
-#else
- emittingVol = m_bDoubleVolume ? 2 * Min(63, m_asActiveSamples[j].m_nVolume) : m_asActiveSamples[j].m_nVolume;
-#endif
+ emittingVol = m_bDoubleVolume ? 2 * Min(63, m_asActiveSamples[j].WORKING_VOLUME_FIELD) : m_asActiveSamples[j].WORKING_VOLUME_FIELD;
#ifdef GTA_PS2
{
SampleManager.InitialiseChannel(k, m_asActiveSamples[k].m_nSampleIndex, m_asActiveSamples[k].m_nBankIndex);
#else
if (SampleManager.InitialiseChannel(k, m_asActiveSamples[k].m_nSampleIndex, m_asActiveSamples[k].m_nBankIndex)) {
#endif
+#ifdef USE_TIME_SCALE_FOR_AUDIO
+ SampleManager.SetChannelFrequency(k, m_asActiveSamples[k].m_nFrequency * timeScale);
+#else
SampleManager.SetChannelFrequency(k, m_asActiveSamples[k].m_nFrequency);
+#endif
isPhoneCall = FALSE;
for (int32 l = 0; l < MISSION_AUDIO_SLOTS; l++) {
if (m_bIsMissionAudioPhoneCall[l]) {
@@ -1194,8 +1282,8 @@ cAudioManager::ProcessActiveQueues()
#endif
#ifndef GTA_PS2
SampleManager.SetChannelLoopPoints(k, m_asActiveSamples[k].m_nLoopStart, m_asActiveSamples[k].m_nLoopEnd);
- SampleManager.SetChannelLoopCount(k, m_asActiveSamples[k].m_nLoopCount);
#endif
+ SampleManager.SetChannelLoopCount(k, m_asActiveSamples[k].m_nLoopCount);
#if !defined(GTA_PS2) || defined(AUDIO_REVERB)
SampleManager.SetChannelReverbFlag(k, m_asActiveSamples[k].m_bReverb);
#endif
@@ -1232,10 +1320,20 @@ cAudioManager::ProcessActiveQueues()
}
}
}
+
#ifdef GTA_PS2
m_nChannelOffset += channelOffset;
#endif
m_nChannelOffset %= m_nActiveSamples;
+
+#ifdef USE_TIME_SCALE_FOR_AUDIO
+ for (uint8 i = 0; i < m_nActiveSamples; i++) {
+ if (m_asActiveSamples[i].m_nSampleIndex != NO_SAMPLE && m_asActiveSamples[i].m_bIsBeingPlayed)
+ SampleManager.SetChannelFrequency(i, m_asActiveSamples[i].m_nFrequency * timeScale);
+ }
+#endif
+
+#undef WORKING_VOLUME_FIELD
}
void