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,215 @@
/* 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/config-manager.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/xmath.h"
#include "qdengine/system/graphics/gr_dispatcher.h"
#include "qdengine/system/sound/snd_dispatcher.h"
#include "qdengine/qdcore/util/plaympp_api.h"
namespace QDEngine {
sndDispatcher *sndDispatcher::_dispatcher_ptr;
static bool operator == (const sndSound &snd0, const sndSound &snd1) {
return snd0.sound() == snd1.sound();
}
static bool operator == (const sndSound &snd, const sndHandle &h) {
return snd.handle() == &h;
}
sndDispatcher::sndDispatcher() : _is_enabled(true),
_is_paused(false),
_volume(255),
_volume_dB(0),
_frequency_coeff(1.0f) {
if (!_dispatcher_ptr)
_dispatcher_ptr = this;
}
sndDispatcher::~sndDispatcher() {
_sounds.clear();
if (_dispatcher_ptr == this)
_dispatcher_ptr = NULL;
}
void sndDispatcher::set_volume(uint32 vol) {
_volume = vol & 0xFF;
_volume_dB = convert_volume_to_dB(_volume);
update_volume();
}
int sndDispatcher::convert_volume_to_dB(int vol) {
if (vol > 255) vol = 255;
if (vol < 0) vol = 0;
if (vol != 255) {
const int DB_MIN = -10000;
const int DB_MAX = 0;
const int DB_SIZE = DB_MAX - DB_MIN;
return (DB_MIN + round(log10(9.0 * log(double(vol + 1)) / (log(2.0) * 8) + 1.0) * DB_SIZE));
} else
return 0;
}
void sndDispatcher::quant() {
for (auto it = _sounds.begin(); it != _sounds.end(); ) {
if (it->is_stopped())
it = _sounds.erase(it);
else
++it;
}
}
bool sndDispatcher::play_sound(const sndSound *snd, bool loop, int vol) {
if (is_enabled()) {
_sounds.push_back(sndSound(*snd));
sndSound &p = _sounds.back();
if (loop)
p.toggle_looping();
int snd_volume = vol * volume() / 256;
if (!p.create_sound_buffer())
return false;
p.set_volume(snd_volume);
p.change_frequency(frequency_coeff());
if (!is_paused()) {
if (!p.play()) return false;
} else
p.pause();
}
return true;
}
bool sndDispatcher::stop_sound(const sndSound *snd) {
sound_list_t::iterator it = Common::find(_sounds.begin(), _sounds.end(), *snd);
if (it != _sounds.end()) {
it->stop();
_sounds.erase(it);
return true;
}
return false;
}
bool sndDispatcher::stop_sound(const sndHandle *handle) {
sound_list_t::iterator it = Common::find(_sounds.begin(), _sounds.end(), *handle);
if (it != _sounds.end()) {
it->stop();
_sounds.erase(it);
return true;
}
return false;
}
sndSound::status_t sndDispatcher::sound_status(const sndHandle *handle) const {
sound_list_t::const_iterator it = Common::find(_sounds.begin(), _sounds.end(), *handle);
if (it != _sounds.end()) {
if (is_paused())
return sndSound::SOUND_PAUSED;
return sndSound::SOUND_PLAYING;
}
return sndSound::SOUND_STOPPED;
}
sndSound::status_t sndDispatcher::sound_status(const sndSound *snd) const {
sound_list_t::const_iterator it = Common::find(_sounds.begin(), _sounds.end(), *snd);
if (it != _sounds.end())
return it->status();
return sndSound::SOUND_STOPPED;
}
bool sndDispatcher::update_volume() {
for (sound_list_t::iterator it = _sounds.begin(); it != _sounds.end(); ++it)
it->set_volume(volume());
return true;
}
bool sndDispatcher::update_frequency() {
for (sound_list_t::iterator it = _sounds.begin(); it != _sounds.end(); ++it)
it->change_frequency(frequency_coeff());
return true;
}
void sndDispatcher::stop_sounds() {
for (sound_list_t::iterator it = _sounds.begin(); it != _sounds.end(); ++it)
it->stop();
_sounds.clear();
}
bool sndDispatcher::set_sound_frequency(const sndHandle *snd, float coeff) {
sound_list_t::iterator it = Common::find(_sounds.begin(), _sounds.end(), *snd);
if (it != _sounds.end()) {
it->change_frequency(frequency_coeff() * coeff);
return true;
}
return false;
}
void sndDispatcher::pause_sounds() {
for (sound_list_t::iterator it = _sounds.begin(); it != _sounds.end(); ++it)
it->pause();
}
void sndDispatcher::resume_sounds() {
for (sound_list_t::iterator it = _sounds.begin(); it != _sounds.end(); ++it) {
if (it->is_paused())
it->resume();
}
}
void sndDispatcher::syncSoundSettings() {
set_volume(ConfMan.getInt("sound_volume"));
if (ConfMan.getBool("enable_sound"))
enable();
else
disable();
}
} // namespace QDEngine

View File

@@ -0,0 +1,165 @@
/* 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 QDENGINE_SYSTEM_SOUND_SND_DISPATCHER_H
#define QDENGINE_SYSTEM_SOUND_SND_DISPATCHER_H
#include "qdengine/system/sound/snd_sound.h"
namespace QDEngine {
//! Диспетчер звуков на DirectSound.
class sndDispatcher {
public:
sndDispatcher();
~sndDispatcher();
//! Логический квант.
void quant();
//! Запускает проигрывание звука.
bool play_sound(const sndSound *snd, bool loop, int vol = 255);
//! Останавливает проигрывание звука.
bool stop_sound(const sndSound *snd);
//! Останавливает проигрывание звука.
bool stop_sound(const sndHandle *handle);
//! Возвращает состояние звука (играется/остановлен и т.д.).
sndSound::status_t sound_status(const sndHandle *handle) const;
//! Возвращает состояние звука (играется/остановлен и т.д.).
sndSound::status_t sound_status(const sndSound *snd) const;
//! Изменение частоты звука.
bool set_sound_frequency(const sndHandle *snd, float coeff);
//! Изменение громкости, диапазон значений - [0, 255].
void set_volume(uint32 vol);
uint32 volume() const {
return _volume;
}
//! Возвращает установленную громкость в децибелах.
int volume_dB() const {
return _volume_dB;
}
void set_frequency_coeff(float coeff) {
_frequency_coeff = coeff;
update_frequency();
}
float frequency_coeff() const {
return _frequency_coeff;
}
//! Пересчет громкости в децибелы.
static int convert_volume_to_dB(int vol);
//! Останавливает все звуки.
void stop_sounds();
//! Ставит все играющие в данный момент звуки на паузу.
void pause_sounds();
//! Возобновляет проигрывание всех звуков, которые были поставлены на паузу.
void resume_sounds();
//! Ставит все звуки на паузу до вызова resume().
void pause() {
_is_paused = true;
pause_sounds();
}
//! Возобновляет проигрывание всех звуков.
void resume() {
_is_paused = false;
resume_sounds();
}
//! Возвращает true, если звуки поставлены на паузу.
bool is_paused() const {
return _is_paused;
}
//! Возвращает true, если звук выключен.
bool is_enabled() const {
return _is_enabled;
}
//! Включает звук.
void enable() {
_is_enabled = true;
}
//! Выключает звук.
void disable() {
_is_enabled = false;
stop_sounds();
}
void syncSoundSettings();
//! Возвращает указатель на текущий диспетчер.
static inline sndDispatcher *get_dispatcher() {
return _dispatcher_ptr;
}
//! Устанавливает указатель на текущий диспетчер.
static inline sndDispatcher *set_dispatcher(sndDispatcher *p) {
sndDispatcher *old_p = _dispatcher_ptr;
_dispatcher_ptr = p;
return old_p;
}
protected:
//! Обновление установки громкости.
bool update_volume();
bool update_frequency();
private:
//! Звук выключен, если false.
bool _is_enabled;
//! Громкость, диапазон значений - [0, 255].
/**
0 - звук полностью давится
255 - звук играется в полную громкость
*/
uint32 _volume;
//! Громкость в децибелах, диапазон значений - [-10000, 0].
/**
-10000 - звук полностью давится
0 - звук играется в полную громкость
*/
int _volume_dB;
float _frequency_coeff;
//! Пауза.
bool _is_paused;
typedef Std::list<sndSound> sound_list_t;
//! Список активных звуков.
sound_list_t _sounds;
//! Текущий диспетчер.
static sndDispatcher *_dispatcher_ptr;
// Audio::SeekableAudioStream *_audioStream;
};
} // namespace QDEngine
#endif // QDENGINE_SYSTEM_SOUND_SND_DISPATCHER_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 "audio/audiostream.h"
#include "common/debug.h"
#include "qdengine/qdengine.h"
#include "qdengine/system/sound/snd_sound.h"
#include "qdengine/system/sound/wav_sound.h"
namespace QDEngine {
sndSound::~sndSound() {
release_sound_buffer();
}
bool sndSound::create_sound_buffer() {
if (!sound())
return false;
return true;
}
bool sndSound::release_sound_buffer() {
if (!is_stopped())
stop(false);
return true;
}
bool sndSound::play() {
debugC(5, kDebugSound, "sndSound::play(). %s", transCyrillic(_sound->_fname.toString()));
if (!_sound->_audioStream) {
warning("sndSound::play(): audioStream is null for '%s'", transCyrillic(_sound->_fname.toString()));
return false;
}
_flags &= ~SOUND_FLAG_PAUSED;
_sound->_audioStream->rewind();
if (_flags & SOUND_FLAG_LOOPING) {
Audio::AudioStream *audio = new Audio::LoopingAudioStream(_sound->_audioStream, 0, DisposeAfterUse::NO);
g_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType, &_audHandle, audio, -1, _volume, 0, DisposeAfterUse::NO);
} else {
g_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType, &_audHandle, _sound->_audioStream, -1, _volume, 0, DisposeAfterUse::NO);
}
return true;
}
bool sndSound::stop(bool rewind) {
debugC(5, kDebugSound, "sndSound::stop(). this: %p", (void *)this);
g_system->getMixer()->stopHandle(_audHandle);
if (rewind && _sound && _sound->_audioStream)
_sound->_audioStream->seek(0);
_isStopped = true;
return true;
}
void sndSound::pause() {
debugC(5, kDebugSound, "sndSound::pause(). this: %p", (void *)this);
_flags |= SOUND_FLAG_PAUSED;
g_system->getMixer()->pauseHandle(_audHandle, true);
}
void sndSound::resume() {
debugC(5, kDebugSound, "sndSound::resume(). this: %p", (void *)this);
_flags &= ~SOUND_FLAG_PAUSED;
g_system->getMixer()->pauseHandle(_audHandle, false);
}
sndSound::status_t sndSound::status() const {
if (_isStopped)
return SOUND_STOPPED;
if (is_paused())
return sndSound::SOUND_PAUSED;
if (g_system->getMixer()->isSoundHandleActive(_audHandle))
return SOUND_PLAYING;
return SOUND_STOPPED;
}
bool sndSound::is_stopped() const {
switch (status()) {
case SOUND_PLAYING:
case SOUND_PAUSED:
return false;
default:
return true;
}
}
bool sndSound::set_volume(int vol) {
_volume = vol;
g_system->getMixer()->setChannelVolume(_audHandle, vol);
return true;
}
bool sndSound::change_frequency(float coeff) {
if (coeff != 1.0)
warning("STUB: sndSound::change_frequency(%f) '%s'", coeff, transCyrillic(sound()->_fname.toString()));
return true;
}
} // namespace QDEngine

