Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
/* 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/>.
*
*/
#include "titanic/sound/audio_buffer.h"
#include "common/algorithm.h"
namespace Titanic {
CAudioBuffer::CAudioBuffer(int maxSize) : _finished(false) {
reset();
}
void CAudioBuffer::reset() {
_data.clear();
}
void CAudioBuffer::push(int16 value) {
enterCriticalSection();
_data.push(value);
leaveCriticalSection();
}
void CAudioBuffer::push(const int16 *values, int count) {
enterCriticalSection();
for (; count > 0; --count, ++values)
_data.push(*values);
leaveCriticalSection();
}
int16 CAudioBuffer::pop() {
enterCriticalSection();
int16 value = _data.pop();
leaveCriticalSection();
return value;
}
int CAudioBuffer::read(int16 *values, int count) {
enterCriticalSection();
int bytesRead = 0;
for (; count > 0 && !_data.empty(); --count, ++bytesRead)
*values++ = _data.pop();
leaveCriticalSection();
return bytesRead;
}
void CAudioBuffer::enterCriticalSection() {
_mutex.lock();
}
void CAudioBuffer::leaveCriticalSection() {
_mutex.unlock();
}
} // End of namespace Titanic

View File

@@ -0,0 +1,109 @@
/* 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/>.
*
*/
#ifndef TITANIC_AUDIO_BUFFER_H
#define TITANIC_AUDIO_BUFFER_H
#include "titanic/support/fixed_queue.h"
#include "common/mutex.h"
namespace Titanic {
#define AUDIO_SAMPLING_RATE 22050
class CAudioBuffer {
private:
Common::Mutex _mutex;
FixedQueue<int16, AUDIO_SAMPLING_RATE * 4> _data;
private:
/**
* Enters a critical section
*/
void enterCriticalSection();
/**
* Leave a critical section
*/
void leaveCriticalSection();
private:
bool _finished;
public:
CAudioBuffer(int maxSize);
/**
* Resets the audio buffer
*/
void reset();
/**
* Returns true if the buffer is empty
*/
bool empty() const { return _data.empty(); }
/**
* Returns the number of 16-bit entries in the buffer
*/
int size() const { return _data.size(); }
/**
* Returns the number of entries free in the buffer
*/
int freeSize() const { return _data.freeSize(); }
/**
* Returns true if the buffer is full
*/
bool full() const { return _data.full(); }
/**
* Returns true if the audio buffering is finished
*/
bool isFinished() const { return _finished && empty(); }
/**
* Adds a value to the buffer
*/
void push(int16 value);
/**
* Adds a value to the buffer
*/
void push(const int16 *values, int count);
/**
* Removes a value from the buffer
*/
int16 pop();
/**
* Reads out a specified number of samples
*/
int read(int16 *values, int count);
/**
* Marks the buffer as finishing, and that no more new data will arrive
*/
void finalize() { _finished = true; }
};
} // End of namespace Titanic
#endif /* TITANIC_AUDIO_BUFFER_H */

View File

