Initial commit
This commit is contained in:
919
engines/hpl1/engine/sound/SoundHandler.cpp
Normal file
919
engines/hpl1/engine/sound/SoundHandler.cpp
Normal file
@@ -0,0 +1,919 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#include "hpl1/engine/sound/SoundHandler.h"
|
||||
#include "hpl1/engine/math/Math.h"
|
||||
#include "hpl1/engine/resources/Resources.h"
|
||||
#include "hpl1/engine/resources/SoundManager.h"
|
||||
#include "hpl1/engine/sound/LowLevelSound.h"
|
||||
#include "hpl1/engine/sound/SoundChannel.h"
|
||||
#include "hpl1/engine/sound/SoundData.h"
|
||||
#include "hpl1/engine/system/String.h"
|
||||
#include "hpl1/engine/system/low_level_system.h"
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsBody.h"
|
||||
#include "hpl1/engine/physics/PhysicsWorld.h"
|
||||
#include "hpl1/engine/scene/World3D.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CONSTRUCTORS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cSoundHandler::cSoundHandler(iLowLevelSound *apLowLevelSound, cResources *apResources) {
|
||||
mpLowLevelSound = apLowLevelSound;
|
||||
mpResources = apResources;
|
||||
|
||||
mfSpeed = 1;
|
||||
mfNewSpeed = 1;
|
||||
mfSpeedRate = 0;
|
||||
mfVolume = 1;
|
||||
mfNewVolume = 1;
|
||||
mfVolumeRate = 0;
|
||||
|
||||
mpWorld3D = NULL;
|
||||
|
||||
mlCount = 0;
|
||||
mlIdCount = 0;
|
||||
|
||||
mbSilent = false;
|
||||
|
||||
mAffectedBySpeed = eSoundDest_World;
|
||||
mAffectedByVolume = eSoundDest_World;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cSoundHandler::~cSoundHandler() {
|
||||
tSoundEntryListIt it;
|
||||
it = mlstGuiSounds.begin();
|
||||
while (it != mlstGuiSounds.end()) {
|
||||
it->mpSound->Stop();
|
||||
hplDelete(it->mpSound);
|
||||
it = mlstGuiSounds.erase(it);
|
||||
}
|
||||
|
||||
it = mlstWorldSounds.begin();
|
||||
while (it != mlstWorldSounds.end()) {
|
||||
it->mpSound->Stop();
|
||||
hplDelete(it->mpSound);
|
||||
it = mlstWorldSounds.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void cSoundRayCallback::Reset() {
|
||||
mbHasCollided = false;
|
||||
}
|
||||
|
||||
bool cSoundRayCallback::BeforeIntersect(iPhysicsBody *pBody) {
|
||||
if (pBody->GetBlocksSound())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
bool cSoundRayCallback::OnIntersect(iPhysicsBody *pBody, cPhysicsRayParams *apParams) {
|
||||
mbHasCollided = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSoundEntry::Update(float afTimeStep) {
|
||||
if (mfNormalVolumeMul != mfNormalVolumeFadeDest) {
|
||||
// Log("speed %s: %f\n", msName.c_str(),mfNormalVolumeFadeSpeed);
|
||||
|
||||
mfNormalVolumeMul += mfNormalVolumeFadeSpeed * afTimeStep;
|
||||
|
||||
if (mfNormalVolumeMul < 0)
|
||||
mfNormalVolumeMul = 0;
|
||||
if (mfNormalVolumeMul > 1)
|
||||
mfNormalVolumeMul = 1;
|
||||
|
||||
if (mfNormalVolumeFadeSpeed < 0) {
|
||||
if (mfNormalVolumeMul <= mfNormalVolumeFadeDest) {
|
||||
mfNormalVolumeMul = mfNormalVolumeFadeDest;
|
||||
}
|
||||
} else {
|
||||
if (mfNormalVolumeMul >= mfNormalVolumeFadeDest) {
|
||||
mfNormalVolumeMul = mfNormalVolumeFadeDest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ABS(mfNormalVolumeFadeDest) < 0.001f && ABS(mfNormalVolumeMul) < 0.001f && mfNormalVolumeFadeSpeed <= 0) {
|
||||
mpSound->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSoundChannel *cSoundHandler::Play(const tString &asName, bool abLoop, float afVolume, const cVector3f &avPos,
|
||||
float afMinDist, float afMaxDist, eSoundDest mType, bool abRelative, bool ab3D, int alPriorityModifier,
|
||||
eSoundDest aEffectType) {
|
||||
if (asName == "")
|
||||
return NULL;
|
||||
|
||||
// Calculate priority
|
||||
int lPrio = 255;
|
||||
if (mType == eSoundDest_World && !abRelative) {
|
||||
lPrio = alPriorityModifier;
|
||||
|
||||
float fDist = cMath::Vector3Dist(avPos, mpLowLevelSound->GetListenerPosition());
|
||||
if (fDist >= afMaxDist)
|
||||
lPrio += 0;
|
||||
else if (fDist >= afMinDist)
|
||||
lPrio += 10;
|
||||
else
|
||||
lPrio += 100;
|
||||
}
|
||||
|
||||
// Create sound channel
|
||||
iSoundChannel *pSound = CreateChannel(asName, lPrio);
|
||||
if (pSound == NULL) {
|
||||
Warning("Can't find sound '%s' (may also be due too many sounds playing).\n", asName.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Set up channel
|
||||
pSound->SetLooping(abLoop);
|
||||
pSound->SetMinDistance(afMinDist);
|
||||
pSound->SetMaxDistance(afMaxDist);
|
||||
pSound->Set3D(ab3D);
|
||||
pSound->SetPriority(lPrio);
|
||||
|
||||
/////// NEW -- Set sound to use Environment if its a world sound
|
||||
|
||||
if (aEffectType == eSoundDest_World)
|
||||
pSound->SetAffectedByEnv(true);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
if (mType == eSoundDest_Gui) {
|
||||
pSound->SetPositionRelative(true);
|
||||
// pSound->SetPosition(avPos);
|
||||
pSound->SetRelPosition(avPos);
|
||||
|
||||
cVector3f vPos = cMath::MatrixMul(mpLowLevelSound->GetListenerMatrix(), avPos);
|
||||
pSound->SetPosition(vPos);
|
||||
|
||||
// Needed?
|
||||
// pSound->SetPosition(mpLowLevelSound->GetListenerPosition() +
|
||||
// pSound->GetRelPosition());
|
||||
} else {
|
||||
|
||||
pSound->SetPositionRelative(abRelative);
|
||||
if (abRelative) {
|
||||
pSound->SetRelPosition(avPos);
|
||||
cVector3f vPos = cMath::MatrixMul(mpLowLevelSound->GetListenerMatrix(), avPos);
|
||||
pSound->SetPosition(vPos);
|
||||
} else {
|
||||
pSound->SetPosition(avPos);
|
||||
}
|
||||
}
|
||||
|
||||
pSound->SetId(mlIdCount);
|
||||
|
||||
cSoundEntry Entry;
|
||||
Entry.mpSound = pSound;
|
||||
Entry.mfNormalVolume = afVolume;
|
||||
Entry.msName = asName;
|
||||
Entry.mfNormalSpeed = 1.0f;
|
||||
|
||||
Entry.mfBlockFadeDest = 1;
|
||||
Entry.mfBlockFadeSpeed = 1;
|
||||
Entry.mfBlockMul = 1;
|
||||
Entry.mbFirstTime = true;
|
||||
|
||||
Entry.mEffectType = aEffectType;
|
||||
|
||||
////////////////////////
|
||||
// Set start volume
|
||||
// GUI
|
||||
if (mType == eSoundDest_Gui) {
|
||||
pSound->SetVolume(afVolume);
|
||||
}
|
||||
// World
|
||||
else {
|
||||
pSound->SetVolume(0);
|
||||
// UpdateDistanceVolume3D(&Entry,1.0f/60.0f,false,mType);
|
||||
}
|
||||
|
||||
// If it is silent do everything as normal except stop the sound at start.
|
||||
if (mbSilent) {
|
||||
pSound->SetLooping(false);
|
||||
pSound->Stop();
|
||||
} else {
|
||||
pSound->Play();
|
||||
}
|
||||
|
||||
if (mType == eSoundDest_Gui) {
|
||||
mlstGuiSounds.push_back(Entry);
|
||||
} else {
|
||||
mlstWorldSounds.push_back(Entry);
|
||||
}
|
||||
|
||||
// Log("Starting sound '%s' prio: %d\n", pSound->GetData()->GetName().c_str(),
|
||||
// pSound->GetPriority());
|
||||
|
||||
mlIdCount++;
|
||||
|
||||
return pSound;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSoundChannel *cSoundHandler::PlayGui(const tString &asName, bool abLoop, float afVolume, const cVector3f &avPos,
|
||||
eSoundDest aEffectType) {
|
||||
return Play(asName, abLoop, afVolume, avPos, 1.0f, 1000.0f, eSoundDest_Gui, true, false, 0, aEffectType);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSoundChannel *cSoundHandler::PlayStream(const tString &asFileName, bool abLoop, float afVolume, bool ab3D, eSoundDest aEffectType) {
|
||||
if (asFileName == "")
|
||||
return NULL;
|
||||
|
||||
iSoundData *pData = mpResources->GetSoundManager()->CreateSoundData(asFileName, true, abLoop);
|
||||
if (pData == NULL) {
|
||||
Error("Couldn't load stream '%s'\n", asFileName.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
iSoundChannel *pSound = pData->CreateChannel(256);
|
||||
if (!pSound) {
|
||||
Error("Can't create sound channel for '%s'\n", asFileName.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// If it is silent do everything as normal except stop the sound at start.
|
||||
if (mbSilent) {
|
||||
// pSound->SetLooping(false);
|
||||
pSound->Stop();
|
||||
} else {
|
||||
pSound->Play();
|
||||
}
|
||||
|
||||
pSound->SetId(mlIdCount);
|
||||
|
||||
pSound->Set3D(ab3D);
|
||||
|
||||
cSoundEntry Entry;
|
||||
Entry.mpSound = pSound;
|
||||
Entry.mfNormalVolume = afVolume;
|
||||
Entry.msName = asFileName;
|
||||
Entry.mfNormalSpeed = 1.0f;
|
||||
|
||||
Entry.mfBlockFadeDest = 1;
|
||||
Entry.mfBlockFadeSpeed = 1;
|
||||
Entry.mfBlockMul = 1;
|
||||
Entry.mbFirstTime = true;
|
||||
|
||||
Entry.mbStream = true;
|
||||
|
||||
Entry.mEffectType = aEffectType;
|
||||
|
||||
/////////////////////////
|
||||
// Setup position
|
||||
pSound->SetPositionRelative(true);
|
||||
pSound->SetRelPosition(cVector3f(0, 0, 1));
|
||||
cVector3f vPos = cMath::MatrixMul(mpLowLevelSound->GetListenerMatrix(),
|
||||
pSound->GetRelPosition());
|
||||
pSound->SetPosition(vPos);
|
||||
|
||||
mlstGuiSounds.push_back(Entry);
|
||||
|
||||
mlIdCount++;
|
||||
|
||||
return pSound;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool cSoundHandler::Stop(const tString &asName) {
|
||||
cSoundEntry *pEntry = GetEntry(asName);
|
||||
if (pEntry) {
|
||||
pEntry->mpSound->Stop();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool cSoundHandler::StopAllExcept(const tString &asName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSoundHandler::StopAll(tFlag mTypes) {
|
||||
tSoundEntryListIt it;
|
||||
if (mTypes & eSoundDest_Gui) {
|
||||
it = mlstGuiSounds.begin();
|
||||
while (it != mlstGuiSounds.end()) {
|
||||
it->mpSound->SetPaused(false);
|
||||
it->mpSound->Stop();
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
if (mTypes & eSoundDest_World) {
|
||||
it = mlstWorldSounds.begin();
|
||||
while (it != mlstWorldSounds.end()) {
|
||||
// Log("Stopping: %s\n",it->mpSound->GetData()->GetName().c_str());
|
||||
it->mpSound->SetPaused(false);
|
||||
it->mpSound->Stop();
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSoundHandler::PauseAll(tFlag mTypes) {
|
||||
tSoundEntryListIt it;
|
||||
if (mTypes & eSoundDest_Gui) {
|
||||
it = mlstGuiSounds.begin();
|
||||
while (it != mlstGuiSounds.end()) {
|
||||
it->mpSound->SetPaused(true);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
if (mTypes & eSoundDest_World) {
|
||||
it = mlstWorldSounds.begin();
|
||||
while (it != mlstWorldSounds.end()) {
|
||||
it->mpSound->SetPaused(true);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSoundHandler::ResumeAll(tFlag mTypes) {
|
||||
tSoundEntryListIt it;
|
||||
if (mTypes & eSoundDest_Gui) {
|
||||
it = mlstGuiSounds.begin();
|
||||
while (it != mlstGuiSounds.end()) {
|
||||
it->mpSound->SetPaused(false);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
if (mTypes & eSoundDest_World) {
|
||||
it = mlstWorldSounds.begin();
|
||||
while (it != mlstWorldSounds.end()) {
|
||||
it->mpSound->SetPaused(false);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool cSoundHandler::IsPlaying(const tString &asName) {
|
||||
cSoundEntry *pEntry = GetEntry(asName);
|
||||
|
||||
if (pEntry)
|
||||
return pEntry->mpSound->IsPlaying();
|
||||
|
||||
return false;
|
||||
}
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool cSoundHandler::IsValid(iSoundChannel *apChannel) {
|
||||
tSoundEntryListIt it;
|
||||
it = mlstWorldSounds.begin();
|
||||
while (it != mlstWorldSounds.end()) {
|
||||
if (it->mpSound == apChannel)
|
||||
return true;
|
||||
it++;
|
||||
}
|
||||
|
||||
it = mlstGuiSounds.begin();
|
||||
while (it != mlstGuiSounds.end()) {
|
||||
if (it->mpSound == apChannel)
|
||||
return true;
|
||||
it++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool cSoundHandler::IsValidId(iSoundChannel *apChannel, int alId) {
|
||||
if (apChannel == NULL)
|
||||
return false;
|
||||
|
||||
tSoundEntryListIt it = mlstWorldSounds.begin();
|
||||
while (it != mlstWorldSounds.end()) {
|
||||
if (it->mpSound == apChannel && it->mpSound->GetId() == alId)
|
||||
return true;
|
||||
it++;
|
||||
}
|
||||
|
||||
it = mlstGuiSounds.begin();
|
||||
while (it != mlstGuiSounds.end()) {
|
||||
if (it->mpSound == apChannel && it->mpSound->GetId() == alId)
|
||||
return true;
|
||||
it++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSoundHandler::Update(float afTimeStep) {
|
||||
if (mfNewSpeed != mfSpeed) {
|
||||
mfSpeed += mfSpeedRate;
|
||||
if (mfSpeedRate < 0 && mfSpeed < mfNewSpeed)
|
||||
mfSpeed = mfNewSpeed;
|
||||
if (mfSpeedRate > 0 && mfSpeed > mfNewSpeed)
|
||||
mfSpeed = mfNewSpeed;
|
||||
}
|
||||
|
||||
if (mfNewVolume != mfVolume) {
|
||||
mfVolume += mfVolumeRate * afTimeStep;
|
||||
if (mfVolumeRate < 0 && mfVolume < mfNewVolume)
|
||||
mfVolume = mfNewVolume;
|
||||
if (mfVolumeRate > 0 && mfVolume > mfNewVolume)
|
||||
mfVolume = mfNewVolume;
|
||||
}
|
||||
|
||||
tSoundEntryListIt it;
|
||||
it = mlstGuiSounds.begin();
|
||||
while (it != mlstGuiSounds.end()) {
|
||||
if (UpdateEntry(&(*it), afTimeStep, eSoundDest_Gui) == false) {
|
||||
it = mlstGuiSounds.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
it = mlstWorldSounds.begin();
|
||||
while (it != mlstWorldSounds.end()) {
|
||||
if (UpdateEntry(&(*it), afTimeStep, eSoundDest_World) == false) {
|
||||
it = mlstWorldSounds.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
mlCount++;
|
||||
}
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
*
|
||||
* \todo support types.
|
||||
* \param afSpeed New speed to run sounds at
|
||||
* \param afRate Rate by which the current speed transform to the new
|
||||
* \param mTypes Types affected, not working yet :S
|
||||
*/
|
||||
void cSoundHandler::SetSpeed(float afSpeed, float afRate, tFlag aTypes) {
|
||||
mfNewSpeed = afSpeed;
|
||||
|
||||
if (mfNewSpeed > mfSpeed && afRate < 0)
|
||||
afRate = -afRate;
|
||||
if (mfNewSpeed < mfSpeed && afRate > 0)
|
||||
afRate = -afRate;
|
||||
|
||||
mfSpeedRate = afRate;
|
||||
|
||||
mAffectedBySpeed = aTypes;
|
||||
|
||||
if (afRate == 0)
|
||||
mfSpeed = mfNewSpeed;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSoundHandler::SetVolume(float afVolume, float afRate, tFlag aTypes) {
|
||||
mfNewVolume = afVolume;
|
||||
|
||||
if (mfNewVolume > mfVolume && afRate < 0)
|
||||
afRate = -afRate;
|
||||
if (mfNewVolume < mfVolume && afRate > 0)
|
||||
afRate = -afRate;
|
||||
|
||||
mfVolumeRate = afRate;
|
||||
|
||||
mAffectedByVolume = aTypes;
|
||||
|
||||
if (afRate == 0)
|
||||
mfVolume = mfNewVolume;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSoundHandler::SetWorld3D(cWorld3D *apWorld3D) {
|
||||
mpWorld3D = apWorld3D;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cSoundEntry *cSoundHandler::GetEntryFromSound(iSoundChannel *apSound) {
|
||||
tSoundEntryListIt it = mlstGuiSounds.begin();
|
||||
while (it != mlstGuiSounds.end()) {
|
||||
if (it->mpSound == apSound) {
|
||||
// Log("returning from GUI %d\n",&(*it));
|
||||
return &(*it);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
it = mlstWorldSounds.begin();
|
||||
while (it != mlstWorldSounds.end()) {
|
||||
if (it->mpSound == apSound) {
|
||||
// Log("returning from World %d\n",&(*it));
|
||||
return &(*it);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
tSoundEntryList *cSoundHandler::GetWorldEntryList() {
|
||||
return &mlstWorldSounds;
|
||||
}
|
||||
|
||||
tSoundEntryList *cSoundHandler::GetGuiEntryList() {
|
||||
return &mlstGuiSounds;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool cSoundHandler::UpdateEntry(cSoundEntry *apEntry, float afTimeStep, tFlag aTypes) {
|
||||
// if(apEntry->mbStream) return;
|
||||
|
||||
apEntry->Update(afTimeStep);
|
||||
|
||||
/*Log("Updating entry: '%s' vol: %f playing: %d\n",apEntry->msName.c_str(),
|
||||
apEntry->mpSound->GetVolume(),
|
||||
apEntry->mpSound->IsPlaying()?1:0);*/
|
||||
// Log("Pos: %s\n",apEntry->mpSound->GetPosition().ToString().c_str());
|
||||
|
||||
if (!apEntry->mpSound->IsPlaying() && !apEntry->mpSound->GetPaused()) {
|
||||
iSoundChannel *pSound = apEntry->mpSound;
|
||||
|
||||
if (pSound->GetStopUsed() == false && pSound->GetCallBack() && pSound->GetLooping() && apEntry->mfNormalVolumeFadeDest != 0) {
|
||||
pSound->GetCallBack()->OnPriorityRelease();
|
||||
// Log("On prio release!\n");
|
||||
}
|
||||
|
||||
// Log("Stopping: %s Time: %f / %f\n",pSound->GetData()->GetName().c_str(),
|
||||
// pSound->GetElapsedTime(),
|
||||
// pSound->GetTotalTime());
|
||||
|
||||
pSound->Stop();
|
||||
hplDelete(pSound);
|
||||
|
||||
return false;
|
||||
} else {
|
||||
if (mAffectedBySpeed & apEntry->mEffectType) {
|
||||
float fSpeed = mfSpeed * apEntry->mfNormalSpeed;
|
||||
if (apEntry->mpSound->GetSpeed() != fSpeed) {
|
||||
apEntry->mpSound->SetSpeed(fSpeed);
|
||||
}
|
||||
} else {
|
||||
if (apEntry->mpSound->GetSpeed() != apEntry->mfNormalSpeed) {
|
||||
apEntry->mpSound->SetSpeed(apEntry->mfNormalSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// Update block fade:
|
||||
if (apEntry->mfBlockMul != apEntry->mfBlockFadeDest) {
|
||||
apEntry->mfBlockMul += apEntry->mfBlockFadeSpeed * afTimeStep;
|
||||
if (apEntry->mfBlockFadeSpeed < 0) {
|
||||
if (apEntry->mfBlockMul < apEntry->mfBlockFadeDest)
|
||||
apEntry->mfBlockMul = apEntry->mfBlockFadeDest;
|
||||
} else {
|
||||
if (apEntry->mfBlockMul > apEntry->mfBlockFadeDest)
|
||||
apEntry->mfBlockMul = apEntry->mfBlockFadeDest;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the sound position
|
||||
// 3D Position!
|
||||
if (apEntry->mbStream) {
|
||||
apEntry->mpSound->SetVolume(apEntry->mfNormalVolume * apEntry->mfNormalVolumeMul * mfVolume);
|
||||
}
|
||||
// else if(apEntry->mpSound->Get3D())
|
||||
if (apEntry->mpSound->Get3D()) {
|
||||
UpdateDistanceVolume3D(apEntry, afTimeStep, apEntry->mbFirstTime ? false : true, aTypes);
|
||||
}
|
||||
// 2D Position
|
||||
else {
|
||||
if (apEntry->mpSound->GetPositionRelative()) {
|
||||
iSoundChannel *pSound = apEntry->mpSound;
|
||||
|
||||
cVector3f vPos = cMath::MatrixMul(mpLowLevelSound->GetListenerMatrix(), pSound->GetRelPosition());
|
||||
pSound->SetPosition(vPos);
|
||||
|
||||
if (apEntry->mEffectType & mAffectedByVolume) {
|
||||
pSound->SetVolume(apEntry->mfNormalVolume * apEntry->mfNormalVolumeMul * mfVolume);
|
||||
} else {
|
||||
pSound->SetVolume(apEntry->mfNormalVolume * apEntry->mfNormalVolumeMul);
|
||||
}
|
||||
} else {
|
||||
iSoundChannel *pSound = apEntry->mpSound;
|
||||
float fDX = pSound->GetPosition().x - mpLowLevelSound->GetListenerPosition().x;
|
||||
float fDY = pSound->GetPosition().y - mpLowLevelSound->GetListenerPosition().y;
|
||||
|
||||
float fDist = sqrt(fDX * fDX + fDY * fDY);
|
||||
|
||||
if (fDist >= pSound->GetMaxDistance()) {
|
||||
pSound->SetVolume(0);
|
||||
} else {
|
||||
if (fDist < pSound->GetMinDistance()) {
|
||||
pSound->SetVolume(apEntry->mfNormalVolume); // some other stuff to support volume effects
|
||||
} else {
|
||||
float fVolume = 1 - ((fDist - pSound->GetMinDistance()) /
|
||||
(pSound->GetMaxDistance() - pSound->GetMinDistance()));
|
||||
fVolume *= apEntry->mfNormalVolume;
|
||||
|
||||
pSound->SetVolume(fVolume);
|
||||
}
|
||||
float fPan = 1 - (0.5f - 0.4f * (fDX / pSound->GetMaxDistance()));
|
||||
pSound->SetPan(fPan);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apEntry->mbFirstTime = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSoundHandler::UpdateDistanceVolume3D(cSoundEntry *apEntry, float afTimeStep, bool abFade,
|
||||
tFlag aTypes) {
|
||||
if (mpWorld3D == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (apEntry->mpSound->GetPositionRelative()) {
|
||||
iSoundChannel *pSound = apEntry->mpSound;
|
||||
cVector3f vPos = cMath::MatrixMul(mpLowLevelSound->GetListenerMatrix(),
|
||||
pSound->GetRelPosition());
|
||||
|
||||
pSound->SetPosition(vPos);
|
||||
// cVector3f vPos = cMath::MatrixMul(mpLowLevelSound->GetListenerMatrix(),
|
||||
// pSound->GetRelPosition());
|
||||
|
||||
// pSound->SetPosition(pSound->GetRelPosition());
|
||||
|
||||
if (aTypes & mAffectedByVolume) {
|
||||
pSound->SetVolume(apEntry->mfNormalVolume * apEntry->mfNormalVolumeMul * mfVolume);
|
||||
} else {
|
||||
pSound->SetVolume(apEntry->mfNormalVolume * apEntry->mfNormalVolumeMul);
|
||||
}
|
||||
} else {
|
||||
// Log("%s ",apEntry->msName.c_str());
|
||||
|
||||
iSoundChannel *pSound = apEntry->mpSound;
|
||||
float fDist = cMath::Vector3Dist(pSound->GetPosition(),
|
||||
mpLowLevelSound->GetListenerPosition());
|
||||
|
||||
if (fDist >= pSound->GetMaxDistance()) {
|
||||
pSound->SetVolume(0);
|
||||
|
||||
// Set very low priority
|
||||
pSound->SetPriority(0);
|
||||
|
||||
// Log(" max distance ");
|
||||
} else {
|
||||
float fVolume = 0;
|
||||
// bool bBlocked = false;
|
||||
|
||||
////////////////////////////////////////
|
||||
// Check if sound is blocked.
|
||||
if (pSound->GetBlockable() && mpWorld3D && mpWorld3D->GetPhysicsWorld() && (apEntry->mlCount % 30) == 0) {
|
||||
iPhysicsWorld *pPhysicsWorld = mpWorld3D->GetPhysicsWorld();
|
||||
|
||||
mSoundRayCallback.Reset();
|
||||
|
||||
pPhysicsWorld->CastRay(&mSoundRayCallback, pSound->GetPosition(),
|
||||
mpLowLevelSound->GetListenerPosition(),
|
||||
false, false, false, true);
|
||||
|
||||
// Log(" from (%s) to (%s) ",pSound->GetPosition().ToString().c_str(),
|
||||
// mpLowLevelSound->GetListenerPosition().ToString().c_str());
|
||||
|
||||
// Log(" callback: %d ",mSoundRayCallback.HasCollided()?1:0);
|
||||
|
||||
if (mSoundRayCallback.HasCollided()) {
|
||||
apEntry->mfBlockFadeDest = 0.0f;
|
||||
apEntry->mfBlockFadeSpeed = -1.0f / 0.55f;
|
||||
|
||||
if (abFade == false) {
|
||||
apEntry->mfBlockMul = 0.0f;
|
||||
}
|
||||
|
||||
pSound->SetFiltering(true, 0xF);
|
||||
// bBlocked = true;
|
||||
} else {
|
||||
// pSound->SetFiltering(false, 0xF);
|
||||
|
||||
apEntry->mfBlockFadeDest = 1;
|
||||
apEntry->mfBlockFadeSpeed = 1.0f / 0.2f;
|
||||
|
||||
if (abFade == false) {
|
||||
apEntry->mfBlockMul = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Log("Blocked: %d ",bBlocked ? 1 : 0);
|
||||
}
|
||||
++apEntry->mlCount;
|
||||
|
||||
/////////////////////////////////////
|
||||
// Lower volume according to distance
|
||||
if (fDist < pSound->GetMinDistance()) {
|
||||
// Set high priority
|
||||
pSound->SetPriority(100);
|
||||
|
||||
fVolume = apEntry->mfNormalVolume; // some other stuff to support volume effects
|
||||
} else {
|
||||
// Set medium priority
|
||||
pSound->SetPriority(10);
|
||||
|
||||
float fDelta = fDist - pSound->GetMinDistance();
|
||||
float fMaxDelta = pSound->GetMaxDistance() - pSound->GetMinDistance();
|
||||
|
||||
fVolume = 1 - (fDelta / fMaxDelta);
|
||||
float fSqr = fVolume * fVolume;
|
||||
|
||||
// Log("Lin: %f Sqr: %f ",fVolume,fSqr);
|
||||
|
||||
// fade between normal and square
|
||||
fVolume = fVolume * apEntry->mfBlockMul + (1.0f - apEntry->mfBlockMul) * fSqr;
|
||||
|
||||
// Log("Mix: %f ",fVolume);
|
||||
|
||||
fVolume *= apEntry->mfNormalVolume;
|
||||
}
|
||||
|
||||
float fBlock = pSound->GetBlockVolumeMul() +
|
||||
apEntry->mfBlockMul * (1 - pSound->GetBlockVolumeMul());
|
||||
|
||||
if (aTypes & apEntry->mEffectType) {
|
||||
pSound->SetVolume(fBlock * fVolume * apEntry->mfNormalVolumeMul * mfVolume);
|
||||
// pSound->SetFilterGainHF(fBlock * fVolume * apEntry->mfNormalVolumeMul * mfVolume);
|
||||
} else {
|
||||
pSound->SetVolume(fBlock * fVolume * apEntry->mfNormalVolumeMul);
|
||||
}
|
||||
|
||||
// pSound->SetFilterGainHF(0.1f);
|
||||
|
||||
// Log("Vol: %f\n",fBlock * fVolume * apEntry->mfNormalVolumeMul);
|
||||
// Log("%s Block: %f\n",apEntry->msName.c_str(),apEntry->mfBlockMul);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cSoundEntry *cSoundHandler::GetEntry(const tString &asName) {
|
||||
tSoundEntryListIt it = mlstGuiSounds.begin();
|
||||
while (it != mlstGuiSounds.end()) {
|
||||
if (cString::ToLowerCase(it->msName) == cString::ToLowerCase(asName)) {
|
||||
return &(*it);
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
it = mlstWorldSounds.begin();
|
||||
while (it != mlstWorldSounds.end()) {
|
||||
// Log("'%s' vs '%s'\n", it->msName.c_str(), asName.c_str());
|
||||
if (cString::ToLowerCase(it->msName) == cString::ToLowerCase(asName)) {
|
||||
return &(*it);
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSoundChannel *cSoundHandler::CreateChannel(const tString &asName, int alPriority) {
|
||||
int lNum = cString::ToInt(cString::GetLastChar(asName).c_str(), 0);
|
||||
iSoundChannel *pSound = NULL;
|
||||
iSoundData *pData = NULL;
|
||||
tString sName;
|
||||
tString sBaseName = asName;
|
||||
|
||||
// Try loading it from the buffer
|
||||
if (lNum >= 1 && lNum <= 9) {
|
||||
pData = mpResources->GetSoundManager()->CreateSoundData(asName, false);
|
||||
} else {
|
||||
int lCount = 0;
|
||||
int lLastNum = -1;
|
||||
|
||||
// Check what the last sound played was.
|
||||
tPlayedSoundNumMapIt SoundIt = m_mapPlayedSound.find(sBaseName);
|
||||
if (SoundIt == m_mapPlayedSound.end()) {
|
||||
m_mapPlayedSound.insert(tPlayedSoundNumMap::value_type(sBaseName, 0));
|
||||
SoundIt = m_mapPlayedSound.find(sBaseName);
|
||||
} else {
|
||||
lLastNum = SoundIt->second;
|
||||
}
|
||||
|
||||
sName = sBaseName + cString::ToString(lCount + 1);
|
||||
pData = mpResources->GetSoundManager()->CreateSoundData(sName, false);
|
||||
while (pData) {
|
||||
lCount++;
|
||||
sName = sBaseName + cString::ToString(lCount + 1);
|
||||
pData = mpResources->GetSoundManager()->CreateSoundData(sName, false);
|
||||
}
|
||||
|
||||
if (lCount > 0) {
|
||||
int lNum2 = cMath::RandRectl(1, lCount);
|
||||
|
||||
if (lCount > 2) {
|
||||
while (lLastNum == lNum2)
|
||||
lNum2 = cMath::RandRectl(1, lCount);
|
||||
}
|
||||
SoundIt->second = lNum2;
|
||||
|
||||
sName = sBaseName + cString::ToString(lNum2);
|
||||
|
||||
pData = mpResources->GetSoundManager()->CreateSoundData(sName, false);
|
||||
|
||||
} else {
|
||||
pData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to stream it
|
||||
if (pData == NULL) {
|
||||
sName = "stream_" + sBaseName;
|
||||
|
||||
pData = mpResources->GetSoundManager()->CreateSoundData(sName, true);
|
||||
if (pData == NULL) {
|
||||
Error("Couldn't stream sound '%s'\n", asName.c_str());
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Create sound channel
|
||||
pSound = pData->CreateChannel(alPriority);
|
||||
if (pSound == NULL) {
|
||||
// Warning("Couldn't play sound '%s'\n",asName.c_str());
|
||||
}
|
||||
|
||||
return pSound;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
} // namespace hpl
|
||||
Reference in New Issue
Block a user