View File

@@ -0,0 +1,131 @@
/* 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 QDENGINE_SYSTEM_SOUND_SND_SOUND_H
#define QDENGINE_SYSTEM_SOUND_SND_SOUND_H
#include "audio/mixer.h"
namespace QDEngine {
class wavSound;
class qdNamedObject;
//! Класс для управления звуками.
class sndHandle {
public:
sndHandle() { };
virtual ~sndHandle() { };
};
//! Базовый класс для звуков.
class sndSound {
public:
explicit sndSound(const wavSound *snd, const sndHandle *h = NULL) : _sound(snd), _handle(h), _flags(0) {}
~sndSound();
//! Состояние звука.
enum status_t {
//! звук не проигрывается
SOUND_STOPPED,
//! звук приостановлен
SOUND_PAUSED,
//! звук пригрывается
SOUND_PLAYING
};
//! Возвращает состояние звука.
status_t status() const;
//! Возвращает указатель на данные звука.
const wavSound *sound() const {
return _sound;
}
//! Возвращает указатель на хэндл звука.
const sndHandle *handle() const {
return _handle;
}
//! Запускает проигрывание звука.
bool play();
//! Останавливает проигрывание звука.
bool stop(bool rewind = true);
//! Ставит звук на паузу.
void pause();
//! Возобновляет проигрывание.
void resume();
//! Возвращает true, если звук на паузе.
bool is_paused() const {
if (_flags & SOUND_FLAG_PAUSED) return true;
else return false;
}
//! Возвращает true, если звук не проигрывается.
bool is_stopped() const;
//! Устанавливает громкость звука, параметр - в децибелах.
/**
Диапазон значений громкости - [-10000, 0]
-10000 - звук совсем не слышен,
0 - громкость самого звука по умолчанию.
*/
bool set_volume(int vol);
bool change_frequency(float coeff = 1.0f);
//! Создает DirectSoundBuffer.
bool create_sound_buffer();
//! Удаляет DirectSoundBuffer.
bool release_sound_buffer();
//! Включает/выключает зацикливание звука.
void toggle_looping() {
_flags ^= SOUND_FLAG_LOOPING;
}
private:
//! Указатель на данные.
const wavSound *_sound;
//! Указатель на хэндл звука.
const sndHandle *_handle;
//! Указатель на DirectSoundBuffer.
//! флаги
enum {
SOUND_FLAG_LOOPING = 0x01,
SOUND_FLAG_PAUSED = 0x02
};
//! флаги
int _flags;
Audio::SoundHandle _audHandle;
byte _volume = 255;
bool _isStopped = false;
};
} // namespace QDEngine
#endif // QDENGINE_SYSTEM_SOUND_SND_SOUND_H

