Files
scummvm-cursorfix/engines/hpl1/engine/sound/MusicHandler.cpp
2026-02-02 04:50:13 +01:00

313 lines
8.3 KiB
C++

/* 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/MusicHandler.h"
#include "hpl1/debug.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"
namespace hpl {
//////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cMusicHandler::cMusicHandler(iLowLevelSound *apLowLevelSound, cResources *apResources) {
mpLowLevelSound = apLowLevelSound;
mpResources = apResources;
mpMainSong = NULL;
mpLock = NULL;
mbIsPaused = false;
}
//-----------------------------------------------------------------------
cMusicHandler::~cMusicHandler() {
if (mpMainSong) {
hplDelete(mpMainSong->mpStream);
hplDelete(mpMainSong);
}
tMusicEntryListIt it = mlstFadingSongs.begin();
while (it != mlstFadingSongs.end()) {
cMusicEntry *pSong = *it;
hplDelete(pSong->mpStream);
hplDelete(pSong);
it = mlstFadingSongs.erase(it);
// it++;
}
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
bool cMusicHandler::Play(const tString &asFileName, float afVolume, float afFadeStepSize, bool abLoop) {
bool bSongIsPlaying = false;
if (mpLock != NULL) {
mpLock->msFileName = asFileName;
mpLock->mfVolume = afVolume;
mpLock->mbLoop = abLoop;
return true;
}
if (mpMainSong != NULL)
if (asFileName == mpMainSong->msFileName)
bSongIsPlaying = true;
if (!bSongIsPlaying) {
// Put the previous song in the fading queue
if (mpMainSong != NULL) {
mpMainSong->mfVolumeAdd = afFadeStepSize;
mlstFadingSongs.push_back(mpMainSong);
}
// If there the song to be played is in the fade que, stop it.
tMusicEntryListIt it = mlstFadingSongs.begin();
while (it != mlstFadingSongs.end()) {
cMusicEntry *pSong = *it;
if (pSong->msFileName == asFileName) {
pSong->mfVolume = 0;
pSong->mpStream->Stop();
hplDelete(pSong->mpStream);
hplDelete(pSong);
it = mlstFadingSongs.erase(it);
} else {
it++;
}
}
// add it and set its properties
mpMainSong = hplNew(cMusicEntry, ());
if (LoadAndStart(asFileName, mpMainSong, 0, abLoop) == false) {
hplDelete(mpMainSong);
mpMainSong = NULL;
return false;
}
} else {
if (mpMainSong->mfMaxVolume == afVolume)
return true;
}
// Set Properties
mpMainSong->mfMaxVolume = afVolume;
mpMainSong->mbLoop = abLoop;
if (mpMainSong->mfMaxVolume > mpMainSong->mfVolume)
mpMainSong->mfVolumeAdd = afFadeStepSize;
else
mpMainSong->mfVolumeAdd = -afFadeStepSize;
return true;
}
//-----------------------------------------------------------------------
void cMusicHandler::Stop(float afFadeStepSize) {
if (mpMainSong == NULL)
return;
if (afFadeStepSize < 0)
afFadeStepSize = -afFadeStepSize;
mpMainSong->mfVolumeAdd = afFadeStepSize;
if (afFadeStepSize == 0) {
mpMainSong->mpStream->SetVolume(0);
mpMainSong->mpStream->Stop();
mpMainSong->mfVolume = 0;
}
mlstFadingSongs.push_back(mpMainSong);
mpMainSong = NULL;
}
//-----------------------------------------------------------------------
void cMusicHandler::Pause() {
if (mpMainSong != NULL)
mpMainSong->mpStream->SetPaused(true);
tMusicEntryListIt it = mlstFadingSongs.begin();
while (it != mlstFadingSongs.end()) {
(*it)->mpStream->SetPaused(true);
it++;
}
mbIsPaused = true;
}
//-----------------------------------------------------------------------
void cMusicHandler::Resume() {
if (mpMainSong != NULL)
mpMainSong->mpStream->SetPaused(false);
tMusicEntryListIt it = mlstFadingSongs.begin();
while (it != mlstFadingSongs.end()) {
(*it)->mpStream->SetPaused(false);
it++;
}
mbIsPaused = false;
}
//-----------------------------------------------------------------------
void cMusicHandler::Lock(cMusicLock *apLock) {
mpLock = apLock;
}
//-----------------------------------------------------------------------
void cMusicHandler::UnLock() {
mpLock = NULL;
}
//-----------------------------------------------------------------------
tString cMusicHandler::GetCurrentSongName() {
if (mpMainSong != NULL)
return mpMainSong->msFileName;
else
return "";
}
//-----------------------------------------------------------------------
float cMusicHandler::GetCurrentSongVolume() {
if (mpMainSong != NULL)
return mpMainSong->mfVolume;
else
return 0;
}
//-----------------------------------------------------------------------
cMusicEntry *cMusicHandler::GetCurrentSong() {
return mpMainSong;
}
//-----------------------------------------------------------------------
void cMusicHandler::Update(float afTimeStep) {
if (mbIsPaused)
return;
if (mpMainSong != NULL) {
if (mpMainSong->mpStream->IsPlaying() == false) {
hplDelete(mpMainSong->mpStream);
hplDelete(mpMainSong);
mpMainSong = NULL;
} else {
// Update the main song
mpMainSong->mfVolume += mpMainSong->mfVolumeAdd * afTimeStep;
if (mpMainSong->mfVolumeAdd > 0) {
if (mpMainSong->mfVolume >= mpMainSong->mfMaxVolume)
mpMainSong->mfVolume = mpMainSong->mfMaxVolume;
} else {
if (mpMainSong->mfVolume <= mpMainSong->mfMaxVolume)
mpMainSong->mfVolume = mpMainSong->mfMaxVolume;
}
if (mpMainSong->mpStream->GetVolume() != mpMainSong->mfVolume) {
mpMainSong->mpStream->SetVolume(mpMainSong->mfVolume);
}
}
}
// Update the fading songs
tMusicEntryListIt it = mlstFadingSongs.begin();
while (it != mlstFadingSongs.end()) {
cMusicEntry *pSong = *it;
pSong->mfVolume -= pSong->mfVolumeAdd * afTimeStep;
if (pSong->mfVolume <= 0) {
pSong->mfVolume = 0;
pSong->mpStream->Stop();
hplDelete(pSong->mpStream);
hplDelete(pSong);
it = mlstFadingSongs.erase(it);
} else {
pSong->mpStream->SetVolume(pSong->mfVolume);
it++;
}
}
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
bool cMusicHandler::LoadAndStart(const tString &asFileName, cMusicEntry *apSong, float afVolume, bool abLoop) {
iSoundData *pData = mpResources->GetSoundManager()->CreateSoundData(asFileName, true, abLoop);
if (pData == NULL) {
Hpl1::logError(Hpl1::kDebugAudio | Hpl1::kDebugResourceLoading, "Couldn't load music '%s'\n", asFileName.c_str());
return false;
}
iSoundChannel *pStream = pData->CreateChannel(256);
if (pStream == NULL) {
Hpl1::logError(Hpl1::kDebugAudio, "Couldn't stream music '%s'!\n", asFileName.c_str());
return false;
}
apSong->msFileName = asFileName;
apSong->mpStream = pStream;
apSong->mpStream->SetVolume(afVolume);
apSong->mpStream->Play();
apSong->mpStream->SetLooping(abLoop);
return true;
}
//-----------------------------------------------------------------------
} // namespace hpl