/* 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 2 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #ifdef _WIN32_WCE // Disable symbol overrides so that we can use system headers. #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "common/config-manager.h" #include "backends/platform/wince/wince-sdl.h" #include "backends/mixer/wincesdl/wincesdl-mixer.h" #include "common/system.h" #include "common/textconsole.h" #ifdef USE_VORBIS #ifndef USE_TREMOR #include #else #ifdef USE_TREMOLO #include #else #include #endif #endif #endif #define SAMPLES_PER_SEC_OLD 11025 #define SAMPLES_PER_SEC_NEW 22050 WINCESdlMixerManager::WINCESdlMixerManager() { } WINCESdlMixerManager::~WINCESdlMixerManager() { } void WINCESdlMixerManager::init() { SDL_AudioSpec desired; int thread_priority; uint32 sampleRate = compute_sample_rate(); if (sampleRate == 0) warning("OSystem_WINCE3::setupMixer called with sample rate 0 - audio will not work"); else if (_mixer && _mixer->getOutputRate() == sampleRate) { debug(1, "Skipping sound mixer re-init: samplerate is good"); return; } memset(&desired, 0, sizeof(desired)); desired.freq = sampleRate; desired.format = AUDIO_S16SYS; desired.channels = 2; desired.samples = 128; desired.callback = private_sound_proc; desired.userdata = this; // Create the mixer instance if (_mixer == 0) _mixer = new Audio::MixerImpl(g_system, sampleRate); // Add sound thread priority if (!ConfMan.hasKey("sound_thread_priority")) thread_priority = THREAD_PRIORITY_NORMAL; else thread_priority = ConfMan.getInt("sound_thread_priority"); desired.thread_priority = thread_priority; SDL_CloseAudio(); if (SDL_OpenAudio(&desired, NULL) != 0) { warning("Could not open audio device: %s", SDL_GetError()); _mixer->setReady(false); } else { debug(1, "Sound opened OK, mixing at %d Hz", sampleRate); // Re-create mixer to match the output rate int vol1 = _mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType); int vol2 = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType); int vol3 = _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType); int vol4 = _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType); delete _mixer; _mixer = new Audio::MixerImpl(g_system, sampleRate); _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, vol1); _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol2); _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol3); _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, vol4); _mixer->setReady(true); SDL_PauseAudio(0); } } void WINCESdlMixerManager::private_sound_proc(void *param, byte *buf, int len) { WINCESdlMixerManager *this_ = (WINCESdlMixerManager *)param; assert(this_); if (this_->_mixer) this_->_mixer->mixCallback(buf, len); if (!OSystem_WINCE3::_soundMaster) memset(buf, 0, len); } uint32 WINCESdlMixerManager::compute_sample_rate() { uint32 sampleRate; // Force at least medium quality FM synthesis for FOTAQ Common::String gameid(ConfMan.get("gameid")); if (gameid == "queen") { if (!((ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) || (ConfMan.hasKey("FM_medium_quality") && ConfMan.getBool("FM_medium_quality")))) { ConfMan.setBool("FM_medium_quality", true); ConfMan.flushToDisk(); } } else { if (!ConfMan.hasKey("FM_high_quality") && !ConfMan.hasKey("FM_medium_quality")) { ConfMan.setBool("FM_high_quality", true); ConfMan.flushToDisk(); } } // See if the output frequency is forced by the game if (gameid == "ft" || gameid == "dig" || gameid == "comi" || gameid == "queen" || gameid == "sword" || gameid == "agi") sampleRate = SAMPLES_PER_SEC_NEW; else { if (ConfMan.hasKey("high_sample_rate") && !ConfMan.getBool("high_sample_rate")) sampleRate = SAMPLES_PER_SEC_OLD; else sampleRate = SAMPLES_PER_SEC_NEW; } #ifdef USE_VORBIS // Modify the sample rate on the fly if OGG is involved if (sampleRate == SAMPLES_PER_SEC_OLD) if (checkOggHighSampleRate()) sampleRate = SAMPLES_PER_SEC_NEW; #endif return sampleRate; } #ifdef USE_VORBIS bool WINCESdlMixerManager::checkOggHighSampleRate() { char trackFile[255]; FILE *testFile; OggVorbis_File *test_ov_file = new OggVorbis_File; // FIXME: The following sprintf assumes that "path" is always // terminated by a path separator. This is *not* true in general. // This code really should check for the path separator, or even // better, use the FSNode API. sprintf(trackFile, "%sTrack1.ogg", ConfMan.get("path").c_str()); // Check if we have an OGG audio track testFile = fopen(trackFile, "rb"); if (testFile) { if (!ov_open(testFile, test_ov_file, NULL, 0)) { bool highSampleRate = (ov_info(test_ov_file, -1)->rate == 22050); ov_clear(test_ov_file); delete test_ov_file; return highSampleRate; } } // Do not test for OGG samples - too big and too slow anyway :) delete test_ov_file; return false; } #endif #endif