scummvm/engines/glk/speech.cpp

209 lines
6.1 KiB
C++
Raw Normal View History

2020-06-21 20:02:09 +00:00
/* 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.
2020-06-21 20:02:09 +00:00
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
2020-06-21 20:02:09 +00:00
* 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/>.
2020-06-21 20:02:09 +00:00
*
*/
#include "glk/speech.h"
#include "common/debug.h"
#include "glk/glk.h"
2020-06-21 20:02:09 +00:00
#if defined(USE_TTS)
#include "common/config-manager.h"
#include "common/system.h"
#endif
namespace Glk {
SpeechManager *SpeechManager::_instance = nullptr;
SpeechManager* SpeechManager::getSpeechManagerInstance() {
#if defined(USE_TTS)
if (!_instance)
_instance = new SpeechManager();
++_instance->_refCount;
return _instance;
#else
return nullptr;
#endif
}
void SpeechManager::releaseSpeechManagerInstance() {
if (--_refCount == 0) {
_instance = nullptr;
delete this;
}
}
2020-06-21 23:17:01 +00:00
void SpeechManager::syncSoundSettings() {
#if defined(USE_TTS)
debugC(kDebugSpeech, "SpeechManager::syncSoundSettings");
if (_instance && _instance->_ttsMan) {
int volume = (ConfMan.getInt("speech_volume") * 100) / 256;
if (ConfMan.hasKey("mute") && ConfMan.getBool("mute"))
volume = 0;
debugC(kDebugSpeech, "Set speech volume to %d", volume);
_instance->_ttsMan->setVolume(volume);
}
#endif
}
SpeechManager::SpeechManager() :
_refCount(0)
2020-06-21 20:02:09 +00:00
#if defined(USE_TTS)
, _ttsMan(nullptr), _lastSpeechSource(nullptr)
#endif
{
#if defined(USE_TTS)
debugC(kDebugSpeech, "Initialize Glk::SpeechManager");
2020-06-21 20:02:09 +00:00
if (_ttsMan != nullptr)
return;
_ttsMan = g_system->getTextToSpeechManager();
if (_ttsMan != nullptr) {
// Language
_ttsMan->setLanguage(ConfMan.get("language"));
// Volume
int volume = (ConfMan.getInt("speech_volume") * 100) / 256;
2020-06-21 23:17:01 +00:00
if (ConfMan.hasKey("mute") && ConfMan.getBool("mute"))
volume = 0;
_ttsMan->setVolume(volume);
2020-06-21 20:02:09 +00:00
// Voice
unsigned voice;
if(ConfMan.hasKey("tts_voice")) {
voice = ConfMan.getInt("tts_voice");
if (voice >= _ttsMan->getVoicesArray().size())
voice = _ttsMan->getDefaultVoice();
} else
voice = _ttsMan->getDefaultVoice();
_ttsMan->setVoice(voice);
} else
debugC(kDebugSpeech, "Text to Speech is not available");
#endif
}
SpeechManager::~SpeechManager() {
#if defined(USE_TTS)
debugC(kDebugSpeech, "Destroy Glk::SpeechManager");
2020-06-21 20:02:09 +00:00
#endif
}
void SpeechManager::speak(const Common::U32String &text, Speech *speechSource) {
2020-06-21 20:02:09 +00:00
#if defined(USE_TTS)
if (_ttsMan != nullptr) {
// If the previous speech is from a different source, interrupt it.
// Otherwise queeue the speech.
Common::TextToSpeechManager::Action speechAction = Common::TextToSpeechManager::QUEUE;
if (speechSource != _lastSpeechSource) {
debugC(kDebugSpeech, "Changing speack text source.");
// Should we interrupt the text from the other source?
// Just queueing the text seems to provide a better experience.
//speechAction = Common::TextToSpeechManager::INTERRUPT;
_lastSpeechSource = speechSource;
}
//debugC(kDebugSpeech, "Speaking: \"%s\"", text.encode().c_str());
_ttsMan->say(text, speechAction);
2020-06-21 20:02:09 +00:00
}
#endif
}
void SpeechManager::stopSpeech(Speech *speechSource) {
2020-06-21 20:02:09 +00:00
#if defined(USE_TTS)
debugC(kDebugSpeech, "SpeechManager::stopSpeech()");
// Should we only interrupt the speech if it is from the given speech source.
// If we do that we probably want to change speak to interrupt the speech when
// called with a different speech source as the current one.
if (_ttsMan != nullptr)
2020-06-21 20:02:09 +00:00
_ttsMan->stop();
#endif
}
Speech::Speech() : _speechManager(nullptr) {
}
Speech::~Speech() {
if (_speechManager) {
warning("Unbalanced calls to gli_initialize_tts and gli_free_tts");
_speechManager->releaseSpeechManagerInstance();
}
}
void Speech::gli_initialize_tts(void) {
debugC(kDebugSpeech, "gli_initialize_tts");
if (!_speechManager)
_speechManager = SpeechManager::getSpeechManagerInstance();
}
void Speech::gli_tts_flush(void) {
debugC(kDebugSpeech, "gli_tts_flush");
if (_speechManager && !_speechBuffer.empty())
_speechManager->speak(_speechBuffer, this);
_speechBuffer.clear();
}
void Speech::gli_tts_purge(void) {
debugC(kDebugSpeech, "gli_tts_purge");
if (_speechManager) {
_speechBuffer.clear();
_speechManager->stopSpeech(this);
}
}
void Speech::gli_tts_speak(const uint32 *buf, size_t len) {
debugC(1, kDebugSpeech, "gli_tts_speak(const uint32 *, size_t)");
if (_speechManager) {
2020-07-07 02:05:34 +00:00
for (uint i = 0 ; i < len ; ++i, ++buf) {
// Should we automatically flush on new lines without waiting for the call to gli_tts_flush?
// Should we also flush on '.', '?', and '!'?
//if (*buf == '\n') {
// debugC(1, kDebugSpeech, "Flushing SpeechManager buffer on new line");
// gli_tts_flush();
//} else {
_speechBuffer += *buf;
//}
}
//debugC(1, kDebugSpeech, "SpeechManager buffer: %s", _speechBuffer.encode().c_str());
}
}
void Speech::gli_tts_speak(const char *buf, size_t len) {
debugC(1, kDebugSpeech, "gli_tts_speak(const char *, size_t)");
if (_speechManager) {
2020-07-07 02:05:34 +00:00
for (uint i = 0 ; i < len ; ++i, ++buf) {
// Should we automatically flush on new lines without waiting for the call to gli_tts_flush?
// Should we also flush on '.', '?', and '!'?
//if (*buf == '\n') {
// debugC(1, kDebugSpeech, "Flushing SpeechManager buffer on new line");
// gli_tts_flush();
//} else {
_speechBuffer += (uint32)*buf;
//}
}
//debugC(1, kDebugSpeech, "SpeechManager buffer: %s", _speechBuffer.encode().c_str());
}
}
2020-06-21 20:02:09 +00:00
void Speech::gli_free_tts(void) {
debugC(kDebugSpeech, "gli_free_tts");
if (_speechManager) {
_speechManager->releaseSpeechManagerInstance();
_speechManager = nullptr;
2020-06-21 20:02:09 +00:00
}
}
} // End of namespace Glk