View File

@@ -0,0 +1,69 @@
/* 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/audiostream.h"
#include "audio/decoders/vorbis.h"
#include "audio/decoders/wave.h"
#include "common/debug.h"
#include "common/system.h"
#include "qdengine/qdengine.h"
#include "qdengine/qd_fwd.h"
#include "qdengine/system/sound/wav_sound.h"
#include "qdengine/qdcore/qd_file_manager.h"
namespace QDEngine {
wavSound::wavSound() {}
wavSound::~wavSound() {}
bool wavSound::wav_file_load(const Common::Path &fpath) {
debugC(3, kDebugSound, "[%d] Loading Wav: %s", g_system->getMillis(), transCyrillic(fpath.toString()));
if (fpath.empty()) {
return false;
}
_fname = fpath;
Common::SeekableReadStream *stream;
if (qdFileManager::instance().open_file(&stream, fpath.toString().c_str(), false)) {
if (_fname.baseName().hasSuffixIgnoreCase(".ogg")) {
#ifdef USE_VORBIS
_audioStream = Audio::makeVorbisStream(stream, DisposeAfterUse::YES);
#else
warning("wavSound::wav_file_load(%s): Vorbis support not compiled", fpath.toString().c_str());
return false;
#endif
} else {
_audioStream = Audio::makeWAVStream(stream, DisposeAfterUse::YES);
}
_length = (float)_audioStream->getLength().msecs() / 1000.0;
}
return true;
}
} // namespace QDEngine

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 QDENGINE_SYSTEM_SOUND_WAV_SOUND_H
#define QDENGINE_SYSTEM_SOUND_WAV_SOUND_H
namespace Audio {
class SeekableAudioStream;
}
namespace QDEngine {
//! Звук из WAV файла.
class wavSound {
public:
wavSound();
~wavSound();
//! Returns sound length in seconds
float length() const { return _length; }
bool wav_file_load(const Common::Path &fname);
Audio::SeekableAudioStream *_audioStream = nullptr;
Common::Path _fname;
private:
float _length = 0.0;
};
} // namespace QDEngine
#endif // QDENGINE_SYSTEM_SOUND_WAV_SOUND_H