diff options
Diffstat (limited to 'backends/platform/bada/audio.cpp')
-rw-r--r-- | backends/platform/bada/audio.cpp | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/backends/platform/bada/audio.cpp b/backends/platform/bada/audio.cpp new file mode 100644 index 0000000000..cfa6418e08 --- /dev/null +++ b/backends/platform/bada/audio.cpp @@ -0,0 +1,260 @@ +/* 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. + * + */ + +#include <FSysSettingInfo.h> +#include <FAppAppRegistry.h> + +#include "backends/platform/bada/audio.h" +#include "backends/platform/bada/system.h" + +#define TIMER_INCREMENT 10 +#define TIMER_INTERVAL 40 +#define MIN_TIMER_INTERVAL 10 +#define MAX_TIMER_INTERVAL 160 +#define INIT_LEVEL 3 +#define CONFIG_KEY L"audiovol" + +// sound level pre-sets +const int levels[] = {0, 1, 10, 45, 70, 99}; + +AudioThread::AudioThread() : + _mixer(0), + _timer(0), + _audioOut(0), + _head(0), + _tail(0), + _ready(0), + _interval(TIMER_INTERVAL), + _playing(-1), + _muted(true) { +} + +Audio::MixerImpl *AudioThread::Construct(OSystem *system) { + logEntered(); + + if (IsFailed(Thread::Construct(THREAD_TYPE_EVENT_DRIVEN, + DEFAULT_STACK_SIZE, + THREAD_PRIORITY_HIGH))) { + AppLog("Failed to create AudioThread"); + return NULL; + } + + _mixer = new Audio::MixerImpl(system, 44100); + return _mixer; +} + +AudioThread::~AudioThread() { + logEntered(); +} + +bool AudioThread::isSilentMode() { + bool silentMode; + String key(L"SilentMode"); + Osp::System::SettingInfo::GetValue(key, silentMode); + return silentMode; +} + +void AudioThread::setMute(bool on) { + if (_audioOut && !isSilentMode()) { + _muted = on; + if (on) { + _timer->Cancel(); + } else { + _timer->Start(_interval); + } + } +} + +int AudioThread::setVolume(bool up, bool minMax) { + int level = -1; + int numLevels = sizeof(levels) / sizeof(levels[0]); + + if (_audioOut && !isSilentMode()) { + int volume = _audioOut->GetVolume(); + if (minMax) { + level = up ? numLevels - 1 : 0; + volume = levels[level]; + } else { + // adjust volume to be one of the preset values + for (int i = 0; i < numLevels && level == -1; i++) { + if (volume == levels[i]) { + level = i; + if (up) { + if (i + 1 < numLevels) { + level = i + 1; + } + } else if (i > 0) { + level = i - 1; + } + } + } + + // default to INIT_LEVEL when current not preset value + if (level == -1) { + level = INIT_LEVEL; + } + volume = levels[level]; + } + + _audioOut->SetVolume(volume); + + // remember the chosen setting + AppRegistry *registry = Application::GetInstance()->GetAppRegistry(); + if (registry) { + registry->Set(CONFIG_KEY, volume); + } + } + return level; +} + +bool AudioThread::OnStart(void) { + logEntered(); + + _audioOut = new Osp::Media::AudioOut(); + if (!_audioOut || + IsFailed(_audioOut->Construct(*this))) { + AppLog("Failed to create AudioOut"); + return false; + } + + int sampleRate = _mixer->getOutputRate(); + + // ideally we would update _mixer with GetOptimizedSampleRate here + if (_audioOut->GetOptimizedSampleRate() != sampleRate) { + AppLog("Non optimal sample rate %d", _audioOut->GetOptimizedSampleRate()); + } + + if (IsFailed(_audioOut->Prepare(AUDIO_TYPE_PCM_S16_LE, + AUDIO_CHANNEL_TYPE_STEREO, + sampleRate))) { + AppLog("Failed to prepare AudioOut %d", sampleRate); + return false; + } + + int bufferSize = _audioOut->GetMinBufferSize(); + for (int i = 0; i < NUM_AUDIO_BUFFERS; i++) { + if (IsFailed(_audioBuffer[i].Construct(bufferSize))) { + AppLog("Failed to create audio buffer"); + return false; + } + } + + _timer = new Timer(); + if (!_timer || IsFailed(_timer->Construct(*this))) { + AppLog("Failed to create audio timer"); + return false; + } + + if (IsFailed(_timer->Start(_interval))) { + AppLog("failed to start audio timer"); + return false; + } + + // get the volume from the app-registry + int volume = levels[INIT_LEVEL]; + AppRegistry *registry = Application::GetInstance()->GetAppRegistry(); + if (registry) { + if (E_KEY_NOT_FOUND == registry->Get(CONFIG_KEY, volume)) { + registry->Add(CONFIG_KEY, volume); + volume = levels[INIT_LEVEL]; + } else { + AppLog("Setting volume: %d", volume); + } + } + + _muted = false; + _mixer->setReady(true); + _audioOut->SetVolume(isSilentMode() ? 0 : volume); + _audioOut->Start(); + return true; +} + +void AudioThread::OnStop(void) { + logEntered(); + + _mixer->setReady(false); + + if (_timer) { + if (!_muted) { + _timer->Cancel(); + } + delete _timer; + } + + if (_audioOut) { + _audioOut->Reset(); + delete _audioOut; + } +} + +void AudioThread::OnAudioOutErrorOccurred(Osp::Media::AudioOut &src, result r) { + logEntered(); +} + +void AudioThread::OnAudioOutInterrupted(Osp::Media::AudioOut &src) { + logEntered(); +} + +void AudioThread::OnAudioOutReleased(Osp::Media::AudioOut &src) { + logEntered(); + _audioOut->Start(); +} + +void AudioThread::OnAudioOutBufferEndReached(Osp::Media::AudioOut &src) { + if (_ready > 0) { + _playing = _tail; + _audioOut->WriteBuffer(_audioBuffer[_tail]); + _tail = (_tail + 1) % NUM_AUDIO_BUFFERS; + _ready--; + } else { + // audio buffer empty: decrease timer inverval + _playing = -1; + _interval -= TIMER_INCREMENT; + if (_interval < MIN_TIMER_INTERVAL) { + _interval = MIN_TIMER_INTERVAL; + } + } +} + +void AudioThread::OnTimerExpired(Timer &timer) { + if (_ready < NUM_AUDIO_BUFFERS) { + uint len = _audioBuffer[_head].GetCapacity(); + int samples = _mixer->mixCallback((byte*)_audioBuffer[_head].GetPointer(), len); + if (samples) { + _head = (_head + 1) % NUM_AUDIO_BUFFERS; + _ready++; + } + } else { + // audio buffer full: increase timer inverval + _interval += TIMER_INCREMENT; + if (_interval > MAX_TIMER_INTERVAL) { + _interval = MAX_TIMER_INTERVAL; + } + } + + if (_ready && _playing == -1) { + OnAudioOutBufferEndReached(*_audioOut); + } + + _timer->Start(_interval); +} + |