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);
 						}
 					}