@@ -0,0 +1,74 @@
/* 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/>.
*
*/
#include "titanic/sound/auto_music_player.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CAutoMusicPlayer, CAutoMusicPlayerBase)
ON_MESSAGE(EnterRoomMsg)
ON_MESSAGE(LeaveRoomMsg)
END_MESSAGE_MAP()
CAutoMusicPlayer::CAutoMusicPlayer() : CAutoMusicPlayerBase() {
}
void CAutoMusicPlayer::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeQuotedLine(_leaveRoomSound, indent);
CAutoMusicPlayerBase::save(file, indent);
}
void CAutoMusicPlayer::load(SimpleFile *file) {
file->readNumber();
_leaveRoomSound = file->readString();
CAutoMusicPlayerBase::load(file);
}
bool CAutoMusicPlayer::EnterRoomMsg(CEnterRoomMsg *msg) {
if (!_isEnabled) {
CRoomItem *room = findRoom();
if (msg->_newRoom == room)
addTimer(2000);
}
return true;
}
bool CAutoMusicPlayer::LeaveRoomMsg(CLeaveRoomMsg *msg) {
if (_isEnabled) {
CRoomItem *room = findRoom();
if (msg->_oldRoom == room) {
CChangeMusicMsg changeMsg;
changeMsg._action = MUSIC_STOP;
changeMsg.execute(this);
}
}
if (!_leaveRoomSound.empty())
playSound(_leaveRoomSound);
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,53 @@
/* 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/>.
*
*/
#ifndef TITANIC_AUTO_MUSIC_PLAYER_H
#define TITANIC_AUTO_MUSIC_PLAYER_H
#include "titanic/sound/auto_music_player_base.h"
#include "titanic/messages/messages.h"
namespace Titanic {
class CAutoMusicPlayer : public CAutoMusicPlayerBase {
DECLARE_MESSAGE_MAP;
bool EnterRoomMsg(CEnterRoomMsg *msg);
bool LeaveRoomMsg(CLeaveRoomMsg *msg);
private:
CString _leaveRoomSound;
public:
CLASSDEF;
CAutoMusicPlayer();
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_AUTO_MUSIC_PLAYER_H */

View File

@@ -0,0 +1,114 @@
/* 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/>.
*
*/
#include "titanic/sound/auto_music_player_base.h"
#include "titanic/game_manager.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CAutoMusicPlayerBase, CGameObject)
ON_MESSAGE(StatusChangeMsg)
ON_MESSAGE(TimerMsg)
ON_MESSAGE(LoadSuccessMsg)
ON_MESSAGE(ChangeMusicMsg)
END_MESSAGE_MAP()
CAutoMusicPlayerBase::CAutoMusicPlayerBase() : CGameObject(),
_initialMute(true), _isEnabled(false), _volumeMode(VOL_NORMAL), _transition(1) {
}
void CAutoMusicPlayerBase::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeQuotedLine(_filename, indent);
file->writeNumberLine(_initialMute, indent);
file->writeNumberLine(_isEnabled, indent);
file->writeNumberLine(_volumeMode, indent);
file->writeNumberLine(_transition, indent);
CGameObject::save(file, indent);
}
void CAutoMusicPlayerBase::load(SimpleFile *file) {
file->readNumber();
_filename = file->readString();
_initialMute = file->readNumber();
_isEnabled = file->readNumber();
_volumeMode = (VolumeMode)file->readNumber();
_transition = file->readNumber();
CGameObject::load(file);
}
bool CAutoMusicPlayerBase::StatusChangeMsg(CStatusChangeMsg *msg) {
return true;
}
bool CAutoMusicPlayerBase::TimerMsg(CTimerMsg *msg) {
CChangeMusicMsg musicMsg;
musicMsg._action = MUSIC_START;
musicMsg.execute(this);
return true;
}
bool CAutoMusicPlayerBase::LoadSuccessMsg(CLoadSuccessMsg *msg) {
if (_isEnabled) {
// WORKAROUND: A problem was encountered with the EmbLobby music player
// not getting turned off when room was left, so was turned on again
// when loading a savegame elsewhere. This guards against it
CRoomItem *newRoom = getGameManager()->getRoom();
if (findRoom() != newRoom) {
_isEnabled = false;
return true;
}
playAmbientSound(_filename, _volumeMode, _initialMute, true, 0,
Audio::Mixer::kMusicSoundType);
}
return true;
}
bool CAutoMusicPlayerBase::ChangeMusicMsg(CChangeMusicMsg *msg) {
if (_isEnabled && msg->_action == MUSIC_STOP) {
_isEnabled = false;
stopAmbientSound(_transition, -1);
}
if (!msg->_filename.empty()) {
_filename = msg->_filename;
if (_isEnabled) {
stopAmbientSound(_transition, -1);
playAmbientSound(_filename, _volumeMode, _initialMute, true, 0,
Audio::Mixer::kMusicSoundType);
}
}
if (!_isEnabled && msg->_action == MUSIC_START) {
_isEnabled = true;
playAmbientSound(_filename, _volumeMode, _initialMute, true, 0,
Audio::Mixer::kMusicSoundType);
}
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,58 @@
/* 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/>.
*
*/
#ifndef TITANIC_AUTO_MUSIC_PLAYER_BASE_H
#define TITANIC_AUTO_MUSIC_PLAYER_BASE_H
#include "titanic/core/game_object.h"
namespace Titanic {
class CAutoMusicPlayerBase : public CGameObject {
DECLARE_MESSAGE_MAP;
bool StatusChangeMsg(CStatusChangeMsg *msg);
bool TimerMsg(CTimerMsg *msg);
bool LoadSuccessMsg(CLoadSuccessMsg *msg);
bool ChangeMusicMsg(CChangeMusicMsg *msg);
protected:
CString _filename;
bool _initialMute;
bool _isEnabled;
VolumeMode _volumeMode;
int _transition;
public:
CLASSDEF;
CAutoMusicPlayerBase();
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_AUTO_MUSIC_PLAYER_BASE_H */

View File

@@ -0,0 +1,133 @@
/* 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/>.
*
*/
#include "titanic/sound/auto_sound_player.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CAutoSoundPlayer, CGameObject)
ON_MESSAGE(TurnOn)
ON_MESSAGE(TurnOff)
ON_MESSAGE(SignalObject)
ON_MESSAGE(SetVolumeMsg)
ON_MESSAGE(LoadSuccessMsg)
END_MESSAGE_MAP()
CAutoSoundPlayer::CAutoSoundPlayer() : CGameObject(),
_unused(0), _volume(70), _balance(0), _repeated(false), _soundHandle(-1),
_stopSeconds(0), _startSeconds(-1), _active(false), _isVectorSound(false) {
}
void CAutoSoundPlayer::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeNumberLine(_unused, indent);
file->writeQuotedLine(_filename, indent);
file->writeNumberLine(_volume, indent);
file->writeNumberLine(_balance, indent);
file->writeNumberLine(_repeated, indent);
file->writeNumberLine(_soundHandle, indent);
file->writeNumberLine(_stopSeconds, indent);
file->writeNumberLine(_startSeconds, indent);
file->writeNumberLine(_active, indent);
file->writeNumberLine(_isVectorSound, indent);
CGameObject::save(file, indent);
}
void CAutoSoundPlayer::load(SimpleFile *file) {
file->readNumber();
_unused = file->readNumber();
_filename = file->readString();
_volume = file->readNumber();
_balance = file->readNumber();
_repeated = file->readNumber();
_soundHandle = file->readNumber();
_stopSeconds = file->readNumber();
_startSeconds = file->readNumber();
_active = file->readNumber();
_isVectorSound = file->readNumber();
CGameObject::load(file);
}
bool CAutoSoundPlayer::TurnOn(CTurnOn *msg) {
if (_soundHandle == -1) {
CProximity prox;
prox._balance = _balance;
prox._repeated = _repeated;
if (_isVectorSound)
prox._positioningMode = POSMODE_VECTOR;
prox._channelVolume = (_startSeconds == -1) ? _volume : 0;
_soundHandle = playSound(_filename, prox);
if (_startSeconds != -1)
setSoundVolume(_soundHandle, _volume, _startSeconds);
_active = true;
}
return true;
}
bool CAutoSoundPlayer::TurnOff(CTurnOff *msg) {
if (_soundHandle != -1) {
if (isSoundActive(_soundHandle))
stopSound(_soundHandle, _stopSeconds);
_soundHandle = -1;
_active = false;
}
return true;
}
bool CAutoSoundPlayer::SignalObject(CSignalObject *msg) {
if (_soundHandle != -1) {
if (isSoundActive(_soundHandle))
stopSound(_soundHandle, msg->_numValue);
_soundHandle = -1;
_active = false;
}
return true;
}
bool CAutoSoundPlayer::SetVolumeMsg(CSetVolumeMsg *msg) {
if (_soundHandle != -1 && isSoundActive(_soundHandle))
setSoundVolume(_soundHandle, msg->_volume, msg->_secondsTransition);
return true;
}
bool CAutoSoundPlayer::LoadSuccessMsg(CLoadSuccessMsg *msg) {
if (_active) {
_soundHandle = -1;
_active = false;
CTurnOn onMsg;
onMsg.execute(this);
}
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,64 @@
/* 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/>.
*
*/
#ifndef TITANIC_AUTO_SOUND_PLAYER_H
#define TITANIC_AUTO_SOUND_PLAYER_H
#include "titanic/core/game_object.h"
namespace Titanic {
class CAutoSoundPlayer : public CGameObject {
DECLARE_MESSAGE_MAP;
bool TurnOn(CTurnOn *msg);
bool TurnOff(CTurnOff *msg);
bool SignalObject(CSignalObject *msg);
bool SetVolumeMsg(CSetVolumeMsg *msg);
bool LoadSuccessMsg(CLoadSuccessMsg *msg);
public:
int _unused;
CString _filename;
int _volume;
int _balance;
bool _repeated;
int _soundHandle;
int _stopSeconds;
int _startSeconds;
bool _active;
bool _isVectorSound;
public:
CLASSDEF;
CAutoSoundPlayer();
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_AUTO_SOUND_PLAYER_H */

View File

@@ -0,0 +1,78 @@
/* 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/>.
*
*/
#include "titanic/sound/auto_sound_player_adsr.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CAutoSoundPlayerADSR, CAutoSoundPlayer)
ON_MESSAGE(TurnOn)
ON_MESSAGE(TurnOff)
END_MESSAGE_MAP()
void CAutoSoundPlayerADSR::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeQuotedLine(_soundName1, indent);
file->writeQuotedLine(_soundName2, indent);
file->writeQuotedLine(_soundName3, indent);
CAutoSoundPlayer::save(file, indent);
}
void CAutoSoundPlayerADSR::load(SimpleFile *file) {
file->readNumber();
_soundName1 = file->readString();
_soundName2 = file->readString();
_soundName3 = file->readString();
CAutoSoundPlayer::load(file);
}
bool CAutoSoundPlayerADSR::TurnOn(CTurnOn *msg) {
if (_soundHandle == -1) {
if (!_soundName1.empty()) {
_soundHandle = playSound(_soundName1, _volume, _balance);
if (!_soundName2.empty())
_soundHandle = queueSound(_soundName2, _soundHandle, _volume, _balance);
_soundHandle = queueSound(_filename, _soundHandle, _volume, _balance);
_active = true;
}
}
return true;
}
bool CAutoSoundPlayerADSR::TurnOff(CTurnOff *msg) {
if (_soundHandle != -1) {
if (!_soundName3.empty())
queueSound(_soundName3, _soundHandle, _volume, _balance);
if (isSoundActive(_soundHandle))
stopSound(_soundHandle);
_soundHandle = -1;
_active = false;
}
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,53 @@
/* 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/>.
*
*/
#ifndef TITANIC_AUTO_SOUND_PLAYER_ADSR_H
#define TITANIC_AUTO_SOUND_PLAYER_ADSR_H
#include "titanic/sound/auto_sound_player.h"
namespace Titanic {
class CAutoSoundPlayerADSR : public CAutoSoundPlayer {
DECLARE_MESSAGE_MAP;
bool TurnOn(CTurnOn *msg);
bool TurnOff(CTurnOff *msg);
private:
CString _soundName1;
CString _soundName2;
CString _soundName3;
public:
CLASSDEF;
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_AUTO_SOUND_PLAYER_ADSR_H */

View File

@@ -0,0 +1,46 @@
/* 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/>.
*
*/
#include "titanic/sound/background_sound_maker.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CBackgroundSoundMaker, CGameObject)
ON_MESSAGE(FrameMsg)
END_MESSAGE_MAP()
void CBackgroundSoundMaker::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeNumberLine(_value, indent);
CGameObject::save(file, indent);
}
void CBackgroundSoundMaker::load(SimpleFile *file) {
file->readNumber();
_value = file->readNumber();
CGameObject::load(file);
}
bool CBackgroundSoundMaker::FrameMsg(CFrameMsg *msg) {
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,51 @@
/* 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/>.
*
*/
#ifndef TITANIC_BACKGROUND_SOUND_MAKER_H
#define TITANIC_BACKGROUND_SOUND_MAKER_H
#include "titanic/core/game_object.h"
namespace Titanic {
class CBackgroundSoundMaker : public CGameObject {
DECLARE_MESSAGE_MAP;
bool FrameMsg(CFrameMsg *msg);
public:
int _value;
public:
CLASSDEF;
CBackgroundSoundMaker() : CGameObject(), _value(0) {}
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_BACKGROUND_SOUND_MAKER_H */

View File

@@ -0,0 +1,55 @@
/* 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/>.
*
*/
#include "titanic/sound/bird_song.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CBirdSong, CRoomAutoSoundPlayer)
ON_MESSAGE(TurnOn)
ON_MESSAGE(SignalObject)
END_MESSAGE_MAP()
void CBirdSong::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeNumberLine(_flag, indent);
CRoomAutoSoundPlayer::save(file, indent);
}
void CBirdSong::load(SimpleFile *file) {
file->readNumber();
_flag = file->readNumber();
CRoomAutoSoundPlayer::load(file);
}
bool CBirdSong::TurnOn(CTurnOn *msg) {
if (!_flag)
CAutoSoundPlayer::TurnOn(msg);
return true;
}
bool CBirdSong::SignalObject(CSignalObject *msg) {
_flag = true;
CAutoSoundPlayer::SignalObject(msg);
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,52 @@
/* 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/>.
*
*/
#ifndef TITANIC_BIRD_SONG_H
#define TITANIC_BIRD_SONG_H
#include "titanic/sound/room_auto_sound_player.h"
namespace Titanic {
class CBirdSong : public CRoomAutoSoundPlayer {
DECLARE_MESSAGE_MAP;
bool TurnOn(CTurnOn *msg);
bool SignalObject(CSignalObject *msg);
public:
bool _flag;
public:
CLASSDEF;
CBirdSong() : CRoomAutoSoundPlayer(), _flag(false) {}
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_BIRD_SONG_H */

View File

@@ -0,0 +1,46 @@
/* 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/>.
*
*/
#include "titanic/sound/dome_from_top_of_well.h"
namespace Titanic {
EMPTY_MESSAGE_MAP(CDomeFromTopOfWell, CViewAutoSoundPlayer);
CDomeFromTopOfWell::CDomeFromTopOfWell() : CViewAutoSoundPlayer() {
_filename = "z#227.wav";
_volume = 25;
_repeated = true;
_stopSeconds = 1;
_startSeconds = 1;
}
void CDomeFromTopOfWell::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
CViewAutoSoundPlayer::save(file, indent);
}
void CDomeFromTopOfWell::load(SimpleFile *file) {
file->readNumber();
CViewAutoSoundPlayer::load(file);
}
} // End of namespace Titanic

View File

@@ -0,0 +1,48 @@
/* 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/>.
*
*/
#ifndef TITANIC_DOME_FROM_TOP_OF_WELL_H
#define TITANIC_DOME_FROM_TOP_OF_WELL_H
#include "titanic/sound/view_auto_sound_player.h"
namespace Titanic {
class CDomeFromTopOfWell : public CViewAutoSoundPlayer {
DECLARE_MESSAGE_MAP;
public:
CLASSDEF;
CDomeFromTopOfWell();
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_DOME_FROM_TOP_OF_WELL_H */

View File

@@ -0,0 +1,59 @@
/* 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/>.
*
*/
#include "titanic/sound/enter_view_toggles_other_music.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CEnterViewTogglesOtherMusic, CTriggerAutoMusicPlayer)
ON_MESSAGE(EnterViewMsg)
END_MESSAGE_MAP()
CEnterViewTogglesOtherMusic::CEnterViewTogglesOtherMusic() :
CTriggerAutoMusicPlayer(), _value(2) {
}
void CEnterViewTogglesOtherMusic::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeNumberLine(_value, indent);
CTriggerAutoMusicPlayer::save(file, indent);
}
void CEnterViewTogglesOtherMusic::load(SimpleFile *file) {
file->readNumber();
_value = file->readNumber();
CTriggerAutoMusicPlayer::load(file);
}
bool CEnterViewTogglesOtherMusic::EnterViewMsg(CEnterViewMsg *msg) {
CViewItem *view = findView();
if (view == msg->_newView) {
CTriggerAutoMusicPlayerMsg triggerMsg;
triggerMsg._value = _value;
triggerMsg.execute(this);
}
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,51 @@
/* 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/>.
*
*/
#ifndef TITANIC_ENTER_VIEW_TOGGLES_OTHER_MUSIC_H
#define TITANIC_ENTER_VIEW_TOGGLES_OTHER_MUSIC_H
#include "titanic/sound/trigger_auto_music_player.h"
namespace Titanic {
class CEnterViewTogglesOtherMusic : public CTriggerAutoMusicPlayer {
DECLARE_MESSAGE_MAP;
bool EnterViewMsg(CEnterViewMsg *msg);
protected:
int _value;
public:
CLASSDEF;
CEnterViewTogglesOtherMusic();
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_ENTER_VIEW_TOGGLES_OTHER_MUSIC_H */

View File

@@ -0,0 +1,93 @@
/* 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/>.
*
*/
#include "titanic/sound/gondolier_song.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CGondolierSong, CRoomAutoSoundPlayer)
ON_MESSAGE(TurnOn)
ON_MESSAGE(SignalObject)
ON_MESSAGE(SetVolumeMsg)
ON_MESSAGE(StatusChangeMsg)
END_MESSAGE_MAP()
void CGondolierSong::save(SimpleFile *file, int indent) {
file->writeNumberLine(_enabled, indent);
file->writeNumberLine(_value, indent);
CRoomAutoSoundPlayer::save(file, indent);
}
void CGondolierSong::load(SimpleFile *file) {
_enabled = file->readNumber();
_value = file->readNumber();
CRoomAutoSoundPlayer::load(file);
}
bool CGondolierSong::TurnOn(CTurnOn *msg) {
if (_enabled) {
if (_soundHandle != -1) {
int volume = _value * _volume / 100;
if (_startSeconds == -1) {
_soundHandle = playSound(_filename, volume, _balance, _repeated);
} else {
_soundHandle = playSound(_filename, 0, _balance, _repeated);
setSoundVolume(_soundHandle, _volume, _startSeconds);
}
_active = true;
}
}
return true;
}
bool CGondolierSong::SignalObject(CSignalObject *msg) {
_enabled = false;
CAutoSoundPlayer::SignalObject(msg);
return true;
}
bool CGondolierSong::SetVolumeMsg(CSetVolumeMsg *msg) {
if (_enabled) {
_volume = msg->_volume;
if (_soundHandle != -1 && isSoundActive(_soundHandle)) {
int newVolume = _value * _volume / 100;
setSoundVolume(_soundHandle, newVolume, msg->_secondsTransition);
}
}
return true;
}
bool CGondolierSong::StatusChangeMsg(CStatusChangeMsg *msg) {
if (_enabled) {
_value = CLIP(msg->_newStatus, 0, 100);
CSetVolumeMsg volumeMsg(_volume, _stopSeconds);
volumeMsg.execute(this);
}
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,55 @@
/* 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/>.
*
*/
#ifndef TITANIC_GONDOLIER_SONG_H
#define TITANIC_GONDOLIER_SONG_H
#include "titanic/sound/room_auto_sound_player.h"
namespace Titanic {
class CGondolierSong : public CRoomAutoSoundPlayer {
DECLARE_MESSAGE_MAP;
bool TurnOn(CTurnOn *msg);
bool SignalObject(CSignalObject *msg);
bool SetVolumeMsg(CSetVolumeMsg *msg);
bool StatusChangeMsg(CStatusChangeMsg *msg);
public:
bool _enabled;
int _value;
public:
CLASSDEF;
CGondolierSong() : CRoomAutoSoundPlayer(), _enabled(true), _value(0) {}
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_GONDOLIER_SONG_H */

View File

@@ -0,0 +1,185 @@
/* 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/>.
*
*/
#include "titanic/sound/music_player.h"
#include "titanic/sound/music_room.h"
#include "titanic/translation.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CMusicPlayer, CGameObject)
ON_MESSAGE(StartMusicMsg)
ON_MESSAGE(StopMusicMsg)
ON_MESSAGE(FrameMsg)
ON_MESSAGE(EnterRoomMsg)
ON_MESSAGE(LeaveRoomMsg)
ON_MESSAGE(CreateMusicPlayerMsg)
ON_MESSAGE(LoadSuccessMsg)
END_MESSAGE_MAP()
void CMusicPlayer::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeNumberLine(_isActive, indent);
file->writeQuotedLine(_stopTarget, indent);
file->writeNumberLine(_musicActive, indent);
file->writeNumberLine(_volume, indent);
CGameObject::save(file, indent);
}
void CMusicPlayer::load(SimpleFile *file) {
file->readNumber();
_isActive = file->readNumber();
_stopTarget = file->readString();
_musicActive = file->readNumber();
_volume = file->readNumber();
CGameObject::load(file);
}
bool CMusicPlayer::StartMusicMsg(CStartMusicMsg *msg) {
if (msg->_musicPlayer != this) {
if (_isActive) {
CStopMusicMsg stopMusicMsg;
stopMusicMsg.execute(this);
}
return false;
}
if (!_isActive) {
lockMouse();
CCreateMusicPlayerMsg createMsg;
createMsg.execute(this);
CSetMusicControlsMsg controlsMsg;
controlsMsg.execute(this, nullptr, MSGFLAG_SCAN);
getMusicRoom()->setupMusic(_volume);
_isActive = true;
unlockMouse();
}
return true;
}
bool CMusicPlayer::StopMusicMsg(CStopMusicMsg *msg) {
if (!_isActive)
// Player isn't playing, so ignore message
return false;
// Stop the music
CMusicRoom *musicRoom = getMusicRoom();
if (musicRoom)
musicRoom->stopMusic();
_isActive = false;
CMusicHasStoppedMsg stoppedMsg;
stoppedMsg.execute(_stopTarget, nullptr, MSGFLAG_SCAN);
return true;
}
bool CMusicPlayer::FrameMsg(CFrameMsg *msg) {
if (_isActive && !CMusicRoom::_musicHandler->update()) {
getMusicRoom()->stopMusic();
_isActive = false;
CMusicHasStoppedMsg stoppedMsg;
stoppedMsg.execute(_stopTarget);
}
return true;
}
bool CMusicPlayer::EnterRoomMsg(CEnterRoomMsg *msg) {
// Set up a timer that will create a music handler
addTimer(100);
return true;
}
bool CMusicPlayer::LeaveRoomMsg(CLeaveRoomMsg *msg) {
getMusicRoom()->destroyMusicHandler();
return true;
}
bool CMusicPlayer::CreateMusicPlayerMsg(CCreateMusicPlayerMsg *msg) {
if (CMusicRoom::_musicHandler) {
CMusicRoom::_musicHandler->setActive(_musicActive);
return true;
}
CMusicRoomHandler *musicHandler = getMusicRoom()->createMusicHandler();
CMusicRoomInstrument *ins;
if (musicHandler) {
ins = musicHandler->createInstrument(BELLS, 3);
ins->load(0, TRANSLATE("z#490.wav", "z#227.wav"), 60);
ins->load(1, TRANSLATE("z#488.wav", "z#225.wav"), 62);
ins->load(2, TRANSLATE("z#489.wav", "z#226.wav"), 63);
ins = musicHandler->createInstrument(SNAKE, 5);
ins->load(0, TRANSLATE("z#493.wav", "z#230.wav"), 22);
ins->load(1, TRANSLATE("z#495.wav", "z#232.wav"), 29);
ins->load(2, TRANSLATE("z#492.wav", "z#229.wav"), 34);
ins->load(3, TRANSLATE("z#494.wav", "z#231.wav"), 41);
ins->load(4, TRANSLATE("z#491.wav", "z#228.wav"), 46);
ins = musicHandler->createInstrument(PIANO, 5);
ins->load(0, TRANSLATE("z#499.wav", "z#236.wav"), 26);
ins->load(1, TRANSLATE("z#497.wav", "z#234.wav"), 34);
ins->load(2, TRANSLATE("z#498.wav", "z#235.wav"), 38);
ins->load(3, TRANSLATE("z#496.wav", "z#233.wav"), 46);
ins->load(4, TRANSLATE("z#500.wav", "z#237.wav"), 60);
ins = musicHandler->createInstrument(BASS, 7);
ins->load(0, TRANSLATE("z#504.wav", "z#241.wav"), 22);
ins->load(1, TRANSLATE("z#507.wav", "z#244.wav"), 29);
ins->load(2, TRANSLATE("z#503.wav", "z#240.wav"), 34);
ins->load(3, TRANSLATE("z#506.wav", "z#243.wav"), 41);
ins->load(4, TRANSLATE("z#502.wav", "z#239.wav"), 46);
ins->load(5, TRANSLATE("z#505.wav", "z#242.wav"), 53);
ins->load(6, TRANSLATE("z#501.wav", "z#238.wav"), 58);
CMusicRoom::_musicHandler->setActive(_musicActive);
}
return true;
}
bool CMusicPlayer::TimerMsg(CTimerMsg *msg) {
CCreateMusicPlayerMsg playerMsg;
playerMsg.execute(this);
return true;
}
bool CMusicPlayer::LoadSuccessMsg(CLoadSuccessMsg *msg) {
if (_isActive) {
// Music is meant to be playing, so restart it
CStopMusicMsg stopMsg;
stopMsg.execute(this);
CStartMusicMsg startMsg;
startMsg.execute(this);
}
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,63 @@
/* 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/>.
*
*/
#ifndef TITANIC_MUSIC_PLAYER_H
#define TITANIC_MUSIC_PLAYER_H
#include "titanic/core/game_object.h"
#include "titanic/messages/messages.h"
namespace Titanic {
class CMusicPlayer : public CGameObject {
DECLARE_MESSAGE_MAP;
bool StartMusicMsg(CStartMusicMsg *msg);
bool StopMusicMsg(CStopMusicMsg *msg);
bool FrameMsg(CFrameMsg *msg);
bool EnterRoomMsg(CEnterRoomMsg *msg);
bool LeaveRoomMsg(CLeaveRoomMsg *msg);
bool CreateMusicPlayerMsg(CCreateMusicPlayerMsg *msg);
bool TimerMsg(CTimerMsg *msg);
bool LoadSuccessMsg(CLoadSuccessMsg *msg);
protected:
bool _isActive;
CString _stopTarget;
bool _musicActive;
int _volume;
public:
CLASSDEF;
CMusicPlayer() : CGameObject(),
_isActive(false), _musicActive(false), _volume(100) {}
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_MUSIC_PLAYER_H */

View File

@@ -0,0 +1,97 @@
/* 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/>.
*
*/
#include "common/textconsole.h"
#include "titanic/sound/music_room.h"
#include "titanic/sound/sound.h"
#include "titanic/game_manager.h"
namespace Titanic {
CMusicRoomHandler *CMusicRoom::_musicHandler;
CMusicRoom::CMusicRoom(CGameManager *gameManager) :
_gameManager(gameManager) {
_sound = &_gameManager->_sound;
}
CMusicRoom::~CMusicRoom() {
destroyMusicHandler();
}
CMusicRoomHandler *CMusicRoom::createMusicHandler() {
if (_musicHandler)
destroyMusicHandler();
_musicHandler = new CMusicRoomHandler(_gameManager->_project, &_sound->_soundManager);
return _musicHandler;
}
void CMusicRoom::destroyMusicHandler() {
delete _musicHandler;
_musicHandler = nullptr;
}
void CMusicRoom::setupMusic(int volume) {
if (_musicHandler) {
// Set up the control values that form the correct settings
_musicHandler->setSpeedControl2(BELLS, 0);
_musicHandler->setSpeedControl2(SNAKE, 1);
_musicHandler->setSpeedControl2(PIANO, -1);
_musicHandler->setSpeedControl2(BASS, -2);
_musicHandler->setPitchControl2(BELLS, 1);
_musicHandler->setPitchControl2(SNAKE, 2);
_musicHandler->setPitchControl2(PIANO, 0);
_musicHandler->setPitchControl2(BASS, 1);
_musicHandler->setInversionControl2(BELLS, true);
_musicHandler->setInversionControl2(SNAKE, false);
_musicHandler->setInversionControl2(PIANO, true);
_musicHandler->setInversionControl2(BASS, false);
_musicHandler->setDirectionControl2(BELLS, false);
_musicHandler->setDirectionControl2(SNAKE, false);
_musicHandler->setDirectionControl2(PIANO, true);
_musicHandler->setDirectionControl2(BASS, true);
// Set up the current control values
for (MusicInstrument idx = BELLS; idx <= BASS;
idx = (MusicInstrument)((int)idx + 1)) {
MusicRoomInstrument &instr = _instruments[idx];
_musicHandler->setSpeedControl(idx, instr._speedControl);
_musicHandler->setPitchControl(idx, instr._pitchControl);
_musicHandler->setDirectionControl(idx, instr._directionControl);
_musicHandler->setInversionControl(idx, instr._inversionControl);
_musicHandler->setMuteControl(idx, instr._muteControl);
}
// Set up the music handler
_musicHandler->setup(volume);
}
}
void CMusicRoom::stopMusic() {
if (_musicHandler)
_musicHandler->stop();
}
} // End of namespace Titanic

View File

@@ -0,0 +1,103 @@
/* 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/>.
*
*/
#ifndef TITANIC_MUSIC_ROOM_H
#define TITANIC_MUSIC_ROOM_H
#include "common/array.h"
#include "titanic/sound/music_room_handler.h"
namespace Titanic {
class CGameManager;
class CSound;
class CMusicRoom {
private:
MusicRoomInstrument _instruments[4];
public:
static CMusicRoomHandler *_musicHandler;
public:
CGameManager *_gameManager;
CSound *_sound;
public:
CMusicRoom(CGameManager *owner);
~CMusicRoom();
/**
* Creates a music handler
*/
CMusicRoomHandler *createMusicHandler();
/**
* Destroys and currently active music handler
*/
void destroyMusicHandler();
/**
* Sets the speed control for a given instrument
*/
void setSpeedControl(MusicInstrument instrument, int val) {
_instruments[instrument]._speedControl = val;
}
/**
* Sets the pitch control for a given instrument
*/
void setPitchControl(MusicInstrument instrument, int val) {
_instruments[instrument]._pitchControl = val;
}
/**
* Sets the direction control for a given instrument
*/
void setDirectionControl(MusicInstrument instrument, bool val) {
_instruments[instrument]._directionControl = val;
}
/**
* Sets the inversion control for a given instrument
*/
void setInversionControl(MusicInstrument instrument, bool val) {
_instruments[instrument]._inversionControl = val;
}
/**
* Sets the mute control for a given instrument
*/
void setMuteControl(MusicInstrument instrument, bool val) {
_instruments[instrument]._muteControl = val;
}
/**
* Sets up the music controls
*/
void setupMusic(int volume);
/**
* Stop playing music
*/
void stopMusic();
};
} // End of namespace Titanic
#endif /* TITANIC_MUSIC_ROOM_H */

View File

@@ -0,0 +1,347 @@
/* 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/>.
*
*/
#include "titanic/sound/music_room_handler.h"
#include "titanic/sound/sound_manager.h"
#include "titanic/events.h"
#include "titanic/core/project_item.h"
#include "titanic/titanic.h"
namespace Titanic {
CMusicRoomHandler::CMusicRoomHandler(CProjectItem *project, CSoundManager *soundManager) :
_project(project), _soundManager(soundManager), _active(false),
_soundHandle(-1), _waveFile(nullptr), _volume(100) {
_instrumentsActive = 0;
_isPlaying = false;
_startTicks = _soundStartTicks = 0;
Common::fill(&_instruments[0], &_instruments[4], (CMusicRoomInstrument *)nullptr);
for (int idx = 0; idx < 4; ++idx)
_songs[idx] = new CMusicSong(idx);
Common::fill(&_startPos[0], &_startPos[4], 0);
Common::fill(&_animExpiryTime[0], &_animExpiryTime[4], 0.0);
Common::fill(&_position[0], &_position[4], 0);
_audioBuffer = new CAudioBuffer(88200);
}
CMusicRoomHandler::~CMusicRoomHandler() {
stop();
for (int idx = 0; idx < 4; ++idx)
delete _songs[idx];
delete _audioBuffer;
}
CMusicRoomInstrument *CMusicRoomHandler::createInstrument(MusicInstrument instrument, int count) {
switch (instrument) {
case BELLS:
_instruments[BELLS] = new CMusicRoomInstrument(_project, _soundManager, MV_BELLS);
break;
case SNAKE:
_instruments[SNAKE] = new CMusicRoomInstrument(_project, _soundManager, MV_SNAKE);
break;
case PIANO:
_instruments[PIANO] = new CMusicRoomInstrument(_project, _soundManager, MV_PIANO);
break;
case BASS:
_instruments[BASS] = new CMusicRoomInstrument(_project, _soundManager, MV_BASS);
break;
default:
return nullptr;
}
_instruments[instrument]->setFilesCount(count);
return _instruments[instrument];
}
void CMusicRoomHandler::setup(int volume) {
_volume = volume;
_audioBuffer->reset();
for (int idx = 0; idx < 4; ++idx) {
MusicRoomInstrument &ins1 = _array1[idx];
MusicRoomInstrument &ins2 = _array2[idx];
if (ins1._directionControl == ins2._directionControl) {
_startPos[idx] = 0;
} else {
_startPos[idx] = _songs[idx]->size() - 1;
}
_position[idx] = _startPos[idx];
_animExpiryTime[idx] = 0.0;
}
_instrumentsActive = 4;
_isPlaying = true;
update();
_waveFile = _soundManager->loadMusic(_audioBuffer, DisposeAfterUse::NO);
update();
}
void CMusicRoomHandler::stop() {
if (_waveFile) {
_soundManager->stopSound(_soundHandle);
delete _waveFile;
_waveFile = nullptr;
_soundHandle = -1;
}
for (int idx = 0; idx < 4; ++idx) {
_instruments[idx]->clear();
if (_active && _instruments[idx])
_instruments[idx]->stop();
}
_instrumentsActive = 0;
_isPlaying = false;
_startTicks = _soundStartTicks = 0;
}
bool CMusicRoomHandler::checkInstrument(MusicInstrument instrument) const {
return (_array1[instrument]._speedControl + _array2[instrument]._speedControl) == 0
&& (_array1[instrument]._pitchControl + _array2[instrument]._pitchControl) == 0
&& _array1[instrument]._directionControl == _array2[instrument]._directionControl
&& _array1[instrument]._inversionControl == _array2[instrument]._inversionControl
&& _array1[instrument]._muteControl == _array2[instrument]._muteControl;
}
void CMusicRoomHandler::setSpeedControl2(MusicInstrument instrument, int value) {
if (instrument >= BELLS && instrument <= BASS && value >= -2 && value <= 2)
_array2[instrument]._speedControl = value;
}
void CMusicRoomHandler::setPitchControl2(MusicInstrument instrument, int value) {
if (instrument >= BELLS && instrument <= BASS && value >= -2 && value <= 2)
_array2[instrument]._pitchControl = value * 3;
}
void CMusicRoomHandler::setInversionControl2(MusicInstrument instrument, bool value) {
if (instrument >= BELLS && instrument <= BASS)
_array2[instrument]._inversionControl = value;
}
void CMusicRoomHandler::setDirectionControl2(MusicInstrument instrument, bool value) {
if (instrument >= BELLS && instrument <= BASS)
_array2[instrument]._directionControl = value;
}
void CMusicRoomHandler::setPitchControl(MusicInstrument instrument, int value) {
if (instrument >= BELLS && instrument <= BASS && value >= -2 && value <= 2)
_array1[instrument]._pitchControl = value * 3;
}
void CMusicRoomHandler::setSpeedControl(MusicInstrument instrument, int value) {
if (instrument >= BELLS && instrument <= BASS && value >= -2 && value <= 2)
_array1[instrument]._speedControl = value;
}
void CMusicRoomHandler::setDirectionControl(MusicInstrument instrument, bool value) {
if (instrument >= BELLS && instrument <= BASS)
_array1[instrument]._directionControl = value;
}
void CMusicRoomHandler::setInversionControl(MusicInstrument instrument, bool value) {
if (instrument >= BELLS && instrument <= BASS)
_array1[instrument]._inversionControl = value;
}
void CMusicRoomHandler::setMuteControl(MusicInstrument instrument, bool value) {
if (instrument >= BELLS && instrument <= BASS)
_array1[instrument]._muteControl = value;
}
void CMusicRoomHandler::start() {
if (_active) {
for (int idx = 0; idx < 4; ++idx)
_instruments[idx]->start();
}
}
bool CMusicRoomHandler::update() {
uint currentTicks = g_system->getMillis();
if (!_startTicks) {
start();
_startTicks = currentTicks;
} else if (!_soundStartTicks && currentTicks >= (_startTicks + 3000)) {
if (_waveFile) {
CProximity prox;
prox._channelVolume = _volume;
_soundHandle = _soundManager->playSound(*_waveFile, prox);
}
_soundStartTicks = currentTicks;
}
if (_instrumentsActive > 0) {
updateAudio();
updateInstruments();
}
return !_audioBuffer->isFinished();
}
void CMusicRoomHandler::updateAudio() {
int size = _audioBuffer->freeSize();
int count;
int16 *ptr;
if (size > 0) {
// Create a temporary buffer for merging the instruments into
int16 *audioData = new int16[size];
Common::fill(audioData, audioData + size, 0);
for (MusicInstrument instrument = BELLS; instrument <= BASS;
instrument = (MusicInstrument)((int)instrument + 1)) {
CMusicRoomInstrument *musicWave = _instruments[instrument];
// Iterate through each of the four instruments and do an additive
// read that will merge their data onto the output buffer
for (count = size, ptr = audioData; count > 0; ) {
int amount = musicWave->read(ptr, count * 2);
if (amount > 0) {
count -= amount / sizeof(uint16);
ptr += amount / sizeof(uint16);
} else if (!pollInstrument(instrument)) {
--_instrumentsActive;
break;
}
}
}
_audioBuffer->push(audioData, size);
delete[] audioData;
}
if (_instrumentsActive == 0)
// Reaching end of music
_audioBuffer->finalize();
}
void CMusicRoomHandler::updateInstruments() {
uint currentTicks = g_system->getMillis();
if (_active && _soundStartTicks) {
for (MusicInstrument instrument = BELLS; instrument <= BASS;
instrument = (MusicInstrument)((int)instrument + 1)) {
MusicRoomInstrument &ins1 = _array1[instrument];
MusicRoomInstrument &ins2 = _array2[instrument];
CMusicRoomInstrument *ins = _instruments[instrument];
// Is this about checking playback position?
if (_position[instrument] < 0 || ins1._muteControl || _position[instrument] >= _songs[instrument]->size()) {
_position[instrument] = -1;
continue;
}
double time = (double)(currentTicks - _soundStartTicks) / 1000.0 - 0.6;
double threshold = _animExpiryTime[instrument] - ins->_insStartTime;
if (time >= threshold) {
_animExpiryTime[instrument] += getAnimDuration(instrument, _position[instrument]);
const CValuePair &vp = (*_songs[instrument])[_position[instrument]];
if (vp._data != 0x7FFFFFFF) {
int amount = getPitch(instrument, _position[instrument]);
_instruments[instrument]->update(amount);
}
if (ins1._directionControl == ins2._directionControl) {
_position[instrument]++;
} else {
_position[instrument]--;
}
}
}
}
}
bool CMusicRoomHandler::pollInstrument(MusicInstrument instrument) {
int &arrIndex = _startPos[instrument];
if (arrIndex < 0) {
_instruments[instrument]->clear();
return false;
}
const CMusicSong &song = *_songs[instrument];
if (arrIndex >= song.size()) {
arrIndex = -1;
_instruments[instrument]->clear();
return false;
}
const CValuePair &vp = song[arrIndex];
uint duration = static_cast<int>(getAnimDuration(instrument, arrIndex) * 44100.0) & ~1;
if (vp._data == 0x7FFFFFFF || _array1[instrument]._muteControl)
_instruments[instrument]->reset(duration);
else
_instruments[instrument]->chooseWaveFile(getPitch(instrument, arrIndex), duration);
if (_array1[instrument]._directionControl == _array2[instrument]._directionControl) {
++arrIndex;
} else {
--arrIndex;
}
return true;
}
double CMusicRoomHandler::getAnimDuration(MusicInstrument instrument, int arrIndex) {
const CValuePair &vp = (*_songs[instrument])[arrIndex];
switch (_array1[instrument]._speedControl + _array2[instrument]._speedControl + 3) {
case 0:
return (double)vp._length * 1.5 * 0.0625 * 0.46875;
case 1:
return (double)vp._length * 1.33 * 0.0625 * 0.46875;
case 2:
return (double)vp._length * 1.25 * 0.0625 * 0.46875;
case 4:
return (double)vp._length * 0.75 * 0.0625 * 0.46875;
case 5:
return (double)vp._length * 0.67 * 0.0625 * 0.46875;
case 6:
return (double)vp._length * 0.5 * 0.0625 * 0.46875;
default:
return (double)vp._length * 1.0 * 0.0625 * 0.46875;
}
}
int CMusicRoomHandler::getPitch(MusicInstrument instrument, int arrIndex) {
const CMusicSong &song = *_songs[instrument];
const CValuePair &vp = song[arrIndex];
int val = vp._data;
const MusicRoomInstrument &ins1 = _array1[instrument];
const MusicRoomInstrument &ins2 = _array2[instrument];
if (ins1._inversionControl != ins2._inversionControl) {
val = song._minVal * 2 + song._range - val;
}
val += ins1._pitchControl + ins2._pitchControl;
return val;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,189 @@
/* 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/>.
*
*/
#ifndef TITANIC_MUSIC_ROOM_HANDLER_H
#define TITANIC_MUSIC_ROOM_HANDLER_H
#include "titanic/sound/audio_buffer.h"
#include "titanic/sound/music_room_instrument.h"
#include "titanic/sound/music_song.h"
#include "titanic/sound/wave_file.h"
namespace Titanic {
class CProjectItem;
class CSoundManager;
enum MusicInstrument { BELLS = 0, SNAKE = 1, PIANO = 2, BASS = 3 };
struct MusicRoomInstrument {
int _pitchControl;
int _speedControl;
bool _directionControl;
bool _inversionControl;
bool _muteControl;
MusicRoomInstrument() : _pitchControl(0), _speedControl(0), _directionControl(false),
_inversionControl(false), _muteControl(false) {}
};
class CMusicRoomHandler {
private:
CProjectItem *_project;
CSoundManager *_soundManager;
CMusicRoomInstrument *_instruments[4];
MusicRoomInstrument _array1[4];
MusicRoomInstrument _array2[4];
CMusicSong *_songs[4];
int _startPos[4];
int _position[4];
double _animExpiryTime[4];
bool _active;
CWaveFile *_waveFile;
int _soundHandle;
int _instrumentsActive;
CAudioBuffer *_audioBuffer;
bool _isPlaying;
uint _soundStartTicks;
uint _startTicks;
int _volume;
private:
/**
* Starts music room instruments animation
*/
void start();
/**
* Handles updating the raw audio being played for all the instruments
*/
void updateAudio();
/**
* Handles updating the instruments themselves, and keeping them animating
*/
void updateInstruments();
/**
* Polls a specified instrument for any updates to see if it's still active.
* @returns Returns true if a given instrument is still active..
* that is, that there is still more data that can be read from it to play
*/
bool pollInstrument(MusicInstrument instrument);
/**
* Gets the duration for a given fragment of an instrument to play
* out, so that animations of the instruments can be synchronized
* to the actual music
*/
double getAnimDuration(MusicInstrument instrument, int arrIndex);
/**
* Figures out a pitch value (of some sort) for use in determining
* which wave file the music instruments will use.
*/
int getPitch(MusicInstrument instrument, int arrIndex);
public:
CMusicRoomHandler(CProjectItem *project, CSoundManager *soundManager);
~CMusicRoomHandler();
/**
* Creates a new music room instrument class to handle the operation of one
* of the instruments in the music room.
* @param instrument Which instrument to create for
* @param count Number of Wave files the new instance will contain
*/
CMusicRoomInstrument *createInstrument(MusicInstrument instrument, int count);
/**
* Main setup for the music room handler
*/
void setup(int volume);
/**
* Flags whether the music handler is active
*/
void setActive(bool flag) { _active = flag; }
/**
* Stop playing the music
*/
void stop();
/**
* Checks the specified instrument to see if it's settings are "correct"
*/
bool checkInstrument(MusicInstrument instrument) const;
/**
* Sets the speed control value
*/
void setSpeedControl2(MusicInstrument instrument, int value);
/**
* Sets the pitch control value
*/
void setPitchControl2(MusicInstrument instrument, int value);
/**
* Sets the inversion control value
*/
void setInversionControl2(MusicInstrument instrument, bool value);
/**
* Sets the direction control value
*/
void setDirectionControl2(MusicInstrument instrument, bool value);
/**
* Sets the pitch control value
*/
void setPitchControl(MusicInstrument instrument, int value);
/**
* Sets the speed control value
*/
void setSpeedControl(MusicInstrument instrument, int value);
/**
* Sets the direction control value
*/
void setDirectionControl(MusicInstrument instrument, bool value);
/**
* Sets the inversion control value
*/
void setInversionControl(MusicInstrument instrument, bool value);
/**
* Sets the mute control value
*/
void setMuteControl(MusicInstrument instrument, bool value);
/**
* Handles regular updates
* @returns True if the music is still playing
*/
bool update();
};
} // End of namespace Titanic
#endif /* TITANIC_MUSIC_ROOM_HANDLER_H */

View File

@@ -0,0 +1,355 @@
/* 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/>.
*
*/
#include "titanic/sound/music_room_instrument.h"
#include "titanic/sound/sound_manager.h"
#include "titanic/core/project_item.h"
#include "titanic/core/game_object.h"
namespace Titanic {
bool CMusicRoomInstrument::_pianoToggle;
int CMusicRoomInstrument::_pianoCtr;
int CMusicRoomInstrument::_bassCtr;
byte *CMusicRoomInstrument::_buffer;
double *CMusicRoomInstrument::_array;
int CMusicRoomInstrument::_arrayIndex;
void CMusicRoomInstrument::init() {
_pianoToggle = false;
_pianoCtr = 0;
_bassCtr = 0;
_buffer = nullptr;
_array = nullptr;
_arrayIndex = 0;
}
void CMusicRoomInstrument::deinit() {
delete[] _buffer;
delete[] _array;
_buffer = nullptr;
}
CMusicRoomInstrument::CMusicRoomInstrument(CProjectItem *project, CSoundManager *soundManager, MusicWaveInstrument instrument) :
_project(project), _soundManager(soundManager), _instrument(instrument) {
Common::fill(&_gameObjects[0], &_gameObjects[4], (CGameObject *)nullptr);
_insStartTime = 0.0;
_waveIndex = -1;
_readPos = 0;
_readIncrement = 0;
_size = 0;
_count = 0;
_field4C = 0;
switch (instrument) {
case MV_PIANO:
_gameObjects[0] = static_cast<CGameObject *>(_project->findByName("Piano Man"));
_gameObjects[1] = static_cast<CGameObject *>(_project->findByName("Piano Mouth"));
_gameObjects[2] = static_cast<CGameObject *>(_project->findByName("Piano Left Arm"));
_gameObjects[3] = static_cast<CGameObject *>(_project->findByName("Piano Right Arm"));
_insStartTime = 0.45;
break;
case MV_BASS:
_gameObjects[0] = static_cast<CGameObject *>(_project->findByName("Bass Player"));
break;
case MV_BELLS:
_gameObjects[0] = static_cast<CGameObject *>(_project->findByName("Tubular Bells"));
_insStartTime = 0.4;
break;
case MV_SNAKE:
_gameObjects[0] = static_cast<CGameObject *>(_project->findByName("Snake_Hammer"));
_gameObjects[1] = static_cast<CGameObject *>(_project->findByName("Snake_Glass"));
_gameObjects[2] = static_cast<CGameObject *>(_project->findByName("Snake_Head"));
_insStartTime = 0.17;
break;
default:
break;
}
}
void CMusicRoomInstrument::setFilesCount(uint count) {
assert(_items.empty());
_items.resize(count);
}
void CMusicRoomInstrument::load(int index, const CString &filename, int v3) {
assert(!_items[index]._waveFile);
_items[index]._waveFile = createWaveFile(filename);
_items[index]._value = v3;
}
CWaveFile *CMusicRoomInstrument::createWaveFile(const CString &name) {
if (name.empty())
return nullptr;
return _soundManager->loadSound(name);
}
void CMusicRoomInstrument::start() {
if (_gameObjects[0]) {
switch (_instrument) {
case MV_PIANO:
_gameObjects[0]->playMovie(0, 29, MOVIE_STOP_PREVIOUS);
_gameObjects[2]->loadFrame(14);
_gameObjects[3]->loadFrame(22);
break;
case MV_BELLS:
_gameObjects[0]->loadFrame(0);
_gameObjects[0]->movieSetPlaying(true);
break;
case MV_SNAKE:
_field4C = 22;
_gameObjects[1]->playMovie(0, 22, 0);
_gameObjects[2]->playMovie(0, 35, MOVIE_STOP_PREVIOUS);
_gameObjects[0]->playMovie(0, 1, MOVIE_STOP_PREVIOUS);
_gameObjects[0]->playMovie(0, 1, 0);
_gameObjects[0]->playMovie(0, 1, 0);
_gameObjects[0]->playMovie(0, 1, 0);
_gameObjects[0]->playMovie(0, 1, 0);
break;
default:
break;
}
}
}
void CMusicRoomInstrument::stop() {
if (_gameObjects[0]) {
switch (_instrument) {
case MV_PIANO:
_gameObjects[1]->setVisible(false);
_gameObjects[2]->setVisible(false);
_gameObjects[3]->setVisible(false);
_gameObjects[0]->playMovie(29, 58, MOVIE_STOP_PREVIOUS);
break;
case MV_BELLS:
_gameObjects[0]->stopMovie();
break;
default:
break;
}
}
}
void CMusicRoomInstrument::update(int val) {
if (_gameObjects[0]) {
switch (_instrument) {
case MV_PIANO:
_gameObjects[1]->setVisible(true);
_gameObjects[2]->setVisible(true);
_gameObjects[3]->setVisible(true);
_gameObjects[_pianoToggle ? 3 : 2]->playMovie(MOVIE_STOP_PREVIOUS);
_pianoToggle = !_pianoToggle;
switch (_pianoCtr) {
case 0:
_gameObjects[1]->playMovie(0, 4, MOVIE_STOP_PREVIOUS);
break;
case 1:
_gameObjects[1]->playMovie(4, 8, MOVIE_STOP_PREVIOUS);
break;
case 2:
_gameObjects[1]->playMovie(8, 12, MOVIE_STOP_PREVIOUS);
break;
case 3:
_gameObjects[1]->playMovie(12, 16, MOVIE_STOP_PREVIOUS);
break;
default:
break;
}
_pianoCtr = (_pianoCtr + 1) % 4;
break;
case MV_BASS:
switch (_bassCtr) {
case 0:
_gameObjects[0]->playMovie(0, 7, MOVIE_STOP_PREVIOUS);
break;
case 1:
_gameObjects[0]->playMovie(7, 14, MOVIE_STOP_PREVIOUS);
break;
case 2:
_gameObjects[0]->playMovie(15, 24, MOVIE_STOP_PREVIOUS);
break;
case 3:
_gameObjects[0]->playMovie(25, 33, MOVIE_STOP_PREVIOUS);
break;
default:
break;
}
// WORKAROUND: Original didn't change the selected bass animation
_bassCtr = (_bassCtr + 1) % 4;
break;
case MV_BELLS:
switch (val) {
case 60:
_gameObjects[0]->playMovie(0, 512, MOVIE_STOP_PREVIOUS);
_gameObjects[0]->movieSetPlaying(true);
_insStartTime = 0.6;
break;
case 62:
_gameObjects[0]->playMovie(828, 1023, MOVIE_STOP_PREVIOUS);
_insStartTime = 0.3;
break;
case 63:
_gameObjects[0]->playMovie(1024, 1085, MOVIE_STOP_PREVIOUS);
break;
default:
break;
}
break;
case MV_SNAKE: {
_gameObjects[0]->playMovie(0, 7, MOVIE_STOP_PREVIOUS);
double tempVal = 46.0 - ((double)(val - 14) * 1.43);
int frameNum = _field4C;
int frameNum1 = (int)((tempVal - frameNum) * 0.25);
_gameObjects[1]->playMovie(frameNum1, frameNum1, MOVIE_STOP_PREVIOUS);
frameNum += frameNum1;
_gameObjects[1]->playMovie(frameNum, frameNum, 0);
frameNum += frameNum1;
_gameObjects[1]->playMovie(frameNum, frameNum, 0);
_gameObjects[2]->playMovie(45, 49, MOVIE_STOP_PREVIOUS);
break;
}
default:
break;
}
}
}
void CMusicRoomInstrument::clear() {
_waveIndex = 0;
_readPos = 0;
_readIncrement = 0;
_size = 0;
_count = 0;
}
void CMusicRoomInstrument::reset(uint total) {
_waveIndex = -1;
_readPos = 0;
_readIncrement = 0;
_size = total;
_count = 0;
}
int CMusicRoomInstrument::read(int16 *ptr, uint size) {
if (!_size)
return 0;
if (size >= _size)
size = _size;
if (_waveIndex != -1) {
// Lock the specified wave file for access
const int16 *data = _items[_waveIndex]._waveFile->lock();
assert(data);
const int16 *src = data;
// Loop through merging data from the wave file into the dest buffer
for (uint idx = 0; idx < (size / sizeof(int16)); ++idx, _readPos += _readIncrement) {
uint srcPos = _readPos >> 8;
if (srcPos >= _count)
break;
int16 val = READ_LE_UINT16(src + srcPos);
*ptr++ += val;
}
// Unlock the wave file
_items[_waveIndex]._waveFile->unlock(data);
}
_size -= size;
return size;
}
void CMusicRoomInstrument::chooseWaveFile(int index, int size) {
if (!_array)
setupArray(-36, 36);
int minDiff = ABS(_items[0]._value - index);
int waveIndex = 0;
for (uint idx = 1; idx < _items.size(); ++idx) {
int diff = ABS(_items[idx]._value - index);
if (diff < minDiff) {
minDiff = diff;
waveIndex = idx;
}
}
const CInstrumentWaveFile &wf = _items[waveIndex];
int arrIndex = _arrayIndex - wf._value + index;
uint waveSize = wf._waveFile->size();
_waveIndex = waveIndex;
_readPos = 0;
_readIncrement = (int)(_array[arrIndex] * 256);
_size = size;
_count = waveSize / 2;
}
void CMusicRoomInstrument::setupArray(int minVal, int maxVal) {
// Delete any prior array and recreate it
delete[] _array;
int arrSize = maxVal - minVal + 1;
_array = new double[arrSize];
_arrayIndex = ABS(minVal);
// Setup array contents
_array[_arrayIndex] = 1.0;
double val = 1.0594634;
for (int idx = 1; idx <= maxVal; ++idx) {
_array[_arrayIndex + idx] = val;
val *= 1.0594634;
}
val = 0.94387404038686;
for (int idx = -1; idx >= minVal; --idx) {
_array[_arrayIndex + idx] = val;
val *= 0.94387404038686;
}
}
} // End of namespace Titanic

View File

@@ -0,0 +1,141 @@
/* 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/>.
*
*/
#ifndef TITANIC_MUSIC_ROOM_INSTRUMENT_H
#define TITANIC_MUSIC_ROOM_INSTRUMENT_H
#include "common/array.h"
#include "titanic/support/string.h"
namespace Titanic {
enum MusicWaveInstrument { MV_PIANO = 0, MV_BASS = 1, MV_BELLS = 2, MV_SNAKE = 3 };
class CProjectItem;
class CSoundManager;
class CWaveFile;
class CGameObject;
class CMusicRoomInstrument {
struct CInstrumentWaveFile {
CWaveFile *_waveFile;
int _value;
CInstrumentWaveFile() : _waveFile(nullptr), _value(0) {}
};
private:
static bool _pianoToggle;
static int _pianoCtr;
static int _bassCtr;
static byte *_buffer;
static double *_array;
static int _arrayIndex;
private:
CSoundManager *_soundManager;
Common::Array<CInstrumentWaveFile> _items;
MusicWaveInstrument _instrument;
CProjectItem *_project;
CGameObject *_gameObjects[4];
int _waveIndex;
int _readPos;
int _readIncrement;
uint _size;
uint _count;
int _field4C;
private:
/**
* Loads the specified wave file, and returns a CWaveFile instance for it
*/
CWaveFile *createWaveFile(const CString &name);
/**
* Sets up an array used for figuring out the sequence in which to
* play the different wave files for each instrument to give the
* music based on the console's settings
*/
void setupArray(int minVal, int maxVal);
public:
double _insStartTime;
public:
/**
* Handles initialization of static fields
*/
static void init();
/**
* Deinitialization of static fields
*/
static void deinit();
public:
CMusicRoomInstrument(CProjectItem *project, CSoundManager *soundManager, MusicWaveInstrument instrument);
/**
* Sets the maximum number of allowed files that be defined
*/
void setFilesCount(uint count);
/**
* Loads a new file into the list of available entries
*/
void load(int index, const CString &filename, int v3);
/**
* Starts the music and associated animations
*/
void start();
/**
* Stops the music and associated animations
*/
void stop();
/**
* Handles regular updates of the instrument, allowing associated
* objects to start animations as the music is played
*/
void update(int val);
/**
* Clear the instrument
*/
void clear();
/**
* Resets the instrument, and sets the maximum for how much data can
* be read from the wave files during each read action
*/
void reset(uint total);
/**
* If there is any wave file currently specified, reads it in
* and merges it into the supplied buffer
*/
int read(int16 *ptr, uint size);
/**
* Figure out which wave file to use next
*/
void chooseWaveFile(int index, int freq);
};
} // End of namespace Titanic
#endif /* TITANIC_MUSIC_ROOM_INSTRUMENT_H */

View File

@@ -0,0 +1,192 @@
/* 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/>.
*
*/
#include "titanic/sound/music_song.h"
#include "titanic/support/files_manager.h"
#include "titanic/titanic.h"
#include "common/util.h"
namespace Titanic {
CMusicSong::CMusicSong(int index) {
// Read in the list of song strings
Common::SeekableReadStream *res = g_vm->_filesManager->getResource("MUSIC/PARSER");
Common::StringArray parserStrings;
while (res->pos() < res->size())
parserStrings.push_back(readStringFromStream(res));
delete res;
// Set up a new song parser with the desired string
CSongParser parser(parserStrings[index].c_str());
// Count how many encoded values there are
CValuePair r;
int count = 0;
while (parser.parse(r))
++count;
assert(count > 0);
// Read in the values to the array
_data.resize(count);
parser.reset();
for (int idx = 0; idx < count; ++idx)
parser.parse(_data[idx]);
// Figure out the range of values in the array
_minVal = 0x7FFFFFFF;
int maxVal = -0x7FFFFFFF;
for (int idx = 0; idx < count; ++idx) {
CValuePair &vp = _data[idx];
if (vp._data != 0x7FFFFFFF) {
if (vp._data < _minVal)
_minVal = vp._data;
if (vp._data > maxVal)
maxVal = vp._data;
}
}
_range = maxVal - _minVal;
}
CMusicSong::~CMusicSong() {
_data.clear();
}
/*------------------------------------------------------------------------*/
#define FETCH_CHAR _currentChar = _str[_strIndex++]
CSongParser::CSongParser(const char *str) : _str(str), _strIndex(0),
_field8(0), _priorChar('A'), _field10(32), _field14(0), _flag(false),
_field1C(0), _currentChar(' '), _numValue(1) {
}
void CSongParser::reset() {
_strIndex = 0;
_field8 = 0;
_field10 = 0;
_field14 = 0;
_currentChar = ' ';
_priorChar = 'A';
_numValue = 1;
_field1C = 0;
}
bool CSongParser::parse(CValuePair &r) {
const int INDEXES[8] = { 0, 2, 3, 5, 7, 8, 10, 0 };
while (_currentChar) {
skipSpaces();
if (Common::isDigit(_currentChar)) {
// Parse the number
Common::String numStr;
do {
numStr += _currentChar;
FETCH_CHAR;
} while (_currentChar && Common::isDigit(_currentChar));
_numValue = atoi(numStr.c_str());
} else if (_currentChar == ',') {
_field10 = _numValue;
FETCH_CHAR;
} else if (_currentChar == ':') {
_priorChar = 'A';
_field8 = _numValue * 12;
FETCH_CHAR;
} else if (_currentChar == '/') {
r._length += _field10;
_field1C += _field10;
FETCH_CHAR;
} else if (_currentChar == '+') {
++_field14;
FETCH_CHAR;
} else if (_currentChar == '-') {
--_field14;
FETCH_CHAR;
} else if (_currentChar == '^') {
if (_flag)
break;
_flag = true;
r._data = 0x7FFFFFFF;
r._length = _field10;
_field14 = 0;
_field1C += _field10;
FETCH_CHAR;
} else if (_currentChar == '|') {
_field1C = 0;
FETCH_CHAR;
} else if (Common::isAlpha(_currentChar)) {
if (_flag)
break;
int val1 = INDEXES[tolower(_currentChar) - 'a'];
int val2 = INDEXES[tolower(_priorChar) - 'a'];
bool flag = true;
if (_currentChar == _priorChar) {
r._data = _field8;
} else if (_currentChar >= 'a' && _currentChar <= 'g') {
val1 -= val2;
if (val1 >= 0)
val1 -= 12;
r._data = _field8 + val1;
} else if (_currentChar >= 'A' && _currentChar <= 'G') {
val1 -= val2;
if (val1 <= 0)
val1 += 12;
r._data = _field8 + val1;
} else {
flag = false;
}
if (flag) {
r._length = _field10;
_field1C += _field10;
_field8 = r._data;
_priorChar = _currentChar;
r._data += _field14;
_field14 = 0;
_flag = true;
}
FETCH_CHAR;
} else {
FETCH_CHAR;
}
}
if (!_flag)
return false;
_flag = false;
return true;
}
void CSongParser::skipSpaces() {
while (_currentChar && Common::isSpace(_currentChar)) {
FETCH_CHAR;
}
}
} // End of namespace Titanic

View File

@@ -0,0 +1,80 @@
/* 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/>.
*
*/
#ifndef TITANIC_MUSIC_SONG_H
#define TITANIC_MUSIC_SONG_H
#include "common/scummsys.h"
#include "common/array.h"
namespace Titanic {
struct CValuePair {
int _data;
int _length;
CValuePair() : _data(0), _length(0) {}
};
class CMusicSong {
public:
Common::Array<CValuePair> _data;
int _minVal;
int _range;
public:
CMusicSong(int index);
~CMusicSong();
int size() const { return _data.size(); }
const CValuePair &operator[](int index) const { return _data[index]; }
};
class CSongParser {
private:
const char *_str;
uint _strIndex;
int _field8;
char _priorChar;
int _field10;
int _field14;
bool _flag;
int _field1C;
char _currentChar;
int _numValue;
private:
void skipSpaces();
public:
CSongParser(const char *str);
/**
* Resets the parser
*/
void reset();
/**
* Parses a value from the string
*/
bool parse(CValuePair &r);
};
} // End of namespace Titanic
#endif /* TITANIC_MUSIC_SONG_H */

View File

@@ -0,0 +1,83 @@
/* 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/>.
*
*/
#include "titanic/sound/node_auto_sound_player.h"
#include "titanic/sound/auto_music_player.h"
#include "titanic/core/room_item.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CNodeAutoSoundPlayer, CAutoSoundPlayer)
ON_MESSAGE(EnterNodeMsg)
ON_MESSAGE(LeaveNodeMsg)
END_MESSAGE_MAP()
void CNodeAutoSoundPlayer::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeNumberLine(_enabled, indent);
CAutoSoundPlayer::save(file, indent);
}
void CNodeAutoSoundPlayer::load(SimpleFile *file) {
file->readNumber();
_enabled = file->readNumber();
CAutoSoundPlayer::load(file);
}
bool CNodeAutoSoundPlayer::EnterNodeMsg(CEnterNodeMsg *msg) {
CNodeItem *node = findNode();
CRoomItem *room = findRoom();
if (node == msg->_newNode) {
CTurnOn onMsg;
onMsg.execute(this);
if (_enabled) {
CChangeMusicMsg changeMsg;
changeMsg._action = MUSIC_STOP;
changeMsg.execute(room, CAutoMusicPlayer::_type,
MSGFLAG_CLASS_DEF | MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_SCAN);
}
}
return true;
}
bool CNodeAutoSoundPlayer::LeaveNodeMsg(CLeaveNodeMsg *msg) {
CNodeItem *node = findNode();
CRoomItem *room = findRoom();
if (node == msg->_oldNode) {
CTurnOff offMsg;
offMsg.execute(this);
if (_enabled) {
CChangeMusicMsg changeMsg;
changeMsg._action = MUSIC_START;
changeMsg.execute(room, CAutoMusicPlayer::_type,
MSGFLAG_CLASS_DEF | MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_SCAN);
}
}
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,53 @@
/* 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/>.
*
*/
#ifndef TITANIC_NODE_AUTO_SOUND_PLAYER_H
#define TITANIC_NODE_AUTO_SOUND_PLAYER_H
#include "titanic/sound/auto_sound_player.h"
#include "titanic/messages/messages.h"
namespace Titanic {
class CNodeAutoSoundPlayer : public CAutoSoundPlayer {
DECLARE_MESSAGE_MAP;
bool EnterNodeMsg(CEnterNodeMsg *msg);
bool LeaveNodeMsg(CLeaveNodeMsg *msg);
private:
bool _enabled;
public:
CLASSDEF;
CNodeAutoSoundPlayer() : CAutoSoundPlayer(), _enabled(true) {}
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_NODE_AUTO_SOUND_PLAYER_H */

View File

@@ -0,0 +1,47 @@
/* 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/>.
*
*/
#include "titanic/sound/proximity.h"
#include "titanic/true_talk/tt_talker.h"
namespace Titanic {
CProximity::CProximity() : _channelVolume(100), _balance(0),
_priorSoundHandle(-1), _frequencyMultiplier(0.0), _frequencyAdjust(1.875),
_repeated(false), _channelMode(10), _positioningMode(POSMODE_NONE),
_azimuth(0.0), _range(0.5), _elevation(0),
_posX(0.0), _posY(0.0), _posZ(0.0),
_hasVelocity(false), _velocityX(0), _velocityY(0), _velocityZ(0),
_disposeAfterUse(DisposeAfterUse::NO), _endTalkerFn(nullptr), _talker(nullptr),
_soundDuration(0), _soundType(Audio::Mixer::kPlainSoundType) {
}
CProximity::CProximity(Audio::Mixer::SoundType soundType, int volume) :
_soundType(soundType), _channelVolume(volume),
_balance(0), _priorSoundHandle(-1), _frequencyMultiplier(0.0),
_frequencyAdjust(1.875), _repeated(false), _channelMode(10),
_positioningMode(POSMODE_NONE), _azimuth(0.0), _range(0.5), _elevation(0),
_posX(0.0), _posY(0.0), _posZ(0.0), _hasVelocity(false), _velocityX(0),
_velocityY(0), _velocityZ(0), _disposeAfterUse(DisposeAfterUse::NO),
_endTalkerFn(nullptr), _talker(nullptr), _soundDuration(0) {
}
} // End of namespace Titanic

View File

@@ -0,0 +1,68 @@
/* 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/>.
*
*/
#ifndef TITANIC_PROXIMITY_H
#define TITANIC_PROXIMITY_H
#include "audio/mixer.h"
#include "common/scummsys.h"
namespace Titanic {
enum PositioningMode { POSMODE_NONE = 0, POSMODE_POLAR = 1, POSMODE_VECTOR = 2 };
class TTtalker;
typedef void (*CEndTalkerFn)(TTtalker *talker);
class CProximity {
public:
int _channelVolume;
int _balance;
int _priorSoundHandle;
double _frequencyMultiplier;
double _frequencyAdjust;
bool _repeated;
int _channelMode;
PositioningMode _positioningMode;
double _azimuth;
double _range;
double _elevation;
double _posX;
double _posY;
double _posZ;
bool _hasVelocity;
double _velocityX;
double _velocityY;
double _velocityZ;
DisposeAfterUse::Flag _disposeAfterUse;
CEndTalkerFn _endTalkerFn;
TTtalker *_talker;
uint _soundDuration;
Audio::Mixer::SoundType _soundType;
public:
CProximity();
CProximity(Audio::Mixer::SoundType soundType, int volume = 100);
};
} // End of namespace Titanic
#endif /* TITANIC_PROXIMITY_H */

View File

@@ -0,0 +1,254 @@
/* 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/>.
*
*/
#include "titanic/sound/qmixer.h"
#include "titanic/debugger.h"
#include "common/system.h"
namespace Titanic {
QMixer::QMixer(Audio::Mixer *mixer) : _mixer(mixer) {
}
QMixer::~QMixer() {
_channels.clear();
}
bool QMixer::qsWaveMixInitEx(const QMIXCONFIG &config) {
assert(_channels.empty());
assert(config.iChannels > 0 && config.iChannels < 256);
_channels.resize(config.iChannels);
return true;
}
void QMixer::qsWaveMixActivate(bool fActivate) {
// Not currently implemented in ScummVM
}
int QMixer::qsWaveMixOpenChannel(int iChannel, QMixFlag mode) {
// Not currently implemented in ScummVM
return 0;
}
int QMixer::qsWaveMixEnableChannel(int iChannel, uint flags, bool enabled) {
// Not currently implemented in ScummVM
return 0;
}
void QMixer::qsWaveMixCloseSession() {
_mixer->stopAll();
_channels.clear();
}
void QMixer::qsWaveMixFreeWave(Audio::SoundHandle &handle) {
_mixer->stopHandle(handle);
}
void QMixer::qsWaveMixFlushChannel(int iChannel, uint flags) {
if (flags & QMIX_OPENALL) {
// Ignore channel, and flush all the channels
for (uint idx = 0; idx < _channels.size(); ++idx)
qsWaveMixFlushChannel(idx, 0);
} else {
// Flush the specified channel
Common::List<SoundEntry>::iterator i;
Common::List<SoundEntry> &sounds = _channels[iChannel]._sounds;
for (i = sounds.begin(); i != sounds.end(); ++i)
_mixer->stopHandle((*i)._soundHandle);
sounds.clear();
}
}
void QMixer::qsWaveMixSetPanRate(int iChannel, uint flags, uint rate) {
ChannelEntry &channel = _channels[iChannel];
channel._panRate = rate;
channel._volumeChangeStart = channel._volumeChangeEnd = 0;
}
void QMixer::qsWaveMixSetVolume(int iChannel, uint flags, uint volume) {
ChannelEntry &channel = _channels[iChannel];
// QMixer volumes go from 0-32767, but we need to convert to 0-255 for ScummVM
assert(volume <= 32767);
byte newVolume = (volume >= 32700) ? 255 : volume * 255 / 32767;
channel._volumeStart = channel._volume;
channel._volumeEnd = newVolume;
channel._volumeChangeStart = g_system->getMillis();
channel._volumeChangeEnd = channel._volumeChangeStart + channel._panRate;
debugC(DEBUG_DETAILED, kDebugCore, "qsWaveMixSetPanRate vol=%d to %d, start=%u, end=%u",
channel._volumeStart, channel._volumeEnd, channel._volumeChangeStart, channel._volumeChangeEnd);
}
void QMixer::qsWaveMixSetSourcePosition(int iChannel, uint flags, const QSVECTOR &position) {
ChannelEntry &channel = _channels[iChannel];
// Flag whether distance should reset when a new sound is started
channel._resetDistance = (flags & QMIX_USEONCE) != 0;
// Currently, we only do a basic simulation of spatial positioning by
// getting the distance, and proportionately reducing the volume the
// further away the source is
channel._distance = sqrt(position.x * position.x + position.y * position.y
+ position.z * position.z);
}
void QMixer::qsWaveMixSetPolarPosition(int iChannel, uint flags, const QSPOLAR &position) {
ChannelEntry &channel = _channels[iChannel];
// Flag whether distance should reset when a new sound is started
channel._resetDistance = (flags & QMIX_USEONCE) != 0;
// Currently, we only do a basic simulation of spatial positioning by
// getting the distance, and proportionately reducing the volume the
// further away the source is
channel._distance = position.range;
}
void QMixer::qsWaveMixSetListenerPosition(const QSVECTOR &position, uint flags) {
// Not currently implemented in ScummVM
}
void QMixer::qsWaveMixSetListenerOrientation(const QSVECTOR &direction, const QSVECTOR &up, uint flags) {
// Not currently implemented in ScummVM
}
void QMixer::qsWaveMixSetDistanceMapping(int iChannel, uint flags, const QMIX_DISTANCES &distances) {
// Not currently implemented in ScummVM
}
void QMixer::qsWaveMixSetFrequency(int iChannel, uint flags, uint frequency) {
// Not currently implemented in ScummVM
}
void QMixer::qsWaveMixSetSourceVelocity(int iChannel, uint flags, const QSVECTOR &velocity) {
// Not currently implemented in ScummVM
}
int QMixer::qsWaveMixPlayEx(int iChannel, uint flags, CWaveFile *waveFile, int loops, const QMIXPLAYPARAMS &params) {
if (iChannel == -1) {
// Find a free channel
for (iChannel = 0; iChannel < (int)_channels.size(); ++iChannel) {
if (_channels[iChannel]._sounds.empty())
break;
}
assert(iChannel != (int)_channels.size());
}
// If the new sound replaces current ones, then clear the channel
ChannelEntry &channel = _channels[iChannel];
if (flags & QMIX_CLEARQUEUE) {
if (!channel._sounds.empty() && channel._sounds.front()._started)
_mixer->stopHandle(channel._sounds.front()._soundHandle);
channel._sounds.clear();
}
// Add the sound to the channel
channel._sounds.push_back(SoundEntry(waveFile, params.callback, loops, params.dwUser));
qsWaveMixPump();
return 0;
}
bool QMixer::qsWaveMixIsChannelDone(int iChannel) const {
return _channels[iChannel]._sounds.empty();
}
void QMixer::qsWaveMixPump() {
// Iterate through each of the channels
for (uint iChannel = 0; iChannel < _channels.size(); ++iChannel) {
ChannelEntry &channel = _channels[iChannel];
// If there's a transition in sound volume in progress, handle it
if (channel._volumeChangeEnd) {
byte oldVolume = channel._volume;
uint currentTicks = g_system->getMillis();
if (currentTicks >= channel._volumeChangeEnd) {
// Reached end of transition period
channel._volume = channel._volumeEnd;
channel._volumeChangeStart = channel._volumeChangeEnd = 0;
} else {
// Transition in progress, so figure out new volume
channel._volume = (int)channel._volumeStart +
((int)channel._volumeEnd - (int)channel._volumeStart) *
(int)(currentTicks - channel._volumeChangeStart) / (int)channel._panRate;
}
debugC(DEBUG_DETAILED, kDebugCore, "qsWaveMixPump time=%u vol=%d",
currentTicks, channel._volume);
if (channel._volume != oldVolume && !channel._sounds.empty()
&& channel._sounds.front()._started) {
_mixer->setChannelVolume(channel._sounds.front()._soundHandle,
channel.getRawVolume());
}
}
// If the playing sound on the channel is finished, then call
// the callback registered for it, and remove it from the list
if (!channel._sounds.empty()) {
SoundEntry &sound = channel._sounds.front();
if (sound._started && !_mixer->isSoundHandleActive(sound._soundHandle)) {
// Sound is finished
if (sound._callback)
// Call the callback to signal end
sound._callback(iChannel, sound._waveFile, sound._userData);
// Remove sound record from channel
channel._sounds.erase(channel._sounds.begin());
}
}
// If there's an unstarted sound at the front of a channel's
// sound list, then start it playing
if (!channel._sounds.empty()) {
SoundEntry &sound = channel._sounds.front();
if (!sound._started) {
if (channel._resetDistance)
channel._distance = 0.0;
// Play the wave
sound._soundHandle = sound._waveFile->play(
sound._loops, channel.getRawVolume());
sound._started = true;
}
}
}
}
/*------------------------------------------------------------------------*/
byte QMixer::ChannelEntry::getRawVolume() const {
// Emperically decided adjustment divisor for distances
const double ADJUSTMENT_FACTOR = 5.0;
double r = 1.0 + (_distance / ADJUSTMENT_FACTOR);
double percent = 1.0 / (r * r);
double newVolume = _volume * percent;
return (byte)newVolume;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,335 @@
/* 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
* aint with this program; if not, write to the Free Software
*
*/
#ifndef TITANIC_QMIXER_H
#define TITANIC_QMIXER_H
#include "audio/mixer.h"
#include "titanic/sound/wave_file.h"
namespace Titanic {
enum QMixFlag {
QMIX_OPENSINGLE = 0, // Open the single channel specified by iChannel
QMIX_OPENALL = 1, // Opens all the channels, iChannel ignored
QMIX_OPENCOUNT = 2, // Open iChannel Channels (eg. if iChannel = 4 will create channels 0-3)
QMIX_OPENAVAILABLE = 3, // Open the first unopened channel, and return channel number
// Channel function flags
QMIX_ALL = 0x01, // apply to all channels
QMIX_NOREMIX = 0x02, // don't remix
QMIX_CONTROL_NOREMIX = 0x04, // don't remix
QMIX_USEONCE = 0x10 // settings are temporary
};
// qsWaveMixEnableChannel flags: if mode==0, use conventional, high-performance
// stereo mixer. Non-zero modes imply some form of additional processing.
enum QMixChannelFlag {
QMIX_CHANNEL_STEREO = 0x0000, // Perform stereo mixing
QMIX_CHANNEL_QSOUND = 0x0001, // Perform QSound localization (default)
QMIX_CHANNEL_DOPPLER = 0x0002, // Calculate velocity using position updates
QMIX_CHANNEL_RANGE = 0x0004, // Do range effects
QMIX_CHANNEL_ELEVATION = 0x0008, // Do elevation effects
QMIX_CHANNEL_NODOPPLERPITCH = 0x0010, // Disable Doppler pitch shift for this channel
QMIX_CHANNEL_PITCH_COPY = 0x0000, // Pitch shifting using copying (fastest)
QMIX_CHANNEL_PITCH_LINEAR = 0x0100, // Pitch shifting using linear interpolation (better but slower)
QMIX_CHANNEL_PITCH_SPLINE = 0x0200, // Pitch shifting using spline interpolation (better yet, but much slower)
QMIX_CHANNEL_PITCH_FILTER = 0x0300, // Pitch shifting using FIR filter (best, but slowest)
QMIX_CHANNEL_PITCH_MASK = 0x0700 // Bits reserved for pitch types
};
/**
* Options for dwFlags parameter in QSWaveMixPlayEx.
*
* Notes: The QMIX_USELRUCHANNEL flag has two roles. When QMIX_CLEARQUEUE is also set,
* the channel that has been playing the longest (least-recently-used) is cleared and
* the buffer played. When QMIX_QUEUEWAVE is set, the channel that will first finish
* playing will be selected and the buffer queued to play. Of course, if an unused
* channel is found, it will be selected instead.
* If QMIX_WAIT hasn't been specified, then the channel number will be returned
* in the iChannel field.
*/
enum QMixPlayFlag {
QMIX_QUEUEWAVE = 0x0000, // Queue on channel
QMIX_CLEARQUEUE = 0x0001, // Clear queue on channel
QMIX_USELRUCHANNEL = 0x0002, // See notes above
QMIX_HIGHPRIORITY = 0x0004,
QMIX_WAIT = 0x0008, // Queue to be played with other sounds
QMIX_IMMEDIATE = 0x0020, // Apply volume/pan changes without interpolation
QMIX_PLAY_SETEVENT = 0x0100, // Calls SetEvent in the original library when done
QMIX_PLAY_PULSEEVENT = 0x0200, // Calls PulseEvent in the original library when done
QMIX_PLAY_NOTIFYSTOP = 0x0400 // Do callback even when stopping or flushing sound
};
/**
* Mixer configuration structure for qsWaveMixInitEx
*/
struct QMIXCONFIG {
uint32 dwSize;
uint32 dwFlags;
uint32 dwSamplingRate; // Sampling rate in Hz
void *lpIDirectSound;
const void *lpGuid;
int iChannels; // Number of channels
int iOutput; // if 0, uses best output device
int iLatency; // (in ms) if 0, uses default for output device
int iMath; // style of math
uint hwnd;
QMIXCONFIG() : dwSize(40), dwFlags(0), dwSamplingRate(0), lpIDirectSound(nullptr),
lpGuid(nullptr), iChannels(0), iOutput(0), iLatency(0), iMath(0), hwnd(0) {}
QMIXCONFIG(uint32 rate, int channels, int latency) : dwSize(40), dwFlags(0),
dwSamplingRate(rate), iChannels(channels), iLatency(latency),
lpIDirectSound(nullptr), lpGuid(nullptr), iOutput(0), iMath(0), hwnd(0) {}
};
/**
* Vector positioning in metres
*/
struct QSVECTOR {
double x;
double y;
double z;
QSVECTOR() : x(0.0), y(0.0), z(0.0) {}
QSVECTOR(double xp, double yp, double zp) : x(xp), y(yp), z(zp) {}
};
/**
* Polar positioning
*/
struct QSPOLAR {
double azimuth; // degrees
double range; // meters
double elevation; // degrees
QSPOLAR() : azimuth(0.0), range(0.0), elevation(0.0) {}
QSPOLAR(double azimuth_, double range_, double elevation_) :
azimuth(azimuth_), range(range_), elevation(elevation_) {}
};
struct QMIX_DISTANCES {
int cbSize; // Structure size
double minDistance; // sounds are at full volume if closer than this
double maxDistance; // sounds are muted if further away than this
double scale; // relative amount to adjust rolloff by
QMIX_DISTANCES() : cbSize(16), minDistance(0.0), maxDistance(0.0), scale(0.0) {}
QMIX_DISTANCES(double minDistance_, double maxDistance_, double scale_) :
cbSize(16), minDistance(minDistance_), maxDistance(maxDistance_), scale(scale_) {}
};
typedef void (*LPQMIXDONECALLBACK)(int iChannel, CWaveFile *lpWave, void *dwUser);
struct QMIXPLAYPARAMS {
uint dwSize; // Size of the play structure
void *lpImage; // Additional preprocessed audio for high performance
uint hwndNotify; // if set, WOM_OPEN and WOM_DONE messages sent to that window
LPQMIXDONECALLBACK callback; // Callback function
void *dwUser; // User data accompanying callback
int lStart;
int lStartLoop;
int lEndLoop;
int lEnd;
const void *lpChannelParams; // initialize with these parameters
// Properties introduced by ScummVM
Audio::Mixer::SoundType _soundType;
QMIXPLAYPARAMS() : dwSize(36), lpImage(nullptr), hwndNotify(0), callback(nullptr),
dwUser(nullptr), lStart(0), lStartLoop(0), lEndLoop(0), lEnd(0),
lpChannelParams(nullptr), _soundType(Audio::Mixer::kPlainSoundType) {}
};
/**
* This class represents an interface to the QMixer library developed by
* QSound Labs, Inc. Which itself is apparently based on Microsoft's
* WaveMix API.
*
* It does not currently have any actual code from the library,
* and instead remaps calls to ScummVM's existing mixer where possible.
* This means that advanced features of the QMixer library, like being
* able to set up both the player and sounds at different positions are
* currently ignored, and all sounds play at full volume.
*/
class QMixer {
struct SoundEntry {
bool _started;
CWaveFile *_waveFile;
Audio::SoundHandle _soundHandle;
LPQMIXDONECALLBACK _callback;
int _loops;
void *_userData;
SoundEntry() : _started(false), _waveFile(nullptr), _callback(nullptr),
_loops(0), _userData(nullptr) {}
SoundEntry(CWaveFile *waveFile, LPQMIXDONECALLBACK callback, int loops, void *userData) :
_started(false), _waveFile(waveFile), _callback(callback), _loops(loops), _userData(userData) {}
};
struct ChannelEntry {
// Currently playing and any following queued sounds for the channel
Common::List<SoundEntry> _sounds;
// Current channel volume
byte _volume;
// Current time in milliseconds for paning (volume) changes
uint _panRate;
// Fields used to transition between volume levels
uint _volumeChangeStart;
uint _volumeChangeEnd;
byte _volumeStart;
byte _volumeEnd;
// Distance of source
double _distance;
bool _resetDistance;
ChannelEntry() : _volume(0), _panRate(0), _volumeChangeStart(0),
_volumeChangeEnd(0), _volumeStart(0), _volumeEnd(0),
_distance(0.0), _resetDistance(true) {}
/**
* Calculates the raw volume level to pass to ScummVM playStream, taking
* into the sound's volume level and distance from origin
*/
byte getRawVolume() const;
};
private:
Common::Array<ChannelEntry> _channels;
protected:
Audio::Mixer *_mixer;
public:
QMixer(Audio::Mixer *mixer);
virtual ~QMixer();
/**
* Initializes the mixer
*/
bool qsWaveMixInitEx(const QMIXCONFIG &config);
/**
* Activates the mixer
*/
void qsWaveMixActivate(bool fActivate);
/**
* Opens channels in the mixer for access
*/
int qsWaveMixOpenChannel(int iChannel, QMixFlag mode);
/**
* Enables a given channel
*/
int qsWaveMixEnableChannel(int iChannel, uint flags, bool enabled);
/**
* Closes down the mixer
*/
void qsWaveMixCloseSession();
/**
* Stops a sound from playing
*/
void qsWaveMixFreeWave(Audio::SoundHandle &handle);
/**
* Flushes a channel
*/
void qsWaveMixFlushChannel(int iChannel, uint flags = 0);
/**
* Sets the amount of time, in milliseconds, to effect a change in
* a channel property (e.g. volume, position). Non-zero values
* smooth out changes
* @param iChannel Channel to change
* @param flags Flags
* @param rate Pan rate in milliseconds
*/
void qsWaveMixSetPanRate(int iChannel, uint flags, uint rate);
/**
* Sets the volume for a channel
*/
void qsWaveMixSetVolume(int iChannel, uint flags, uint volume);
/**
* Sets the relative position of a channel
* @param iChannel Channel number
* @param Flags Flags
* @param position Vector position for channel
*/
void qsWaveMixSetSourcePosition(int iChannel, uint flags, const QSVECTOR &position);
/**
* Sets the relative position of a channel using polar co-ordinates
* @param iChannel Channel number
* @param Flags Flags
* @param position Polar position for channel
*/
void qsWaveMixSetPolarPosition(int iChannel, uint flags, const QSPOLAR &position);
/**
* Sets the listener position
*/
void qsWaveMixSetListenerPosition(const QSVECTOR &position, uint flags = 0);
/**
* Sets the listener orientation
*/
void qsWaveMixSetListenerOrientation(const QSVECTOR &direction, const QSVECTOR &up, uint flags = 0);
/**
* Sets the mapping ditance range
*/
void qsWaveMixSetDistanceMapping(int iChannel, uint flags, const QMIX_DISTANCES &distances);
/**
* Sets the frequency/rate of sound playback
*/
void qsWaveMixSetFrequency(int iChannel, uint flags, uint frequency);
/**
* Sets the velocity of the source (listener)
*/
void qsWaveMixSetSourceVelocity(int iChannel, uint flags, const QSVECTOR &velocity);
/**
* Plays sound
* @param iChannel The channel number to be played on
* @param flags Play flags
* @param mixWave Data for the sound to be played
* @param loops Number of loops to play (-1 for forever)
* @param params Playback parameter data
*/
int qsWaveMixPlayEx(int iChannel, uint flags, CWaveFile *waveFile, int loops, const QMIXPLAYPARAMS &params);
/**
* Returns true if there are no more buffers playing or queued on the channel
*/
bool qsWaveMixIsChannelDone(int iChannel) const;
/**
* Handles regularly updating the mixer
*/
void qsWaveMixPump();
};
} // End of namespace Titanic
#endif /* TITANIC_QMIXER_H */

View File

@@ -0,0 +1,78 @@
/* 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/>.
*
*/
#include "titanic/sound/restricted_auto_music_player.h"
#include "titanic/core/room_item.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CRestrictedAutoMusicPlayer, CAutoMusicPlayer)
ON_MESSAGE(EnterRoomMsg)
ON_MESSAGE(LeaveRoomMsg)
END_MESSAGE_MAP()
void CRestrictedAutoMusicPlayer::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeQuotedLine(_oldNodeName, indent);
file->writeQuotedLine(_newNodeName, indent);
file->writeQuotedLine(_newRoomName, indent);
file->writeQuotedLine(_oldRoomName, indent);
CAutoMusicPlayer::save(file, indent);
}
void CRestrictedAutoMusicPlayer::load(SimpleFile *file) {
file->readNumber();
_oldNodeName = file->readString();
_newNodeName = file->readString();
_newRoomName = file->readString();
_oldRoomName = file->readString();
CAutoMusicPlayer::load(file);
}
bool CRestrictedAutoMusicPlayer::EnterRoomMsg(CEnterRoomMsg *msg) {
if (!msg->_oldRoom)
return true;
if (petCheckNode(_oldNodeName))
return false;
CString roomName = msg->_oldRoom->getName();
if (!_oldRoomName.compareToIgnoreCase(roomName)) {
_isEnabled = true;
return false;
} else {
return CAutoMusicPlayer::EnterRoomMsg(msg);
}
}
bool CRestrictedAutoMusicPlayer::LeaveRoomMsg(CLeaveRoomMsg *msg) {
CString roomName = msg->_newRoom->getName();
if (petCheckNode(_newNodeName) || !_newRoomName.compareToIgnoreCase(roomName)) {
_isEnabled = false;
return true;
} else {
return CAutoMusicPlayer::LeaveRoomMsg(msg);
}
}
} // End of namespace Titanic

View File

@@ -0,0 +1,55 @@
/* 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/>.
*
*/
#ifndef TITANIC_RESTRICTED_AUTO_MUSIC_PLAYER_H
#define TITANIC_RESTRICTED_AUTO_MUSIC_PLAYER_H
#include "titanic/sound/auto_music_player.h"
#include "titanic/messages/messages.h"
namespace Titanic {
class CRestrictedAutoMusicPlayer : public CAutoMusicPlayer {
DECLARE_MESSAGE_MAP;
bool EnterRoomMsg(CEnterRoomMsg *msg);
bool LeaveRoomMsg(CLeaveRoomMsg *msg);
private:
CString _oldNodeName;
CString _newNodeName;
CString _newRoomName;
CString _oldRoomName;
public:
CLASSDEF;
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_RESTRICTED_AUTO_MUSIC_PLAYER_H */

View File

@@ -0,0 +1,61 @@
/* 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/>.
*
*/
#include "titanic/sound/room_auto_sound_player.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CRoomAutoSoundPlayer, CAutoSoundPlayer)
ON_MESSAGE(EnterRoomMsg)
ON_MESSAGE(LeaveRoomMsg)
END_MESSAGE_MAP()
void CRoomAutoSoundPlayer::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
CAutoSoundPlayer::save(file, indent);
}
void CRoomAutoSoundPlayer::load(SimpleFile *file) {
file->readNumber();
CAutoSoundPlayer::load(file);
}
bool CRoomAutoSoundPlayer::EnterRoomMsg(CEnterRoomMsg *msg) {
CRoomItem *room = findRoom();
if (room == msg->_newRoom) {
CTurnOn onMsg;
onMsg.execute(this);
}
return true;
}
bool CRoomAutoSoundPlayer::LeaveRoomMsg(CLeaveRoomMsg *msg) {
CRoomItem *room = findRoom();
if (room == msg->_oldRoom) {
CTurnOff offMsg;
offMsg.execute(this);
}
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,50 @@
/* 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/>.
*
*/
#ifndef TITANIC_ROOM_AUTO_SOUND_PLAYER_H
#define TITANIC_ROOM_AUTO_SOUND_PLAYER_H
#include "titanic/sound/auto_sound_player.h"
#include "titanic/messages/messages.h"
namespace Titanic {
class CRoomAutoSoundPlayer : public CAutoSoundPlayer {
DECLARE_MESSAGE_MAP;
bool EnterRoomMsg(CEnterRoomMsg *msg);
bool LeaveRoomMsg(CLeaveRoomMsg *msg);
public:
CLASSDEF;
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_ROOM_AUTO_SOUND_PLAYER_H */

View File

@@ -0,0 +1,61 @@
/* 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/>.
*
*/
#include "titanic/sound/room_trigger_auto_music_player.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CRoomTriggerAutoMusicPlayer, CTriggerAutoMusicPlayer)
ON_MESSAGE(LeaveRoomMsg)
ON_MESSAGE(EnterRoomMsg)
END_MESSAGE_MAP()
void CRoomTriggerAutoMusicPlayer::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
CTriggerAutoMusicPlayer::save(file, indent);
}
void CRoomTriggerAutoMusicPlayer::load(SimpleFile *file) {
file->readNumber();
CTriggerAutoMusicPlayer::load(file);
}
bool CRoomTriggerAutoMusicPlayer::LeaveRoomMsg(CLeaveRoomMsg *msg) {
if (msg->_oldRoom == findRoom()) {
CTriggerAutoMusicPlayerMsg triggerMsg;
triggerMsg._value = 1;
triggerMsg.execute(this);
}
return true;
}
bool CRoomTriggerAutoMusicPlayer::EnterRoomMsg(CEnterRoomMsg *msg) {
if (msg->_newRoom == findRoom()) {
CTriggerAutoMusicPlayerMsg triggerMsg;
triggerMsg._value = 2;
triggerMsg.execute(this);
}
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,50 @@
/* 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/>.
*
*/
#ifndef TITANIC_ROOM_TRIGGER_AUTO_MUSIC_PLAYER_H
#define TITANIC_ROOM_TRIGGER_AUTO_MUSIC_PLAYER_H
#include "titanic/sound/trigger_auto_music_player.h"
#include "titanic/messages/messages.h"
namespace Titanic {
class CRoomTriggerAutoMusicPlayer : public CTriggerAutoMusicPlayer {
DECLARE_MESSAGE_MAP;
bool LeaveRoomMsg(CLeaveRoomMsg *msg);
bool EnterRoomMsg(CEnterRoomMsg *msg);
public:
CLASSDEF;
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_ROOM_TRIGGER_AUTO_MUSIC_PLAYER_H */

View File

@@ -0,0 +1,115 @@
/* 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/>.
*
*/
#include "titanic/sound/season_noises.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CSeasonNoises, CViewAutoSoundPlayer)
ON_MESSAGE(ChangeSeasonMsg)
ON_MESSAGE(EnterViewMsg)
ON_MESSAGE(ActMsg)
ON_MESSAGE(LoadSuccessMsg)
END_MESSAGE_MAP()
CSeasonNoises::CSeasonNoises() : CViewAutoSoundPlayer(), _seasonNumber(SEASON_SUMMER),
_springName("NULL"), _summerName("NULL"), _autumnName("NULL"), _winterName("NULL") {
}
void CSeasonNoises::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeNumberLine(_seasonNumber, indent);
file->writeQuotedLine(_springName, indent);
file->writeQuotedLine(_summerName, indent);
file->writeQuotedLine(_autumnName, indent);
file->writeQuotedLine(_winterName, indent);
CViewAutoSoundPlayer::save(file, indent);
}
void CSeasonNoises::load(SimpleFile *file) {
file->readNumber();
_seasonNumber = (Season)file->readNumber();
_springName = file->readString();
_summerName = file->readString();
_autumnName = file->readString();
_winterName = file->readString();
CViewAutoSoundPlayer::load(file);
}
bool CSeasonNoises::ChangeSeasonMsg(CChangeSeasonMsg *msg) {
_seasonNumber = (Season)(((int)_seasonNumber + 1) % 4);
CActMsg actMsg("Update");
actMsg.execute(this);
return true;
}
bool CSeasonNoises::EnterViewMsg(CEnterViewMsg *msg) {
CActMsg actMsg("Update");
actMsg.execute(this);
return true;
}
bool CSeasonNoises::ActMsg(CActMsg *msg) {
msg->_action = "Update";
switch (_seasonNumber) {
case SEASON_SUMMER:
_filename = _summerName;
break;
case SEASON_AUTUMN:
_filename = _autumnName;
break;
case SEASON_WINTER:
_filename = _winterName;
break;
case SEASON_SPRING:
_filename = _springName;
break;
default:
break;
}
CSignalObject signalMsg;
signalMsg._numValue = 2;
signalMsg.execute(this);
CTurnOn onMsg;
onMsg.execute(this);
return true;
}
bool CSeasonNoises::LoadSuccessMsg(CLoadSuccessMsg *msg) {
if (_active) {
_active = false;
_soundHandle = -1;
CActMsg actMsg("Update");
actMsg.execute(this);
}
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,58 @@
/* 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/>.
*
*/
#ifndef TITANIC_SEASON_NOISES_H
#define TITANIC_SEASON_NOISES_H
#include "titanic/sound/view_auto_sound_player.h"
namespace Titanic {
class CSeasonNoises : public CViewAutoSoundPlayer {
DECLARE_MESSAGE_MAP;
bool ChangeSeasonMsg(CChangeSeasonMsg *msg);
bool EnterViewMsg(CEnterViewMsg *msg);
bool ActMsg(CActMsg *msg);
bool LoadSuccessMsg(CLoadSuccessMsg *msg);
private:
Season _seasonNumber;
CString _springName;
CString _summerName;
CString _autumnName;
CString _winterName;
public:
CLASSDEF;
CSeasonNoises();
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_SEASON_NOISES_H */

View File

@@ -0,0 +1,135 @@
/* 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/>.
*
*/
#include "titanic/sound/seasonal_music_player.h"
#include "titanic/translation.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CSeasonalMusicPlayer, CAutoMusicPlayerBase)
ON_MESSAGE(ChangeSeasonMsg)
ON_MESSAGE(ArboretumGateMsg)
ON_MESSAGE(ChangeMusicMsg)
END_MESSAGE_MAP()
CSeasonalMusicPlayer::CSeasonalMusicPlayer() : CAutoMusicPlayerBase() {
_isSpring = false;
_isSummer = true;
_isAutumn = false;
_isWinter = false;
_springMode = VOL_MUTE;
_summerMode = VOL_QUIET;
_autumnMode = VOL_MUTE;
_winterMode = VOL_MUTE;
}
void CSeasonalMusicPlayer::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeNumberLine(_isSpring, indent);
file->writeNumberLine(_isSummer, indent);
file->writeNumberLine(_isAutumn, indent);
file->writeNumberLine(_isWinter, indent);
file->writeNumberLine(_springMode, indent);
file->writeNumberLine(_summerMode, indent);
file->writeNumberLine(_autumnMode, indent);
file->writeNumberLine(_winterMode, indent);
CAutoMusicPlayerBase::save(file, indent);
}
void CSeasonalMusicPlayer::load(SimpleFile *file) {
file->readNumber();
_isSpring = file->readNumber();
_isSummer = file->readNumber();
_isAutumn = file->readNumber();
_isWinter = file->readNumber();
_springMode = (VolumeMode)file->readNumber();
_summerMode = (VolumeMode)file->readNumber();
_autumnMode = (VolumeMode)file->readNumber();
_winterMode = (VolumeMode)file->readNumber();
CAutoMusicPlayerBase::load(file);
}
bool CSeasonalMusicPlayer::ChangeSeasonMsg(CChangeSeasonMsg *msg) {
_isSpring = msg->_season == "spring";
_isSummer = msg->_season == "summer";
_isAutumn = msg->_season == "autumn";
_isWinter = msg->_season == "winter";
_springMode = _isSpring ? VOL_QUIET : VOL_MUTE;
_summerMode = _isSummer ? VOL_QUIET : VOL_MUTE;
_autumnMode = _isAutumn ? VOL_QUIET : VOL_MUTE;
_winterMode = _isWinter ? VOL_QUIET : VOL_MUTE;
CChangeMusicMsg changeMsg;
changeMsg._filename = msg->_season;
changeMsg.execute(this);
return true;
}
bool CSeasonalMusicPlayer::ArboretumGateMsg(CArboretumGateMsg *msg) {
CChangeMusicMsg changeMsg;
changeMsg._action = msg->_value ? MUSIC_START : MUSIC_STOP;
changeMsg.execute(this);
return true;
}
bool CSeasonalMusicPlayer::ChangeMusicMsg(CChangeMusicMsg *msg) {
if (_isEnabled && msg->_action == MUSIC_STOP) {
_isEnabled = false;
stopAmbientSound(_transition, -1);
}
if (!msg->_filename.empty()) {
if (_isSummer) {
setAmbientSoundVolume(VOL_MUTE, 2, 0);
setAmbientSoundVolume(VOL_QUIET, 2, 1);
} else if (_isAutumn) {
setAmbientSoundVolume(VOL_MUTE, 2, 1);
setAmbientSoundVolume(VOL_QUIET, 2, 2);
} else if (_isWinter) {
setAmbientSoundVolume(VOL_MUTE, 2, 2);
setAmbientSoundVolume(VOL_QUIET, 2, 3);
} else if (_isSpring) {
setAmbientSoundVolume(VOL_MUTE, 2, 3);
setAmbientSoundVolume(VOL_QUIET, 2, 0);
}
}
if (!_isEnabled && msg->_action == MUSIC_START) {
_isEnabled = true;
loadSound(TRANSLATE("c#64.wav", "c#47.wav"));
loadSound(TRANSLATE("c#63.wav", "c#46.wav"));
loadSound(TRANSLATE("c#65.wav", "c#48.wav"));
loadSound(TRANSLATE("c#62.wav", "c#47.wav"));
playAmbientSound(TRANSLATE("c#64.wav", "c#47.wav"), _springMode, _isSpring, true, 0);
playAmbientSound(TRANSLATE("c#63.wav", "c#46.wav"), _summerMode, _isSummer, true, 1);
playAmbientSound(TRANSLATE("c#65.wav", "c#48.wav"), _autumnMode, _isAutumn, true, 2);
playAmbientSound(TRANSLATE("c#62.wav", "c#47.wav"), _winterMode, _isWinter, true, 3);
}
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,60 @@
/* 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/>.
*
*/
#ifndef TITANIC_SEASONAL_MUSIC_PLAYER_H
#define TITANIC_SEASONAL_MUSIC_PLAYER_H
#include "titanic/sound/auto_music_player_base.h"
namespace Titanic {
class CSeasonalMusicPlayer : public CAutoMusicPlayerBase {
DECLARE_MESSAGE_MAP;
bool ChangeSeasonMsg(CChangeSeasonMsg *msg);
bool ArboretumGateMsg(CArboretumGateMsg *msg);
bool ChangeMusicMsg(CChangeMusicMsg *msg);
private:
bool _isSpring;
bool _isSummer;
bool _isAutumn;
bool _isWinter;
VolumeMode _springMode;
VolumeMode _summerMode;
VolumeMode _autumnMode;
VolumeMode _winterMode;
public:
CLASSDEF;
CSeasonalMusicPlayer();
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_SEASONAL_MUSIC_PLAYER_H */

View File

@@ -0,0 +1,243 @@
/* 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/>.
*
*/
#include "titanic/sound/sound.h"
#include "titanic/game_manager.h"
#include "titanic/titanic.h"
namespace Titanic {
CSoundItem::~CSoundItem() {
delete _waveFile;
}
/*------------------------------------------------------------------------*/
CSound::CSound(CGameManager *owner, Audio::Mixer *mixer) :
_gameManager(owner), _soundManager(mixer) {
g_vm->_movieManager.setSoundManager(&_soundManager);
}
CSound::~CSound() {
_soundManager.qsWaveMixCloseSession();
_sounds.destroyContents();
}
void CSound::save(SimpleFile *file) const {
_soundManager.save(file);
}
void CSound::load(SimpleFile *file) {
_soundManager.load(file);
}
void CSound::preLoad() {
_soundManager.preLoad();
if (_gameManager)
_gameManager->_musicRoom.destroyMusicHandler();
}
void CSound::preEnterView(CViewItem *newView, bool isNewRoom) {
CNodeItem *node = newView->findNode();
double xp, yp, zp;
node->getPosition(xp, yp, zp);
double cosVal = cos(newView->_angle);
double sinVal = -sin(newView->_angle);
_soundManager.setListenerPosition(xp, yp, zp, cosVal, sinVal, 0, isNewRoom);
}
bool CSound::isActive(int handle) {
if (handle != 0 && handle != -1)
return _soundManager.isActive(handle);
return false;
}
void CSound::setVolume(uint handle, uint volume, uint seconds) {
_soundManager.setVolume(handle, volume, seconds);
}
void CSound::activateSound(CWaveFile *waveFile, DisposeAfterUse::Flag disposeAfterUse) {
for (CSoundItemList::iterator i = _sounds.begin(); i != _sounds.end(); ++i) {
CSoundItem *sound = *i;
if (sound->_waveFile == waveFile) {
sound->_active = true;
sound->_disposeAfterUse = disposeAfterUse;
// Anything bigger than 50Kb is automatically flagged to be free when finished
if (waveFile->size() > (50 * 1024))
sound->_disposeAfterUse = DisposeAfterUse::YES;
break;
}
}
}
void CSound::stopChannel(int channel) {
_soundManager.stopChannel(channel);
}
void CSound::checkSounds() {
for (CSoundItemList::iterator i = _sounds.begin(); i != _sounds.end(); ) {
CSoundItem *soundItem = *i;
if (soundItem->_active && soundItem->_disposeAfterUse == DisposeAfterUse::YES) {
if (!_soundManager.isActive(soundItem->_waveFile)) {
i = _sounds.erase(i);
delete soundItem;
continue;
}
}
++i;
}
}
void CSound::removeOldest() {
for (CSoundItemList::iterator i = _sounds.reverse_begin();
i != _sounds.end(); --i) {
CSoundItem *soundItem = *i;
if (soundItem->_active && !_soundManager.isActive(soundItem->_waveFile)) {
_sounds.remove(soundItem);
delete soundItem;
break;
}
}
}
CWaveFile *CSound::getTrueTalkSound(CDialogueFile *dialogueFile, int index) {
return loadSpeech(dialogueFile, index);
}
CWaveFile *CSound::loadSound(const CString &name) {
checkSounds();
// Check whether an entry for the given name is already active
for (CSoundItemList::iterator i = _sounds.begin(); i != _sounds.end(); ++i) {
CSoundItem *soundItem = *i;
if (soundItem->_name == name) {
// Found it, so move it to the front of the list and return
_sounds.remove(soundItem);
_sounds.push_front(soundItem);
return soundItem->_waveFile;
}
}
// Create new sound item
CSoundItem *soundItem = new CSoundItem(name);
soundItem->_waveFile = _soundManager.loadSound(name);
if (!soundItem->_waveFile) {
// Couldn't load sound, so destroy new item and return
delete soundItem;
return 0;
}
// Add the item to the list of sounds
_sounds.push_front(soundItem);
// If there are more than 10 sounds loaded, remove the last one,
// which is the least recently used of all of them
if (_sounds.size() > 10)
removeOldest();
return soundItem->_waveFile;
}
int CSound::playSound(const CString &name, CProximity &prox) {
CWaveFile *waveFile = loadSound(name);
if (!waveFile)
return -1;
prox._soundDuration = waveFile->getDurationTicks();
if (prox._soundType != Audio::Mixer::kPlainSoundType)
waveFile->_soundType = prox._soundType;
activateSound(waveFile, prox._disposeAfterUse);
return _soundManager.playSound(*waveFile, prox);
}
CWaveFile *CSound::loadSpeech(CDialogueFile *dialogueFile, int speechId) {
checkSounds();
// Check whether an entry for the given name is already active
for (CSoundItemList::iterator i = _sounds.begin(); i != _sounds.end(); ++i) {
CSoundItem *soundItem = *i;
if (soundItem->_dialogueFileHandle == dialogueFile->getFile()
&& soundItem->_speechId == speechId) {
// Found it, so move it to the front of the list and return
_sounds.remove(soundItem);
_sounds.push_front(soundItem);
return soundItem->_waveFile;
}
}
// Create new sound item
CSoundItem *soundItem = new CSoundItem(dialogueFile->getFile(), speechId);
soundItem->_waveFile = _soundManager.loadSpeech(dialogueFile, speechId);
if (!soundItem->_waveFile) {
// Couldn't load speech, so destroy new item and return
delete soundItem;
return 0;
}
// Add the item to the list of sounds
_sounds.push_front(soundItem);
// If there are more than 10 sounds loaded, remove the last one,
// which is the least recently used of all of them
if (_sounds.size() > 10)
removeOldest();
return soundItem->_waveFile;
}
int CSound::playSpeech(CDialogueFile *dialogueFile, int speechId, CProximity &prox) {
CWaveFile *waveFile = loadSpeech(dialogueFile, speechId);
if (!waveFile)
return -1;
prox._soundDuration = waveFile->getDurationTicks();
if (prox._soundType != Audio::Mixer::kPlainSoundType)
waveFile->_soundType = prox._soundType;
activateSound(waveFile, prox._disposeAfterUse);
return _soundManager.playSound(*waveFile, prox);
}
void CSound::stopSound(uint handle) {
_soundManager.stopSound(handle);
}
void CSound::setCanFree(int handle) {
if (handle != 0 && handle != -1)
_soundManager.setCanFree(handle);
}
void CSound::updateMixer() {
_soundManager.waveMixPump();
}
} // End of namespace Titanic

View File

@@ -0,0 +1,194 @@
/* 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/>.
*
*/
#ifndef TITANIC_SOUND_H
#define TITANIC_SOUND_H
#include "titanic/support/simple_file.h"
#include "titanic/sound/proximity.h"
#include "titanic/sound/sound_manager.h"
#include "titanic/sound/wave_file.h"
#include "titanic/core/list.h"
#include "titanic/core/view_item.h"
#include "titanic/true_talk/dialogue_file.h"
namespace Titanic {
class CGameManager;
class CSoundItem : public ListItem {
public:
CString _name;
CWaveFile *_waveFile;
File *_dialogueFileHandle;
int _speechId;
DisposeAfterUse::Flag _disposeAfterUse;
bool _active;
public:
CSoundItem() : ListItem(), _waveFile(nullptr), _dialogueFileHandle(nullptr),
_speechId(0), _disposeAfterUse(DisposeAfterUse::NO), _active(false) {}
CSoundItem(const CString &name) : ListItem(), _name(name), _waveFile(nullptr),
_dialogueFileHandle(nullptr), _disposeAfterUse(DisposeAfterUse::NO),
_speechId(0), _active(false) {}
CSoundItem(File *dialogueFile, int speechId) : ListItem(), _waveFile(nullptr),
_dialogueFileHandle(dialogueFile), _speechId(speechId), _active(false),
_disposeAfterUse(DisposeAfterUse::NO) {}
~CSoundItem() override;
};
class CSoundItemList : public List<CSoundItem> {
};
class CSound {
private:
CGameManager *_gameManager;
CSoundItemList _sounds;
private:
/**
* Check whether any sounds are done and can be be removed
*/
void checkSounds();
/**
* Removes the oldest sound from the sounds list that isn't
* currently playing
*/
void removeOldest();
public:
QSoundManager _soundManager;
public:
CSound(CGameManager *owner, Audio::Mixer *mixer);
~CSound();
/**
* Save the data for the class to file
*/
void save(SimpleFile *file) const;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file);
/**
* Called when a game is about to be loaded
*/
void preLoad();
/**
* Called when loading a game is complete
*/
void postLoad() { _soundManager.postLoad(); }
/**
* Called when a game is about to be saved
*/
void preSave() { _soundManager.preSave(); }
/**
* Called when a game has finished being saved
*/
void postSave() { _soundManager.postSave(); }
/**
* Called when the view has been changed
*/
void preEnterView(CViewItem *newView, bool isNewRoom);
/**
* Returns true if a sound with the specified handle is active
*/
bool isActive(int handle);
/**
* Sets the volume for a sound
* @param handle Sound handle
* @param volume Volume percentage (0 to 100)
* @param seconds Number of seconds to transition to the new volume
*/
void setVolume(uint handle, uint volume, uint seconds);
/**
* Flags a sound about to be played as activated
*/
void activateSound(CWaveFile *waveFile,
DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::NO);
/**
* Stops any sounds attached to a given channel
*/
void stopChannel(int channel);
/**
* Loads a TrueTalk dialogue
* @param dialogueFile Dialogue file reference
* @param speechId Speech Id within dialogue
* @returns Wave file instance
*/
CWaveFile *getTrueTalkSound(CDialogueFile *dialogueFile, int index);
/**
* Load a speech resource
* @param dialogueFile Dialogue file reference
* @param speechId Speech Id within dialogue
* @returns Wave file instance
*/
CWaveFile *loadSpeech(CDialogueFile *dialogueFile, int speechId);
/**
* Play a speech
* @param dialogueFile Dialogue file reference
* @param speechId Speech Id within dialogue
* @param prox Proximity instance
*/
int playSpeech(CDialogueFile *dialogueFile, int speechId, CProximity &prox);
/**
* Load a sound
* @param name Name of sound resource
* @returns Sound item record
*/
CWaveFile *loadSound(const CString &name);
/**
* Play a sound
*/
int playSound(const CString &name, CProximity &prox);
/**
* Stop a sound
*/
void stopSound(uint handle);
/**
* Flags that a sound can be freed if a timeout is set
*/
void setCanFree(int handle);
/**
* Handles regularly updating the mixer
*/
void updateMixer();
};
} // End of namespace Titanic
#endif /* TITANIC_SOUND_H */

View File

@@ -0,0 +1,498 @@
/* 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/>.
*
*/
#include "titanic/sound/sound_manager.h"
#include "titanic/events.h"
#include "titanic/titanic.h"
namespace Titanic {
const uint LATENCY = 100;
const uint CHANNELS_COUNT = 16;
CSoundManager::CSoundManager() : _musicPercent(75.0), _speechPercent(75.0),
_masterPercent(75.0), _parrotPercent(75.0), _handleCtr(1) {
}
uint CSoundManager::getModeVolume(VolumeMode mode) {
switch (mode) {
case VOL_NORMAL:
return (uint)_masterPercent;
case VOL_QUIET:
return (uint)(_masterPercent * 30 / 100);
case VOL_VERY_QUIET:
return (uint)(_masterPercent * 15 / 100);
default:
return 0;
}
}
/*------------------------------------------------------------------------*/
void QSoundManagerSounds::add(CWaveFile *waveFile, int iChannel, CEndTalkerFn endFn, TTtalker *talker) {
push_back(new QSoundManagerSound(waveFile, iChannel, endFn, talker));
}
void QSoundManagerSounds::flushChannel(int iChannel) {
for (iterator i = begin(); i != end(); ++i) {
QSoundManagerSound *item = *i;
if (item->_iChannel == iChannel) {
if (item->_endFn)
item->_endFn(item->_talker);
remove(item);
delete item;
break;
}
}
}
void QSoundManagerSounds::flushChannel(CWaveFile *waveFile, int iChannel) {
for (iterator i = begin(); i != end(); ++i) {
QSoundManagerSound *item = *i;
if (item->_waveFile->isLoaded() && item->_iChannel == iChannel) {
if (item->_endFn)
item->_endFn(item->_talker);
remove(item);
delete item;
break;
}
}
}
bool QSoundManagerSounds::contains(const CWaveFile *waveFile) const {
for (const_iterator i = begin(); i != end(); ++i) {
const QSoundManagerSound *item = *i;
if (item->_waveFile == waveFile)
return true;
}
return false;
}
/*------------------------------------------------------------------------*/
void QSoundManager::Slot::clear() {
_waveFile = nullptr;
_isTimed = false;
_ticks = 0;
_channel = -1;
_handle = 0;
_positioningMode = POSMODE_NONE;
}
/*------------------------------------------------------------------------*/
QSoundManager::QSoundManager(Audio::Mixer *mixer) : CSoundManager(), QMixer(mixer),
_field18(0), _field1C(0) {
_slots.resize(48);
Common::fill(&_channelsVolume[0], &_channelsVolume[16], 0);
Common::fill(&_channelsMode[0], &_channelsMode[16], 0);
qsWaveMixInitEx(QMIXCONFIG(AUDIO_SAMPLING_RATE, CHANNELS_COUNT, LATENCY));
qsWaveMixActivate(true);
qsWaveMixOpenChannel(0, QMIX_OPENALL);
}
QSoundManager::~QSoundManager() {
// Close down the mixer
qsWaveMixCloseSession();
}
CWaveFile *QSoundManager::loadSound(const CString &name) {
CWaveFile *waveFile = new CWaveFile(_mixer);
// Try to load the specified sound
if (!waveFile->loadSound(name)) {
delete waveFile;
return nullptr;
}
return waveFile;
}
CWaveFile *QSoundManager::loadSpeech(CDialogueFile *dialogueFile, int speechId) {
CWaveFile *waveFile = new CWaveFile(_mixer);
// Try to load the specified sound
if (!waveFile->loadSpeech(dialogueFile, speechId)) {
delete waveFile;
return nullptr;
}
return waveFile;
}
CWaveFile *QSoundManager::loadMusic(const CString &name) {
CWaveFile *waveFile = new CWaveFile(_mixer);
// Try to load the specified sound
if (!waveFile->loadMusic(name)) {
delete waveFile;
return nullptr;
}
return waveFile;
}
CWaveFile *QSoundManager::loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse) {
CWaveFile *waveFile = new CWaveFile(_mixer);
// Try to load the specified audio buffer
if (!waveFile->loadMusic(buffer, disposeAfterUse)) {
delete waveFile;
return nullptr;
}
return waveFile;
}
int QSoundManager::playSound(CWaveFile &waveFile, CProximity &prox) {
int channel = -1;
uint flags = QMIX_CLEARQUEUE;
if (prox._priorSoundHandle >= 1) {
// This sound should only be started after a prior one finishes,
// so scan the slots for the specified sound
for (uint idx = 0; idx < _slots.size(); ++idx) {
if (_slots[idx]._handle == prox._priorSoundHandle) {
channel = _slots[idx]._channel;
flags = QMIX_QUEUEWAVE;
break;
}
}
}
if (channel >= 0 || (channel = resetChannel(prox._channelMode)) != -1) {
return playWave(&waveFile, channel, flags, prox);
}
return 0;
}
void QSoundManager::stopSound(int handle) {
resetChannel(10);
for (uint idx = 0; idx < _slots.size(); ++idx) {
Slot &slot = _slots[idx];
if (slot._handle == handle) {
qsWaveMixFlushChannel(slot._channel);
_sounds.flushChannel(slot._channel);
resetChannel(10);
}
}
}
void QSoundManager::stopChannel(int channel) {
int endChannel;
switch (channel) {
case 0:
case 3:
endChannel = channel + 3;
break;
case 6:
endChannel = 10;
break;
case 10:
endChannel = 48;
break;
default:
return;
}
for (; channel < endChannel; ++channel) {
qsWaveMixFlushChannel(channel);
_sounds.flushChannel(channel);
}
}
void QSoundManager::setCanFree(int handle) {
for (uint idx = 0; idx < _slots.size(); ++idx) {
if (_slots[idx]._handle == handle)
_slots[idx]._isTimed = true;
}
}
void QSoundManager::stopAllChannels() {
qsWaveMixFlushChannel(0, QMIX_OPENALL);
for (int idx = 0; idx < 16; ++idx)
_sounds.flushChannel(idx);
resetChannel(10);
}
int QSoundManager::resetChannel(int iChannel) {
int newChannel = -1;
int channelStart = 10;
int channelEnd = 16;
if (iChannel != 10) {
qsWaveMixFlushChannel(iChannel);
_sounds.flushChannel(iChannel);
channelStart = iChannel;
channelEnd = iChannel + 1;
} else {
uint ticks = g_vm->_events->getTicksCount();
for (uint idx = 0; idx < _slots.size(); ++idx) {
Slot &slot = _slots[idx];
if (slot._isTimed && slot._ticks && ticks > slot._ticks) {
qsWaveMixFlushChannel(slot._channel);
_sounds.flushChannel(slot._channel);
}
}
}
for (iChannel = channelStart; iChannel < channelEnd; ++iChannel) {
if (qsWaveMixIsChannelDone(iChannel)) {
// Scan through the slots, and reset any slot using the channel
for (uint idx = 0; idx < _slots.size(); ++idx) {
Slot &slot = _slots[idx];
if (slot._channel == iChannel)
slot.clear();
}
// Use the empty channel
newChannel = iChannel;
}
}
return newChannel;
}
void QSoundManager::setVolume(int handle, uint volume, uint seconds) {
for (uint idx = 0; idx < _slots.size(); ++idx) {
Slot &slot = _slots[idx];
if (slot._handle == handle) {
assert(slot._channel >= 0);
_channelsVolume[slot._channel] = volume;
updateVolume(slot._channel, seconds * 1000);
if (!volume) {
uint ticks = g_vm->_events->getTicksCount() + seconds * 1000;
if (!slot._ticks || ticks >= slot._ticks)
slot._ticks = ticks;
} else {
slot._ticks = 0;
}
break;
}
}
}
void QSoundManager::setVectorPosition(int handle, double x, double y, double z, uint panRate) {
for (uint idx = 0; idx < _slots.size(); ++idx) {
Slot &slot = _slots[idx];
if (slot._handle == handle) {
qsWaveMixSetPanRate(slot._channel, QMIX_USEONCE, panRate);
qsWaveMixSetSourcePosition(slot._channel, QMIX_USEONCE, QSVECTOR(x, y, z));
break;
}
}
}
void QSoundManager::setPolarPosition(int handle, double range, double azimuth, double elevation, uint panRate) {
for (uint idx = 0; idx < _slots.size(); ++idx) {
Slot &slot = _slots[idx];
if (slot._handle == handle) {
qsWaveMixSetPanRate(slot._channel, QMIX_USEONCE, panRate);
qsWaveMixSetPolarPosition(slot._channel, QMIX_USEONCE,
QSPOLAR(azimuth, range, elevation));
break;
}
}
}
bool QSoundManager::isActive(int handle) {
resetChannel(10);
for (uint idx = 0; idx < _slots.size(); ++idx) {
if (_slots[idx]._handle == handle)
return true;
}
return false;
}
bool QSoundManager::isActive(const CWaveFile *waveFile) {
return _sounds.contains(waveFile);
}
void QSoundManager::waveMixPump() {
qsWaveMixPump();
}
uint QSoundManager::getLatency() const {
return LATENCY;
}
void QSoundManager::setMusicPercent(double percent) {
_musicPercent = percent;
updateVolumes();
}
void QSoundManager::setSpeechPercent(double percent) {
_speechPercent = percent;
updateVolumes();
}
void QSoundManager::setMasterPercent(double percent) {
_masterPercent = percent;
updateVolumes();
}
void QSoundManager::setParrotPercent(double percent) {
_parrotPercent = percent;
}
void QSoundManager::setListenerPosition(double posX, double posY, double posZ,
double directionX, double directionY, double directionZ, bool stopSounds) {
if (stopSounds) {
// Stop any running sounds
for (uint idx = 0; idx < _slots.size(); ++idx) {
if (_slots[idx]._positioningMode != 0)
stopSound(_slots[idx]._handle);
}
}
qsWaveMixSetListenerPosition(QSVECTOR(posX, posY, posZ));
qsWaveMixSetListenerOrientation(QSVECTOR(directionX, directionY, directionZ),
QSVECTOR(0.0, 0.0, -1.0));
}
int QSoundManager::playWave(CWaveFile *waveFile, int iChannel, uint flags, CProximity &prox) {
if (!waveFile || !waveFile->isLoaded())
return 0;
prox._channelVolume = CLIP(prox._channelVolume, 0, 100);
prox._balance = CLIP(prox._balance, -100, 100);
int slotIndex = findFreeSlot();
if (slotIndex == -1)
return -1;
// Set the volume
setChannelVolume(iChannel, prox._channelVolume, prox._channelMode);
switch (prox._positioningMode) {
case POSMODE_POLAR:
qsWaveMixSetPolarPosition(iChannel, 8, QSPOLAR(prox._azimuth, prox._range, prox._elevation));
qsWaveMixEnableChannel(iChannel, QMIX_CHANNEL_ELEVATION, true);
qsWaveMixSetDistanceMapping(iChannel, 8, QMIX_DISTANCES(5.0, 3.0, 1.0));
break;
case POSMODE_VECTOR:
qsWaveMixSetSourcePosition(iChannel, 8, QSVECTOR(prox._posX, prox._posY, prox._posZ));
qsWaveMixEnableChannel(iChannel, QMIX_CHANNEL_ELEVATION, true);
qsWaveMixSetDistanceMapping(iChannel, 8, QMIX_DISTANCES(5.0, 3.0, 1.0));
break;
default:
qsWaveMixEnableChannel(iChannel, QMIX_CHANNEL_ELEVATION, true);
qsWaveMixSetPolarPosition(iChannel, 8, QSPOLAR(0.0, 1.0, 0.0));
break;
}
if (prox._frequencyMultiplier || prox._frequencyAdjust != 1.875) {
uint freq = (uint)(waveFile->getFrequency() * prox._frequencyMultiplier);
qsWaveMixSetFrequency(iChannel, 8, freq);
}
_sounds.add(waveFile, iChannel, prox._endTalkerFn, prox._talker);
QMIXPLAYPARAMS playParams;
playParams.callback = soundFinished;
playParams.dwUser = this;
if (!qsWaveMixPlayEx(iChannel, flags, waveFile, prox._repeated ? -1 : 0, playParams)) {
Slot &slot = _slots[slotIndex];
slot._handle = _handleCtr++;
slot._channel = iChannel;
slot._waveFile = waveFile;
slot._positioningMode = prox._positioningMode;
return slot._handle;
} else {
_sounds.flushChannel(waveFile, iChannel);
if (prox._disposeAfterUse == DisposeAfterUse::YES)
delete waveFile;
return 0;
}
}
void QSoundManager::soundFreed(Audio::SoundHandle &handle) {
qsWaveMixFreeWave(handle);
}
void QSoundManager::updateVolume(int channel, uint panRate) {
double volume = _channelsVolume[channel] * 327;
switch (_channelsMode[channel]) {
case 0:
case 1:
case 2:
volume = (_speechPercent * volume) / 100;
break;
case 3:
case 4:
case 5:
volume = (75 * volume) / 100;
break;
case 6:
case 7:
case 8:
case 9:
volume = (_masterPercent * volume) / 100;
break;
default:
break;
}
volume = (_musicPercent * volume) / 100;
qsWaveMixSetPanRate(channel, 0, panRate);
qsWaveMixSetVolume(channel, 0, (uint)volume);
}
void QSoundManager::updateVolumes() {
for (uint idx = 0; idx < CHANNELS_COUNT; ++idx)
updateVolume(idx, 250);
}
void QSoundManager::soundFinished(int iChannel, CWaveFile *waveFile, void *soundManager) {
static_cast<QSoundManager *>(soundManager)->_sounds.flushChannel(waveFile, iChannel);
}
int QSoundManager::findFreeSlot() {
for (uint idx = 0; idx < _slots.size(); ++idx) {
if (!_slots[idx]._waveFile)
return idx;
}
return -1;
}
void QSoundManager::setChannelVolume(int iChannel, uint volume, uint mode) {
_channelsVolume[iChannel] = volume;
_channelsMode[iChannel] = mode;
updateVolume(iChannel, 250);
}
} // End of namespace Titanic z

View File

@@ -0,0 +1,474 @@
/* 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/>.
*
*/
#ifndef TITANIC_SOUND_MANAGER_H
#define TITANIC_SOUND_MANAGER_H
#include "titanic/core/list.h"
#include "titanic/support/simple_file.h"
#include "titanic/sound/audio_buffer.h"
#include "titanic/sound/proximity.h"
#include "titanic/sound/qmixer.h"
#include "titanic/sound/wave_file.h"
#include "titanic/true_talk/dialogue_file.h"
namespace Titanic {
enum VolumeMode {
VOL_NORMAL = -1, VOL_QUIET = -2, VOL_VERY_QUIET = -3, VOL_MUTE = -4
};
/**
* Abstract interface class for a sound manager
*/
class CSoundManager {
protected:
uint _handleCtr;
// Old volume levels, deprecated in favor of setting the volumes
// directly in the ScummVM mixer
double _musicPercent;
double _speechPercent;
double _masterPercent;
double _parrotPercent;
public:
CSoundManager();
virtual ~CSoundManager() {}
/**
* Loads a sound
* @param name Name of sound resource
* @returns Loaded wave file
*/
virtual CWaveFile *loadSound(const CString &name) { return nullptr; }
/**
* Loads a speech resource from a dialogue file
* @param name Name of sound resource
* @returns Loaded wave file
*/
virtual CWaveFile *loadSpeech(CDialogueFile *dialogueFile, int speechId) { return 0; }
/**
* Loads a music file
* @param name Name of music resource
* @returns Loaded wave file
* @remarks The original only classified music as what's produced in the
* music room puzzle. For ScummVM, we've reclassified some wave files that
* contain background music as music as well.
*/
virtual CWaveFile *loadMusic(const CString &name) { return nullptr; }
/**
* Loads a music file from a streaming audio buffer
* @param buffer Audio buffer
* @returns Loaded wave file
*/
virtual CWaveFile *loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse) { return nullptr; }
/**
* Start playing a previously loaded wave file
*/
virtual int playSound(CWaveFile &waveFile, CProximity &prox) = 0;
/**
* Stop playing the specified sound
*/
virtual void stopSound(int handle) = 0;
/**
* Stops a designated range of channels
*/
virtual void stopChannel(int channel) = 0;
virtual void proc9(int handle) {}
/**
* Stops sounds on all playing channels
*/
virtual void stopAllChannels() = 0;
/**
* Sets the volume for a sound
* @param handle Handle for sound
* @param volume New volume
* @param seconds Number of seconds to transition to the new volume
*/
virtual void setVolume(int handle, uint volume, uint seconds) = 0;
/**
* Set the position for a sound
* @param handle Handle for sound
* @param x x position in metres
* @param y y position in metres
* @param z z position in metres
* @param panRate Rate in milliseconds to transition
*/
virtual void setVectorPosition(int handle, double x, double y, double z, uint panRate) {}
/**
* Set the position for a sound
* @param handle Handle for sound
* @param range Range value in metres
* @param azimuth Azimuth value in degrees
* @param elevation Elevation value in degrees
* @param panRate Rate in milliseconds to transition
*/
virtual void setPolarPosition(int handle, double range, double azimuth, double elevation, uint panRate) {}
/**
* Returns true if the given sound is currently active
*/
virtual bool isActive(int handle) = 0;
/**
* Returns true if the given sound is currently active
*/
virtual bool isActive(const CWaveFile *waveFile) { return false; }
/**
* Handles regularly updating the mixer
*/
virtual void waveMixPump() = 0;
/**
* Returns the movie latency
*/
virtual uint getLatency() const { return 0; }
/**
* Sets the music volume percent
*/
virtual void setMusicPercent(double percent) = 0;
/**
* Sets the speech volume percent
*/
virtual void setSpeechPercent(double percent) = 0;
/**
* Sets the master volume percent
*/
virtual void setMasterPercent(double percent) = 0;
/**
* Sets the Parrot NPC volume percent
*/
virtual void setParrotPercent(double percent) = 0;
/**
* Called when a game is about to be loaded
*/
virtual void preLoad() { stopAllChannels(); }
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) {}
/**
* Called after loading of a game is completed
*/
virtual void postLoad() {}
/**
* Called when a game is about to be saved
*/
virtual void preSave() {}
/**
* Save the data for the class to file
*/
void save(SimpleFile *file) const {}
/**
* Called after saving is complete
*/
virtual void postSave() {}
/**
* Sets the position and orientation for the listener (player)
*/
virtual void setListenerPosition(double posX, double posY, double posZ,
double directionX, double directionY, double directionZ, bool stopSounds) {}
/**
* Returns the music volume percent
*/
double getMusicVolume() const { return _musicPercent; }
/**
* Returns the speech volume percent
*/
double getSpeechVolume() const { return _speechPercent; }
/**
* Returns the parrot volume percent
*/
double getParrotVolume() const { return _parrotPercent; }
/**
* Gets the volume for a given mode? value
*/
uint getModeVolume(VolumeMode mode);
};
class QSoundManagerSound : public ListItem {
public:
CWaveFile *_waveFile;
int _iChannel;
CEndTalkerFn _endFn;
TTtalker *_talker;
public:
QSoundManagerSound() : ListItem(), _waveFile(nullptr),
_iChannel(0), _endFn(nullptr), _talker(nullptr) {}
QSoundManagerSound(CWaveFile *waveFile, int iChannel, CEndTalkerFn endFn, TTtalker *talker) :
ListItem(), _waveFile(waveFile), _iChannel(iChannel), _endFn(endFn), _talker(talker) {}
};
class QSoundManagerSounds : public List<QSoundManagerSound> {
public:
/**
* Adds a new sound entry to the list
*/
void add(CWaveFile *waveFile, int iChannel, CEndTalkerFn endFn, TTtalker *talker);
/**
* Flushes a wave file attached to the specified channel
*/
void flushChannel(int iChannel);
/**
* Flushes a wave file attached to the specified channel
*/
void flushChannel(CWaveFile *waveFile, int iChannel);
/**
* Returns true if the list contains the specified wave file
*/
bool contains(const CWaveFile *waveFile) const;
};
/**
* Concrete sound manager class that handles interfacing with
* the QMixer sound mixer class
*/
class QSoundManager : public CSoundManager, public QMixer {
struct Slot {
CWaveFile *_waveFile;
bool _isTimed;
uint _ticks;
int _channel;
int _handle;
PositioningMode _positioningMode;
Slot() : _waveFile(0), _isTimed(0), _ticks(0), _channel(-1),
_handle(0), _positioningMode(POSMODE_NONE) {}
void clear();
};
private:
QSoundManagerSounds _sounds;
Common::Array<Slot> _slots;
uint _channelsVolume[16];
int _channelsMode[16];
private:
/**
* Updates the volume for a channel
* @param channel Channel to be update
* @param panRate Time in milliseconds for change to occur
*/
void updateVolume(int channel, uint panRate);
/**
* Updates all the volumes
*/
void updateVolumes();
/**
* Called by the QMixer when a sound finishes playing
*/
static void soundFinished(int iChannel, CWaveFile *waveFile, void *soundManager);
/**
* Finds the first free slot
*/
int findFreeSlot();
/**
* Sets a channel volume
*/
void setChannelVolume(int iChannel, uint volume, uint mode);
/**
* Resets the specified channel and returns a new free one
*/
int resetChannel(int iChannel);
public:
int _field18;
int _field1C;
public:
QSoundManager(Audio::Mixer *mixer);
~QSoundManager() override;
/**
* Loads a sound
* @param name Name of sound resource
* @returns Loaded wave file
*/
CWaveFile *loadSound(const CString &name) override;
/**
* Loads a speech resource from a dialogue file
* @param name Name of sound resource
* @returns Loaded wave file
*/
CWaveFile *loadSpeech(CDialogueFile *dialogueFile, int speechId) override;
/**
* Loads a music file
* @param name Name of music resource
* @returns Loaded wave file
* @remarks The original only classified music as what's produced in the
* music room puzzle. For ScummVM, we've reclassified some wave files that
* contain background music as music as well.
*/
CWaveFile *loadMusic(const CString &name) override;
/**
* Loads a music file from a streaming audio buffer
* @param buffer Audio buffer
* @returns Loaded wave file
*/
CWaveFile *loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse) override;
/**
* Start playing a previously loaded sound resource
*/
int playSound(CWaveFile &waveFile, CProximity &prox) override;
/**
* Stop playing the specified sound
*/
void stopSound(int handle) override;
/**
* Stops a designated range of channels
*/
void stopChannel(int channel) override;
/**
* Flags that a sound can be freed if a timeout is set
*/
virtual void setCanFree(int handle);
/**
* Stops sounds on all playing channels
*/
void stopAllChannels() override;
/**
* Sets the volume for a sound
* @param handle Handle for sound
* @param volume New volume
* @param seconds Number of seconds to transition to the new volume
*/
void setVolume(int handle, uint volume, uint seconds) override;
/**
* Set the position for a sound
* @param handle Handle for sound
* @param x x position in metres
* @param y y position in metres
* @param z z position in metres
* @param panRate Rate in milliseconds to transition
*/
void setVectorPosition(int handle, double x, double y, double z, uint panRate) override;
/**
* Set the position for a sound
* @param handle Handle for sound
* @param range Range value in metres
* @param azimuth Azimuth value in degrees
* @param elevation Elevation value in degrees
* @param panRate Rate in milliseconds to transition
*/
void setPolarPosition(int handle, double range, double azimuth, double elevation, uint panRate) override;
/**
* Returns true if the given sound is currently active
*/
bool isActive(int handle) override;
/**
* Returns true if the given sound is currently active
*/
bool isActive(const CWaveFile *waveFile) override;
/**
* Handles regularly updating the mixer
*/
void waveMixPump() override;
/**
* Returns the movie latency
*/
uint getLatency() const override;
/**
* Sets the music volume percent
*/
void setMusicPercent(double percent) override;
/**
* Sets the speech volume percent
*/
void setSpeechPercent(double percent) override;
/**
* Sets the master volume percent
*/
void setMasterPercent(double percent) override;
/**
* Sets the Parrot NPC volume percent
*/
void setParrotPercent(double percent) override;
/**
* Sets the position and orientation for the listener (player)
*/
void setListenerPosition(double posX, double posY, double posZ,
double directionX, double directionY, double directionZ, bool stopSounds) override;
/**
* Starts a wave file playing
*/
virtual int playWave(CWaveFile *waveFile, int iChannel, uint flags, CProximity &prox);
/**
* Called when a wave file is freed
*/
void soundFreed(Audio::SoundHandle &handle);
};
} // End of namespace Titanic
#endif /* TITANIC_QSOUND_MANAGER_H */

View File

@@ -0,0 +1,166 @@
/* 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/>.
*
*/
#include "titanic/sound/titania_speech.h"
#include "titanic/translation.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CTitaniaSpeech, CGameObject)
ON_MESSAGE(ActMsg)
ON_MESSAGE(MovieEndMsg)
ON_MESSAGE(MovieFrameMsg)
ON_MESSAGE(TimerMsg)
ON_MESSAGE(EnterRoomMsg)
END_MESSAGE_MAP()
void CTitaniaSpeech::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeNumberLine(_actionNum, indent);
file->writeNumberLine(_backgroundFrame, indent);
CGameObject::save(file, indent);
}
void CTitaniaSpeech::load(SimpleFile *file) {
file->readNumber();
_actionNum = file->readNumber();
_backgroundFrame = file->readNumber();
CGameObject::load(file);
}
bool CTitaniaSpeech::ActMsg(CActMsg *msg) {
CSetFrameMsg frameMsg;
CVisibleMsg visibleMsg;
CActMsg actMsg;
if (msg->_action == "TitaniaSpeech") {
CProximity prox(Audio::Mixer::kSpeechSoundType);
switch (_actionNum) {
case 1:
loadSound(TRANSLATE("a#12.wav", "a#0.wav"));
sleep(1000);
playMovie(TRANSLATE(0, 584), TRANSLATE(187, 761),
MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
if (g_language == Common::EN_ANY) {
movieSetPlaying(true);
movieEvent(0);
} else {
playSound("a#0.wav", prox);
}
break;
case 2:
loadSound(TRANSLATE("a#11.wav", "a#4.wav"));
addTimer(0);
startAnimTimer("Para2", 300);
addTimer(6000);
addTimer(12000);
addTimer(18000);
addTimer(24000);
startAnimTimer("NextPara", TRANSLATE(30000, 33000));
break;
case 3:
visibleMsg._visible = false;
visibleMsg.execute("TitaniaStillControl");
loadSound(TRANSLATE("a#10.wav", "a#2.wav"));
playMovie(585, TRANSLATE(706, 748), MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
playSound(TRANSLATE("a#10.wav", "a#2.wav"), prox);
break;
case 4:
visibleMsg._visible = false;
visibleMsg.execute("TitaniaStillControl");
loadSound(TRANSLATE("a#9.wav", "a#3.wav"));
playMovie(707, 905, MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
playSound(TRANSLATE("a#9.wav", "a#3.wav"), prox);
break;
case 5:
visibleMsg._visible = false;
visibleMsg.execute("TitaniaStillControl");
loadSound(TRANSLATE("a#8.wav", "a#1.wav"));
playMovie(906, TRANSLATE(938, 943), MOVIE_WAIT_FOR_FINISH | MOVIE_NOTIFY_OBJECT);
playSound(TRANSLATE("a#8.wav", "a#1.wav"), prox);
break;
default:
sleep(3000);
actMsg._action = "SleepTitania";
actMsg.execute("TitaniaControl");
}
}
return true;
}
bool CTitaniaSpeech::MovieEndMsg(CMovieEndMsg *msg) {
if (_actionNum == 5) {
startAnimTimer("NextPara", 0);
} else {
if (_actionNum != 1)
addTimer(0);
startAnimTimer("NextPara", 3000);
}
return true;
}
bool CTitaniaSpeech::MovieFrameMsg(CMovieFrameMsg *msg) {
int frame = getMovieFrame();
if (frame == 0) {
CProximity prox(Audio::Mixer::kSpeechSoundType);
playSound(TRANSLATE("a#12.wav", "a#0.wav"), prox);
}
return true;
}
bool CTitaniaSpeech::TimerMsg(CTimerMsg *msg) {
CSetFrameMsg frameMsg;
CVisibleMsg visibleMsg;
CActMsg actMsg("TitaniaSpeech");
if (msg->_action == "NextPara") {
visibleMsg.execute("TitaniaStillControl");
++_actionNum;
actMsg.execute(this);
} else if (msg->_action == "Para2") {
CProximity prox(Audio::Mixer::kSpeechSoundType);
playSound(TRANSLATE("a#11.wav", "a#4.wav"), prox);
} else {
frameMsg._frameNumber = _backgroundFrame++;
frameMsg.execute("TitaniaStillControl");
}
return true;
}
bool CTitaniaSpeech::EnterRoomMsg(CEnterRoomMsg *msg) {
CActMsg actMsg("Disable");
actMsg.execute("ShipAnnouncements");
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,57 @@
/* 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/>.
*
*/
#ifndef TITANIC_TITANIA_SPEECH_H
#define TITANIC_TITANIA_SPEECH_H
#include "titanic/core/game_object.h"
#include "titanic/messages/messages.h"
namespace Titanic {
class CTitaniaSpeech : public CGameObject {
DECLARE_MESSAGE_MAP;
bool ActMsg(CActMsg *msg);
bool MovieEndMsg(CMovieEndMsg *msg);
bool MovieFrameMsg(CMovieFrameMsg *msg);
bool TimerMsg(CTimerMsg *msg);
bool EnterRoomMsg(CEnterRoomMsg *msg);
private:
int _actionNum;
int _backgroundFrame;
public:
CLASSDEF;
CTitaniaSpeech() : CGameObject(), _actionNum(1), _backgroundFrame(0) {}
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_TITANIA_SPEECH_H */

View File

@@ -0,0 +1,60 @@
/* 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/>.
*
*/
#include "titanic/sound/trigger_auto_music_player.h"
#include "titanic/sound/auto_music_player.h"
#include "titanic/core/room_item.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CTriggerAutoMusicPlayer, CGameObject)
ON_MESSAGE(TriggerAutoMusicPlayerMsg)
END_MESSAGE_MAP()
void CTriggerAutoMusicPlayer::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeQuotedLine(_roomName, indent);
CGameObject::save(file, indent);
}
void CTriggerAutoMusicPlayer::load(SimpleFile *file) {
file->readNumber();
_roomName = file->readString();
CGameObject::load(file);
}
bool CTriggerAutoMusicPlayer::TriggerAutoMusicPlayerMsg(CTriggerAutoMusicPlayerMsg *msg) {
CRoomItem *room1 = msg->_value == 1 ? locateRoom(_roomName) : findRoom();
CRoomItem *room2 = msg->_value == 2 ? locateRoom(_roomName) : findRoom();
CChangeMusicMsg changeMsg;
changeMsg._action = MUSIC_STOP;
changeMsg.execute(room1, CAutoMusicPlayer::_type,
MSGFLAG_CLASS_DEF | MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_SCAN);
changeMsg._action = MUSIC_START;
changeMsg.execute(room2, CAutoMusicPlayer::_type,
MSGFLAG_CLASS_DEF | MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_SCAN);
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,50 @@
/* 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/>.
*
*/
#ifndef TITANIC_TRIGGER_AUTO_MUSIC_PLAYER_H
#define TITANIC_TRIGGER_AUTO_MUSIC_PLAYER_H
#include "titanic/core/game_object.h"
namespace Titanic {
class CTriggerAutoMusicPlayer : public CGameObject {
DECLARE_MESSAGE_MAP;
bool TriggerAutoMusicPlayerMsg(CTriggerAutoMusicPlayerMsg *msg);
protected:
CString _roomName;
public:
CLASSDEF;
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_TRIGGER_AUTO_MUSIC_PLAYER_H */

View File

@@ -0,0 +1,83 @@
/* 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/>.
*
*/
#include "titanic/sound/view_auto_sound_player.h"
#include "titanic/sound/auto_music_player.h"
#include "titanic/core/room_item.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CViewAutoSoundPlayer, CAutoSoundPlayer)
ON_MESSAGE(EnterViewMsg)
ON_MESSAGE(LeaveViewMsg)
END_MESSAGE_MAP()
void CViewAutoSoundPlayer::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeNumberLine(_enabled, indent);
CAutoSoundPlayer::save(file, indent);
}
void CViewAutoSoundPlayer::load(SimpleFile *file) {
file->readNumber();
_enabled = file->readNumber();
CAutoSoundPlayer::load(file);
}
bool CViewAutoSoundPlayer::EnterViewMsg(CEnterViewMsg *msg) {
CViewItem *view = findView();
CRoomItem *room = findRoom();
if (view == msg->_newView) {
CTurnOn onMsg;
onMsg.execute(this);
if (_enabled) {
CChangeMusicMsg changeMsg;
changeMsg._action = MUSIC_STOP;
changeMsg.execute(room, CAutoMusicPlayer::_type,
MSGFLAG_CLASS_DEF |MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_SCAN);
}
}
return true;
}
bool CViewAutoSoundPlayer::LeaveViewMsg(CLeaveViewMsg *msg) {
CViewItem *view = findView();
CRoomItem *room = findRoom();
if (view == msg->_oldView) {
CTurnOff offMsg;
offMsg.execute(this);
if (_enabled) {
CChangeMusicMsg changeMsg;
changeMsg._action = MUSIC_START;
changeMsg.execute(room, CAutoMusicPlayer::_type,
MSGFLAG_CLASS_DEF | MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_SCAN);
}
}
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,52 @@
/* 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/>.
*
*/
#ifndef TITANIC_VIEW_AUTO_SOUND_PLAYER_H
#define TITANIC_VIEW_AUTO_SOUND_PLAYER_H
#include "titanic/sound/auto_sound_player.h"
namespace Titanic {
class CViewAutoSoundPlayer : public CAutoSoundPlayer {
DECLARE_MESSAGE_MAP;
bool EnterViewMsg(CEnterViewMsg *msg);
bool LeaveViewMsg(CLeaveViewMsg *msg);
private:
bool _enabled;
public:
CLASSDEF;
CViewAutoSoundPlayer() : CAutoSoundPlayer(), _enabled(false) {}
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_VIEW_AUTO_SOUND_PLAYER_H */

View File

@@ -0,0 +1,57 @@
/* 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/>.
*
*/
#include "titanic/sound/view_toggles_other_music.h"
namespace Titanic {
BEGIN_MESSAGE_MAP(CViewTogglesOtherMusic, CEnterViewTogglesOtherMusic)
ON_MESSAGE(LeaveViewMsg)
END_MESSAGE_MAP()
CViewTogglesOtherMusic::CViewTogglesOtherMusic() :
CEnterViewTogglesOtherMusic(), _value(1) {
}
void CViewTogglesOtherMusic::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeNumberLine(_value, indent);
CEnterViewTogglesOtherMusic::save(file, indent);
}
void CViewTogglesOtherMusic::load(SimpleFile *file) {
file->readNumber();
_value = file->readNumber();
CEnterViewTogglesOtherMusic::load(file);
}
bool CViewTogglesOtherMusic::LeaveViewMsg(CLeaveViewMsg *msg) {
if (msg->_oldView == findView()) {
CTriggerAutoMusicPlayerMsg playerMsg(_value);
playerMsg.execute(this);
}
return true;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,51 @@
/* 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/>.
*
*/
#ifndef TITANIC_VIEW_TOGGLES_OTHER_MUSIC_H
#define TITANIC_VIEW_TOGGLES_OTHER_MUSIC_H
#include "titanic/sound/enter_view_toggles_other_music.h"
namespace Titanic {
class CViewTogglesOtherMusic : public CEnterViewTogglesOtherMusic {
DECLARE_MESSAGE_MAP;
bool LeaveViewMsg(CLeaveViewMsg *msg);
private:
int _value;
public:
CLASSDEF;
CViewTogglesOtherMusic();
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_VIEW_TOGGLES_OTHER_MUSIC_H */

View File

@@ -0,0 +1,55 @@
/* 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/>.
*
*/
#include "titanic/sound/water_lapping_sounds.h"
namespace Titanic {
EMPTY_MESSAGE_MAP(CWaterLappingSounds, CRoomAutoSoundPlayer);
CWaterLappingSounds::CWaterLappingSounds() : CRoomAutoSoundPlayer(),
_value(0) {
_filename = "z#217.wav";
_repeated = false;
_startSeconds = 0;
}
void CWaterLappingSounds::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
file->writeQuotedLine(_filename, indent);
file->writeNumberLine(_repeated, indent);
file->writeNumberLine(_startSeconds, indent);
file->writeNumberLine(_value, indent);
CRoomAutoSoundPlayer::save(file, indent);
}
void CWaterLappingSounds::load(SimpleFile *file) {
file->readNumber();
_filename = file->readString();
_repeated = file->readNumber();
_startSeconds = file->readNumber();
_value = file->readNumber();
CRoomAutoSoundPlayer::load(file);
}
} // End of namespace Titanic

View File

@@ -0,0 +1,50 @@
/* 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/>.
*
*/
#ifndef TITANIC_WATER_LAPPING_SOUNDS_H
#define TITANIC_WATER_LAPPING_SOUNDS_H
#include "titanic/sound/room_auto_sound_player.h"
namespace Titanic {
class CWaterLappingSounds : public CRoomAutoSoundPlayer {
DECLARE_MESSAGE_MAP;
public:
int _value;
public:
CLASSDEF;
CWaterLappingSounds();
/**
* Save the data for the class to file
*/
void save(SimpleFile *file, int indent) override;
/**
* Load the data for the class from file
*/
void load(SimpleFile *file) override;
};
} // End of namespace Titanic
#endif /* TITANIC_WATER_LAPPING_SOUNDS_H */

View File

@@ -0,0 +1,212 @@
/* 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/>.
*
*/
#include "audio/decoders/raw.h"
#include "audio/decoders/wave.h"
#include "audio/decoders/wave_types.h"
#include "common/memstream.h"
#include "titanic/sound/wave_file.h"
#include "titanic/sound/sound_manager.h"
#include "titanic/support/simple_file.h"
namespace Titanic {
/**
* This creates a ScummVM audio stream around a CAudioBuffer buffer,
* allowing for streaming audio output for the music room music
*/
class AudioBufferStream : public Audio::SeekableAudioStream {
private:
CAudioBuffer *_audioBuffer;
public:
AudioBufferStream(CAudioBuffer *audioBuffer) : _audioBuffer(audioBuffer) {}
int readBuffer(int16 *buffer, const int numSamples) override;
bool isStereo() const override { return false; }
bool endOfData() const override;
int getRate() const override { return 22050; }
Audio::Timestamp getLength() const override { return Audio::Timestamp(); }
bool seek(const Audio::Timestamp &where) override { return false; }
};
int AudioBufferStream::readBuffer(int16 *buffer, const int numSamples) {
return _audioBuffer->read(buffer, numSamples);
}
bool AudioBufferStream::endOfData() const {
return _audioBuffer->isFinished();
}
/*------------------------------------------------------------------------*/
CWaveFile::CWaveFile(Audio::Mixer *mixer) : _mixer(mixer), _pendingAudioStream(nullptr),
_waveData(nullptr), _waveSize(0), _dataSize(0), _headerSize(0),
_rate(0), _flags(0), _wavType(0), _soundType(Audio::Mixer::kPlainSoundType) {
setup();
}
void CWaveFile::setup() {
_loadMode = LOADMODE_SCUMMVM;
_dataSize = 0;
_audioBuffer = nullptr;
_disposeAudioBuffer = DisposeAfterUse::NO;
_channel = -1;
}
CWaveFile::~CWaveFile() {
// Delete any pending audio stream if it wasn't used
delete _pendingAudioStream;
if (_disposeAudioBuffer == DisposeAfterUse::YES && _audioBuffer)
delete _audioBuffer;
free(_waveData);
}
uint CWaveFile::getDurationTicks() const {
if (!_rate)
return 0;
// FIXME: The original uses acmStreamSize to calculate
// a desired size. Since I have no idea how the system API
// method works, for now I'm using a simple ratio of a
// sample output to input value
double newSize = (double)_dataSize * (1475712.0 / 199836.0);
return (uint)(newSize * 1000.0 / _rate);
}
bool CWaveFile::loadSound(const CString &name) {
StdCWadFile file;
if (!file.open(name))
return false;
Common::SeekableReadStream *stream = file.readStream();
uint wavSize = stream->size();
byte *data = (byte *)malloc(wavSize);
stream->read(data, wavSize);
load(data, wavSize);
_soundType = Audio::Mixer::kSFXSoundType;
return true;
}
bool CWaveFile::loadSpeech(CDialogueFile *dialogueFile, int speechIndex) {
DialogueResource *res = dialogueFile->openWaveEntry(speechIndex);
if (!res)
return false;
byte *data = (byte *)malloc(res->_size);
dialogueFile->read(res, data, res->_size);
load(data, res->_size);
_soundType = Audio::Mixer::kSpeechSoundType;
return true;
}
bool CWaveFile::loadMusic(const CString &name) {
StdCWadFile file;
if (!file.open(name))
return false;
Common::SeekableReadStream *stream = file.readStream();
uint wavSize = stream->size();
byte *data = new byte[wavSize];
stream->read(data, wavSize);
delete stream;
load(data, wavSize);
_soundType = Audio::Mixer::kMusicSoundType;
return true;
}
bool CWaveFile::loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse) {
_audioBuffer = buffer;
_disposeAudioBuffer = disposeAfterUse;
_loadMode = LOADMODE_AUDIO_BUFFER;
_pendingAudioStream = new AudioBufferStream(_audioBuffer);
return true;
}
void CWaveFile::load(byte *data, uint dataSize) {
_waveData = data;
_waveSize = dataSize;
// Parse the wave header
Common::MemoryReadStream wavStream(data, dataSize, DisposeAfterUse::NO);
if (!Audio::loadWAVFromStream(wavStream, _dataSize, _rate, _flags, &_wavType))
error("Invalid wave file");
_headerSize = wavStream.pos();
}
Audio::SeekableAudioStream *CWaveFile::createAudioStream() {
Audio::SeekableAudioStream *stream;
if (_pendingAudioStream) {
stream = _pendingAudioStream;
_pendingAudioStream = nullptr;
} else {
// Create a new ScummVM audio stream for the wave file data
stream = Audio::makeWAVStream(
new Common::MemoryReadStream(_waveData, _waveSize, DisposeAfterUse::NO),
DisposeAfterUse::YES);
}
_rate = stream->getRate();
return stream;
}
const int16 *CWaveFile::lock() {
switch (_loadMode) {
case LOADMODE_SCUMMVM:
// Sanity checking that only raw 16-bit LE 22Khz waves can be locked
assert(_waveData && _rate == AUDIO_SAMPLING_RATE);
assert(_flags == (Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_16BITS));
assert(_wavType == Audio::kWaveFormatPCM);
// Return a pointer to the data section of the wave file
return (const int16 *)(_waveData + _headerSize);
default:
return nullptr;
}
}
void CWaveFile::unlock(const int16 *ptr) {
// No implementation needed in ScummVM
}
Audio::SoundHandle CWaveFile::play(int numLoops, byte volume) {
Audio::SeekableAudioStream *audioStream = createAudioStream();
Audio::SoundHandle handle;
Audio::AudioStream *stream = audioStream;
if (numLoops != 0)
stream = new Audio::LoopingAudioStream(audioStream,
(numLoops == -1) ? 0 : numLoops);
_mixer->playStream(_soundType, &handle, stream, -1,
volume, 0, DisposeAfterUse::YES);
return handle;
}
} // End of namespace Titanic

View File

@@ -0,0 +1,138 @@
/* 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/>.
*
*/
#ifndef TITANIC_WAVE_FILE_H
#define TITANIC_WAVE_FILE_H
#include "audio/audiostream.h"
#include "audio/mixer.h"
#include "titanic/sound/audio_buffer.h"
#include "titanic/support/string.h"
#include "titanic/true_talk/dialogue_file.h"
namespace Titanic {
enum LoadMode { LOADMODE_AUDIO_BUFFER = 1, LOADMODE_SCUMMVM = 2 };
class CWaveFile {
private:
Audio::Mixer *_mixer;
byte *_waveData;
int _waveSize;
int _dataSize;
int _headerSize;
int _rate;
byte _flags;
uint16 _wavType;
Audio::SeekableAudioStream *_pendingAudioStream;
private:
/**
* Handles setup of fields shared by the constructors
*/
void setup();
/**
* Gets passed the raw data for the wave file
*/
void load(byte *data, uint dataSize);
/**
* Returns a ScummVM Audio Stream for playback purposes
*/
Audio::SeekableAudioStream *createAudioStream();
public:
Audio::Mixer::SoundType _soundType;
LoadMode _loadMode;
CAudioBuffer *_audioBuffer;
DisposeAfterUse::Flag _disposeAudioBuffer;
int _channel;
public:
CWaveFile(Audio::Mixer *mixer);
~CWaveFile();
/**
* Returns the duration of the wave file
* @returns Total ticks. Not really sure how ticks
* map to real time
*/
uint getDurationTicks() const;
/**
* Return the size of the wave file
*/
uint size() const { return _dataSize; }
/**
* Tries to load the specified wave file sound
*/
bool loadSound(const CString &name);
/**
* Tries to load speech from a specified dialogue file
*/
bool loadSpeech(CDialogueFile *dialogueFile, int speechIndex);
/**
* Tries to load the specified music wave file
*/
bool loadMusic(const CString &name);
/**
* Tries to load the specified audio buffer
*/
bool loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse);
/**
* Returns true if the wave file has data loaded
*/
bool isLoaded() const {
return _waveData != nullptr || _pendingAudioStream != nullptr;
}
/**
* Return the frequency of the loaded wave file
*/
uint getFrequency() const { return _rate; }
/**
* Lock sound data for access
*/
const int16 *lock();
/**
* Unlock sound data after a prior call to lock
*/
void unlock(const int16 *ptr);
/**
* Plays the wave file
* @param numLoops Number of times to loop. 0 for none,
* -1 for infinite, and >0 for specified number of times
* @param volume Volume to play at
* @returns Audio handle for started sound
*/
Audio::SoundHandle play(int numLoops, byte volume);
};
} // End of namespace Titanic
#endif /* TITANIC_WAVE_FILE_H */