PageRenderTime 58ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/engines/wintermute/base/sound/base_sound_manager.cpp

http://github.com/scummvm/scummvm
C++ | 298 lines | 179 code | 60 blank | 59 comment | 24 complexity | 0cd2528cfac381c0af8cca1eb365ebc9 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, GPL-2.0
  1. /* ScummVM - Graphic Adventure Engine
  2. *
  3. * ScummVM is the legal property of its developers, whose names
  4. * are too numerous to list here. Please refer to the COPYRIGHT
  5. * file distributed with this source distribution.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20. *
  21. */
  22. /*
  23. * This file is based on WME Lite.
  24. * http://dead-code.org/redir.php?target=wmelite
  25. * Copyright (c) 2011 Jan Nedoma
  26. */
  27. #include "engines/wintermute/base/sound/base_sound_manager.h"
  28. #include "engines/wintermute/base/base_engine.h"
  29. #include "engines/wintermute/utils/path_util.h"
  30. #include "engines/wintermute/utils/string_util.h"
  31. #include "engines/wintermute/base/base_file_manager.h"
  32. #include "engines/wintermute/base/gfx/base_renderer.h"
  33. #include "engines/wintermute/base/sound/base_sound_buffer.h"
  34. #include "engines/wintermute/wintermute.h"
  35. #include "common/config-manager.h"
  36. #include "audio/mixer.h"
  37. namespace Wintermute {
  38. //////////////////////////////////////////////////////////////////////
  39. // Construction/Destruction
  40. //////////////////////////////////////////////////////////////////////
  41. //IMPLEMENT_PERSISTENT(BaseSoundMgr, true);
  42. //////////////////////////////////////////////////////////////////////////
  43. BaseSoundMgr::BaseSoundMgr(BaseGame *inGame) : BaseClass(inGame) {
  44. _soundAvailable = false;
  45. _volumeMaster = 255;
  46. _volumeMasterPercent = 100;
  47. }
  48. //////////////////////////////////////////////////////////////////////////
  49. BaseSoundMgr::~BaseSoundMgr() {
  50. saveSettings();
  51. cleanup();
  52. }
  53. //////////////////////////////////////////////////////////////////////////
  54. bool BaseSoundMgr::cleanup() {
  55. for (uint32 i = 0; i < _sounds.size(); i++) {
  56. delete _sounds[i];
  57. }
  58. _sounds.clear();
  59. return STATUS_OK;
  60. }
  61. //////////////////////////////////////////////////////////////////////////
  62. void BaseSoundMgr::saveSettings() {
  63. if (_soundAvailable) {
  64. ConfMan.setInt("master_volume_percent", _volumeMasterPercent);
  65. }
  66. }
  67. //////////////////////////////////////////////////////////////////////////
  68. bool BaseSoundMgr::initialize() {
  69. _soundAvailable = false;
  70. if (!g_system->getMixer()->isReady()) {
  71. return STATUS_FAILED;
  72. }
  73. byte volumeMasterPercent = (ConfMan.hasKey("master_volume_percent") ? ConfMan.getInt("master_volume_percent") : 100);
  74. setMasterVolumePercent(volumeMasterPercent);
  75. _soundAvailable = true;
  76. g_engine->syncSoundSettings();
  77. return STATUS_OK;
  78. }
  79. //////////////////////////////////////////////////////////////////////////
  80. BaseSoundBuffer *BaseSoundMgr::addSound(const Common::String &filename, Audio::Mixer::SoundType type, bool streamed) {
  81. if (!_soundAvailable) {
  82. return nullptr;
  83. }
  84. if (filename.empty()) {
  85. // At least one game, Bickadoodle, calls playSound with an empty filename, see #6594
  86. BaseEngine::LOG(0, "addSound called with empty filename");
  87. }
  88. BaseSoundBuffer *sound;
  89. Common::String useFilename = filename;
  90. useFilename.toLowercase();
  91. // try to switch WAV to OGG file (if available)
  92. if (useFilename.hasSuffix(".wav")) {
  93. Common::String oggFilename = useFilename;
  94. oggFilename.erase(oggFilename.size() - 4);
  95. oggFilename = oggFilename + ".ogg";
  96. if (BaseFileManager::getEngineInstance()->hasFile(oggFilename)) {
  97. useFilename = oggFilename;
  98. }
  99. }
  100. sound = new BaseSoundBuffer(_gameRef);
  101. if (!sound) {
  102. return nullptr;
  103. }
  104. sound->setStreaming(streamed);
  105. sound->setType(type);
  106. bool res = sound->loadFromFile(useFilename);
  107. if (DID_FAIL(res)) {
  108. BaseEngine::LOG(res, "Error loading sound '%s'", useFilename.c_str());
  109. delete sound;
  110. return nullptr;
  111. }
  112. // Make sure the master-volume is applied to the sound.
  113. sound->updateVolume();
  114. // register sound
  115. _sounds.push_back(sound);
  116. return sound;
  117. return nullptr;
  118. }
  119. //////////////////////////////////////////////////////////////////////////
  120. bool BaseSoundMgr::addSound(BaseSoundBuffer *sound, Audio::Mixer::SoundType type) {
  121. if (!sound) {
  122. return STATUS_FAILED;
  123. }
  124. // Make sure the master-volume is applied to the sound.
  125. sound->updateVolume();
  126. // register sound
  127. _sounds.push_back(sound);
  128. return STATUS_OK;
  129. }
  130. //////////////////////////////////////////////////////////////////////////
  131. bool BaseSoundMgr::removeSound(BaseSoundBuffer *sound) {
  132. for (uint32 i = 0; i < _sounds.size(); i++) {
  133. if (_sounds[i] == sound) {
  134. delete _sounds[i];
  135. _sounds.remove_at(i);
  136. return STATUS_OK;
  137. }
  138. }
  139. return STATUS_FAILED;
  140. }
  141. //////////////////////////////////////////////////////////////////////////
  142. bool BaseSoundMgr::setVolume(Audio::Mixer::SoundType type, int volume) {
  143. if (!_soundAvailable) {
  144. return STATUS_OK;
  145. }
  146. switch (type) {
  147. case Audio::Mixer::kSFXSoundType:
  148. ConfMan.setInt("sfx_volume", volume);
  149. break;
  150. case Audio::Mixer::kSpeechSoundType:
  151. ConfMan.setInt("speech_volume", volume);
  152. break;
  153. case Audio::Mixer::kMusicSoundType:
  154. ConfMan.setInt("music_volume", volume);
  155. break;
  156. case Audio::Mixer::kPlainSoundType:
  157. error("Plain sound type shouldn't be used in WME");
  158. break;
  159. default:
  160. break;
  161. }
  162. g_engine->syncSoundSettings();
  163. return STATUS_OK;
  164. }
  165. //////////////////////////////////////////////////////////////////////////
  166. bool BaseSoundMgr::setVolumePercent(Audio::Mixer::SoundType type, byte percent) {
  167. return setVolume(type, percent * 255 / 100);
  168. }
  169. //////////////////////////////////////////////////////////////////////////
  170. byte BaseSoundMgr::getVolumePercent(Audio::Mixer::SoundType type) {
  171. int volume = 0;
  172. switch (type) {
  173. case Audio::Mixer::kSFXSoundType:
  174. case Audio::Mixer::kSpeechSoundType:
  175. case Audio::Mixer::kMusicSoundType:
  176. volume = g_system->getMixer()->getVolumeForSoundType(type);
  177. break;
  178. default:
  179. error("Sound-type not set");
  180. break;
  181. }
  182. return (byte)(volume * 100 / 255);
  183. }
  184. //////////////////////////////////////////////////////////////////////////
  185. bool BaseSoundMgr::setMasterVolume(byte value) {
  186. // This function intentionally doesn't touch _volumeMasterPercent,
  187. // as that variable keeps track of what the game actually wanted,
  188. // and this gives a close approximation, while letting the game
  189. // be none the wiser about round-off-errors. This function should thus
  190. // ONLY be called by setMasterVolumePercent.
  191. _volumeMaster = value;
  192. for (uint32 i = 0; i < _sounds.size(); i++) {
  193. _sounds[i]->updateVolume();
  194. }
  195. return STATUS_OK;
  196. }
  197. //////////////////////////////////////////////////////////////////////////
  198. bool BaseSoundMgr::setMasterVolumePercent(byte percent) {
  199. _volumeMasterPercent = percent;
  200. setMasterVolume((int)ceil(percent * 255.0 / 100.0));
  201. return STATUS_OK;
  202. }
  203. //////////////////////////////////////////////////////////////////////////
  204. byte BaseSoundMgr::getMasterVolumePercent() {
  205. return _volumeMasterPercent;
  206. }
  207. //////////////////////////////////////////////////////////////////////////
  208. byte BaseSoundMgr::getMasterVolume() {
  209. return (byte)_volumeMaster;
  210. }
  211. //////////////////////////////////////////////////////////////////////////
  212. bool BaseSoundMgr::pauseAll(bool includingMusic) {
  213. for (uint32 i = 0; i < _sounds.size(); i++) {
  214. if (_sounds[i]->isPlaying() && (_sounds[i]->getType() != Audio::Mixer::kMusicSoundType || includingMusic)) {
  215. _sounds[i]->pause();
  216. _sounds[i]->setFreezePaused(true);
  217. }
  218. }
  219. return STATUS_OK;
  220. }
  221. //////////////////////////////////////////////////////////////////////////
  222. bool BaseSoundMgr::resumeAll() {
  223. for (uint32 i = 0; i < _sounds.size(); i++) {
  224. if (_sounds[i]->isFreezePaused()) {
  225. _sounds[i]->resume();
  226. _sounds[i]->setFreezePaused(false);
  227. }
  228. }
  229. return STATUS_OK;
  230. }
  231. //////////////////////////////////////////////////////////////////////////
  232. float BaseSoundMgr::posToPan(int x, int y) {
  233. float relPos = (float)x / ((float)BaseEngine::getRenderer()->getWidth());
  234. float minPan = -0.7f;
  235. float maxPan = 0.7f;
  236. return minPan + relPos * (maxPan - minPan);
  237. }
  238. } // End of namespace Wintermute