diff --git a/LEGO1/lego/legoomni/include/lego3dsound.h b/LEGO1/lego/legoomni/include/lego3dsound.h index e52c249b..dc7840a3 100644 --- a/LEGO1/lego/legoomni/include/lego3dsound.h +++ b/LEGO1/lego/legoomni/include/lego3dsound.h @@ -20,6 +20,7 @@ public: MxResult Create(LPDIRECTSOUNDBUFFER p_directSoundBuffer, const char* p_name, MxS32 p_volume); void Destroy(); MxU32 UpdatePosition(LPDIRECTSOUNDBUFFER p_directSoundBuffer); + void FUN_10011a60(LPDIRECTSOUNDBUFFER p_directSoundBuffer, const char* p_name); void Reset(); MxS32 SetDistance(MxS32 p_min, MxS32 p_max); diff --git a/LEGO1/lego/legoomni/include/legocachesoundmanager.h b/LEGO1/lego/legoomni/include/legocachesoundmanager.h index 8297b416..0856aa70 100644 --- a/LEGO1/lego/legoomni/include/legocachesoundmanager.h +++ b/LEGO1/lego/legoomni/include/legocachesoundmanager.h @@ -56,11 +56,12 @@ public: LegoCacheSound* FindSoundByKey(const char* p_key); LegoCacheSound* ManageSoundEntry(LegoCacheSound* p_sound); - LegoCacheSound* FUN_1003dae0(const char* p_one, const char* p_two, MxBool p_three); - LegoCacheSound* FUN_1003db10(LegoCacheSound* p_one, const char* p_two, MxBool p_three); - void FUN_1003dc40(LegoCacheSound** p_und); + LegoCacheSound* Play(const char* p_key, const char* p_name, MxBool p_looping); + void Destroy(LegoCacheSound*& p_sound); private: + LegoCacheSound* Play(LegoCacheSound* p_sound, const char* p_name, MxBool p_looping); + Set100d6b4c m_set; // 0x04 List100d6b4c m_list; // 0x14 }; diff --git a/LEGO1/lego/legoomni/include/legocachsound.h b/LEGO1/lego/legoomni/include/legocachsound.h index 10d0108b..b80ded36 100644 --- a/LEGO1/lego/legoomni/include/legocachsound.h +++ b/LEGO1/lego/legoomni/include/legocachsound.h @@ -37,10 +37,10 @@ public: virtual void FUN_10006cd0(undefined4, undefined4); // vtable+0x1c inline const MxString& GetUnknown0x48() const { return m_unk0x48; } - inline const undefined GetUnknown0x58() const { return m_unk0x58; } + inline const MxBool GetUnknown0x58() const { return m_unk0x58; } - LegoCacheSound* FUN_10006960(); - MxResult FUN_10006a30(const char* p_str, MxBool); + LegoCacheSound* Clone(); + MxResult Play(const char* p_name, MxBool p_looping); void FUN_10006b80(); void FUN_10006be0(); void SetDistance(MxS32 p_min, MxS32 p_max); @@ -59,12 +59,12 @@ private: MxU8* m_data; // 0x40 MxU32 m_dataSize; // 0x44 MxString m_unk0x48; // 0x48 - undefined m_unk0x58; // 0x58 + MxBool m_unk0x58; // 0x58 PCMWAVEFORMAT m_wfx; // 0x59 - MxBool m_isLooping; // 0x69 + MxBool m_looping; // 0x69 MxBool m_unk0x6a; // 0x6a MxS32 m_volume; // 0x6c - undefined m_unk0x70; // 0x70 + MxBool m_unk0x70; // 0x70 MxString m_unk0x74; // 0x74 undefined m_unk0x84; // 0x84 }; diff --git a/LEGO1/lego/legoomni/src/audio/lego3dsound.cpp b/LEGO1/lego/legoomni/src/audio/lego3dsound.cpp index f2da166c..508cd395 100644 --- a/LEGO1/lego/legoomni/src/audio/lego3dsound.cpp +++ b/LEGO1/lego/legoomni/src/audio/lego3dsound.cpp @@ -151,7 +151,6 @@ MxU32 Lego3DSound::UpdatePosition(LPDIRECTSOUNDBUFFER p_directSoundBuffer) } else { MxS32 newVolume = m_volume; - if (distance < 100.0f) { newVolume = m_volume; } @@ -184,6 +183,101 @@ MxU32 Lego3DSound::UpdatePosition(LPDIRECTSOUNDBUFFER p_directSoundBuffer) return updated; } +// FUNCTION: LEGO1 0x10011a60 +// FUNCTION: BETA10 0x10039d04 +void Lego3DSound::FUN_10011a60(LPDIRECTSOUNDBUFFER p_directSoundBuffer, const char* p_name) +{ + assert(p_directSoundBuffer); + + if (p_name == NULL) { + if (m_ds3dBuffer != NULL) { + m_ds3dBuffer->SetMode(DS3DMODE_DISABLE, DS3D_IMMEDIATE); + } + } + else { + if (CharacterManager()->IsActor(p_name)) { + m_roi = CharacterManager()->GetActorROI(p_name, TRUE); + m_enabled = m_isActor = TRUE; + } + else { + m_roi = FindROI(p_name); + } + + if (m_roi == NULL) { + m_roi = CharacterManager()->CreateAutoROI(NULL, p_name, TRUE); + + if (m_roi != NULL) { + m_enabled = TRUE; + } + } + + if (m_roi == NULL) { + return; + } + + if (m_isActor) { + m_positionROI = m_roi->FindChildROI("head", m_roi); + } + else { + m_positionROI = m_roi; + } + + if (m_ds3dBuffer != NULL) { + DWORD dwMode; + m_ds3dBuffer->GetMode(&dwMode); + + if (dwMode & DS3DMODE_DISABLE) { + m_ds3dBuffer->SetMode(DS3DMODE_NORMAL, DS3D_IMMEDIATE); + } + + const float* position = m_positionROI->GetWorldPosition(); + m_ds3dBuffer->SetPosition(position[0], position[1], position[2], DS3D_IMMEDIATE); + } + else { + const float* position = m_positionROI->GetWorldPosition(); + ViewROI* pov = VideoManager()->GetViewROI(); + + if (pov != NULL) { + const float* povPosition = pov->GetWorldPosition(); + float distance = DISTSQRD3(povPosition, position); + + MxS32 newVolume; + if (distance < 100.0f) { + newVolume = m_volume; + } + else if (distance < 400.0f) { + newVolume = m_volume * 0.4; + } + else if (distance < 3600.0f) { + newVolume = m_volume * 0.1; + } + else { + newVolume = 0; + } + + newVolume = newVolume * SoundManager()->GetVolume() / 100; + newVolume = SoundManager()->GetAttenuation(newVolume); + p_directSoundBuffer->SetVolume(newVolume); + } + } + + LegoEntity* entity = m_roi->GetEntity(); + if (entity != NULL && entity->IsA("LegoActor") && ((LegoActor*) entity)->GetSoundFrequencyFactor() != 0.0f) { + m_actor = ((LegoActor*) entity); + } + + p_directSoundBuffer->GetFrequency(&m_dwFrequency); + + if (m_actor != NULL) { + m_frequencyFactor = m_actor->GetSoundFrequencyFactor(); + + if (m_frequencyFactor != 0.0) { + p_directSoundBuffer->SetFrequency(m_frequencyFactor * m_dwFrequency); + } + } + } +} + // FUNCTION: LEGO1 0x10011ca0 void Lego3DSound::Reset() { diff --git a/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp b/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp index 6628246b..36445ce7 100644 --- a/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp +++ b/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp @@ -104,53 +104,48 @@ LegoCacheSound* LegoCacheSoundManager::ManageSoundEntry(LegoCacheSound* p_sound) } // FUNCTION: LEGO1 0x1003dae0 -LegoCacheSound* LegoCacheSoundManager::FUN_1003dae0(const char* p_one, const char* p_two, MxBool p_three) +LegoCacheSound* LegoCacheSoundManager::Play(const char* p_key, const char* p_name, MxBool p_looping) { - // DECOMP: Second parameter is LegoRoi::m_name (0xe4) - return FUN_1003db10(FindSoundByKey(p_one), p_two, p_three); + return Play(FindSoundByKey(p_key), p_name, p_looping); } // FUNCTION: LEGO1 0x1003db10 -LegoCacheSound* LegoCacheSoundManager::FUN_1003db10(LegoCacheSound* p_one, const char* p_two, MxBool p_three) +LegoCacheSound* LegoCacheSoundManager::Play(LegoCacheSound* p_sound, const char* p_name, MxBool p_looping) { - if (!p_one) { + if (!p_sound) { return NULL; } - if (p_one->GetUnknown0x58()) { - LegoCacheSound* result = p_one->FUN_10006960(); + if (p_sound->GetUnknown0x58()) { + LegoCacheSound* clone = p_sound->Clone(); - if (result) { - LegoCacheSound* t = ManageSoundEntry(result); - t->FUN_10006a30(p_two, p_three); - return t; + if (clone) { + LegoCacheSound* sound = ManageSoundEntry(clone); + sound->Play(p_name, p_looping); + return sound; } } else { - p_one->FUN_10006a30(p_two, p_three); - return p_one; + p_sound->Play(p_name, p_looping); + return p_sound; } return NULL; } // FUNCTION: LEGO1 0x1003dc40 -void LegoCacheSoundManager::FUN_1003dc40(LegoCacheSound** p_und) +void LegoCacheSoundManager::Destroy(LegoCacheSound*& p_sound) { - // Called during LegoWorld::Destroy like this: - // SoundManager()->GetCacheSoundManager()->FUN_1003dc40(&sound); - // LegoCacheSound*& p_sound? - #ifdef COMPAT_MODE Set100d6b4c::iterator setIter; for (setIter = m_set.begin(); setIter != m_set.end(); setIter++) { #else for (Set100d6b4c::iterator setIter = m_set.begin(); setIter != m_set.end(); setIter++) { #endif - if ((*setIter).GetSound() == *p_und) { - (*p_und)->FUN_10006b80(); + if ((*setIter).GetSound() == p_sound) { + p_sound->FUN_10006b80(); - delete *p_und; + delete p_sound; m_set.erase(setIter); return; } @@ -167,8 +162,8 @@ void LegoCacheSoundManager::FUN_1003dc40(LegoCacheSound** p_und) } LegoCacheSound* sound = (*listIter).GetSound(); - if (sound == *p_und) { - (*p_und)->FUN_10006b80(); + if (sound == p_sound) { + p_sound->FUN_10006b80(); delete sound; m_list.erase(listIter); diff --git a/LEGO1/lego/legoomni/src/audio/legocachsound.cpp b/LEGO1/lego/legoomni/src/audio/legocachsound.cpp index 19ba06f3..457e51f4 100644 --- a/LEGO1/lego/legoomni/src/audio/legocachsound.cpp +++ b/LEGO1/lego/legoomni/src/audio/legocachsound.cpp @@ -23,11 +23,11 @@ void LegoCacheSound::Init() { m_dsBuffer = NULL; m_data = NULL; - m_unk0x58 = 0; + m_unk0x58 = FALSE; memset(&m_wfx, 0, sizeof(m_wfx)); m_unk0x6a = FALSE; - m_unk0x70 = 0; - m_isLooping = TRUE; + m_unk0x70 = FALSE; + m_looping = TRUE; m_volume = 79; m_unk0x84 = 0; } @@ -114,22 +114,69 @@ void LegoCacheSound::Destroy() Init(); } -// STUB: LEGO1 0x10006960 -LegoCacheSound* LegoCacheSound::FUN_10006960() +// FUNCTION: LEGO1 0x10006960 +// FUNCTION: BETA10 0x100668cf +LegoCacheSound* LegoCacheSound::Clone() { - // TODO + LegoCacheSound* pnew = new LegoCacheSound(); + + if (pnew->Create(&m_wfx, m_unk0x48, m_volume, m_data, m_dataSize) == SUCCESS) { + return pnew; + } + + delete pnew; return NULL; } -// STUB: LEGO1 0x10006a30 -MxResult LegoCacheSound::FUN_10006a30(const char* p_str, MxBool) +// FUNCTION: LEGO1 0x10006a30 +// FUNCTION: BETA10 0x10066a23 +MxResult LegoCacheSound::Play(const char* p_name, MxBool p_looping) { - // TODO - // gets param2 from FUN_1003db10 - if (m_data == NULL && m_dataSize == 0) { + if (m_data == NULL || m_dataSize == 0) { return FAILURE; } + m_unk0x6a = FALSE; + m_sound.FUN_10011a60(m_dsBuffer, p_name); + + if (p_name != NULL) { + m_unk0x74 = p_name; + } + + DWORD dwStatus; + m_dsBuffer->GetStatus(&dwStatus); + + if (dwStatus == DSBSTATUS_BUFFERLOST) { + m_dsBuffer->Restore(); + m_dsBuffer->GetStatus(&dwStatus); + } + + if (dwStatus != DSBSTATUS_BUFFERLOST) { + LPVOID pvAudioPtr1, pvAudioPtr2; + DWORD dwAudioBytes1, dwAudioBytes2; + + if (m_dsBuffer->Lock(0, m_dataSize, &pvAudioPtr1, &dwAudioBytes1, &pvAudioPtr2, &dwAudioBytes2, 0) == DS_OK) { + memcpy(pvAudioPtr1, m_data, dwAudioBytes1); + + if (dwAudioBytes2 != 0) { + memcpy(pvAudioPtr2, m_data + dwAudioBytes1, dwAudioBytes2); + } + + m_dsBuffer->Unlock(pvAudioPtr1, dwAudioBytes1, pvAudioPtr2, dwAudioBytes2); + m_dsBuffer->SetCurrentPosition(0); + m_dsBuffer->Play(0, 0, p_looping); + } + } + + if (p_looping == FALSE) { + m_looping = FALSE; + } + else { + m_looping = TRUE; + } + + m_unk0x58 = TRUE; + m_unk0x70 = TRUE; return SUCCESS; } @@ -137,13 +184,13 @@ MxResult LegoCacheSound::FUN_10006a30(const char* p_str, MxBool) void LegoCacheSound::FUN_10006b80() { DWORD dwStatus; - m_dsBuffer->GetStatus(&dwStatus); + if (dwStatus) { m_dsBuffer->Stop(); } - m_unk0x58 = 0; + m_unk0x58 = FALSE; m_unk0x6a = FALSE; m_sound.Reset(); @@ -155,7 +202,7 @@ void LegoCacheSound::FUN_10006b80() // FUNCTION: LEGO1 0x10006be0 void LegoCacheSound::FUN_10006be0() { - if (!m_isLooping) { + if (!m_looping) { DWORD dwStatus; m_dsBuffer->GetStatus(&dwStatus); @@ -164,7 +211,7 @@ void LegoCacheSound::FUN_10006be0() return; } - m_unk0x70 = 0; + m_unk0x70 = FALSE; } if (dwStatus == 0) { @@ -174,7 +221,7 @@ void LegoCacheSound::FUN_10006be0() m_unk0x74 = ""; } - m_unk0x58 = 0; + m_unk0x58 = FALSE; return; } } @@ -189,7 +236,7 @@ void LegoCacheSound::FUN_10006be0() m_unk0x6a = TRUE; } else if (m_unk0x6a) { - m_dsBuffer->Play(0, 0, m_isLooping); + m_dsBuffer->Play(0, 0, m_looping); m_unk0x6a = FALSE; } } diff --git a/LEGO1/lego/legoomni/src/entity/legoactor.cpp b/LEGO1/lego/legoomni/src/entity/legoactor.cpp index 6ab78b63..d7d79e1a 100644 --- a/LEGO1/lego/legoomni/src/entity/legoactor.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoactor.cpp @@ -103,7 +103,7 @@ void LegoActor::ParseAction(char* p_extra) } if (KeyValueStringParse(value, g_strSOUND, p_extra)) { - m_sound = SoundManager()->GetCacheSoundManager()->FUN_1003dae0(value, GetROI()->GetName(), TRUE); + m_sound = SoundManager()->GetCacheSoundManager()->Play(value, GetROI()->GetName(), TRUE); } if (KeyValueStringParse(value, g_strMUTE, p_extra)) { diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index fcec9fdd..fecff1de 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -204,7 +204,7 @@ void LegoWorld::Destroy(MxBool p_fromDestructor) while (cursor.First(sound)) { cursor.Detach(); - SoundManager()->GetCacheSoundManager()->FUN_1003dc40(&sound); + SoundManager()->GetCacheSoundManager()->Destroy(sound); } delete m_cacheSoundList; diff --git a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp index e1eeedbe..f0e2e69b 100644 --- a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp @@ -233,7 +233,7 @@ MxResult LegoExtraActor::VTable0x94(LegoPathActor* p_actor, MxBool p_bool) m_roi->FUN_100a58f0(matrix2); m_roi->VTable0x14(); FUN_1002ad8a(); - SoundManager()->GetCacheSoundManager()->FUN_1003dae0("crash5", m_roi->GetName(), FALSE); + SoundManager()->GetCacheSoundManager()->Play("crash5", m_roi->GetName(), FALSE); m_scheduledTime = Timer()->GetTime() + m_disAnim->GetDuration(); m_prevWorldSpeed = m_worldSpeed; VTable0xc4(); @@ -245,7 +245,7 @@ MxResult LegoExtraActor::VTable0x94(LegoPathActor* p_actor, MxBool p_bool) if (b) { LegoROI* roi = m_roi; - SoundManager()->GetCacheSoundManager()->FUN_1003dae0("crash5", m_roi->GetName(), FALSE); + SoundManager()->GetCacheSoundManager()->Play("crash5", m_roi->GetName(), FALSE); VTable0xc4(); m_state = 0x102; Mx3DPointFloat dir = p_actor->GetWorldDirection(); diff --git a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp index 430914b2..454f04fb 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp @@ -278,7 +278,7 @@ MxS32 LegoPathActor::VTable0x8c(float p_time, Matrix4& p_transform) const char* var = VariableTable()->GetVariable(g_strHIT_WALL_SOUND); if (var && var[0] != 0) { - SoundManager()->GetCacheSoundManager()->FUN_1003dae0(var, NULL, FALSE); + SoundManager()->GetCacheSoundManager()->Play(var, NULL, FALSE); } }