aboutsummaryrefslogtreecommitdiff
path: root/backends/text-to-speech
diff options
context:
space:
mode:
authorThierry Crozat2019-07-31 22:26:57 +0100
committerFilippos Karapetis2019-09-01 22:47:55 +0300
commit9ca2602e82429cf3b210f363e0a478fd876a13b5 (patch)
treee9f45357db4dd2c157c242aa48def633ae7d914f /backends/text-to-speech
parent1694b930e652cd2cc549988f9960604a35e36c25 (diff)
downloadscummvm-rg350-9ca2602e82429cf3b210f363e0a478fd876a13b5.tar.gz
scummvm-rg350-9ca2602e82429cf3b210f363e0a478fd876a13b5.tar.bz2
scummvm-rg350-9ca2602e82429cf3b210f363e0a478fd876a13b5.zip
TTS: Implement speech queueing on macOS
Diffstat (limited to 'backends/text-to-speech')
-rw-r--r--backends/text-to-speech/macosx/macosx-text-to-speech.h13
-rw-r--r--backends/text-to-speech/macosx/macosx-text-to-speech.mm54
2 files changed, 60 insertions, 7 deletions
diff --git a/backends/text-to-speech/macosx/macosx-text-to-speech.h b/backends/text-to-speech/macosx/macosx-text-to-speech.h
index fed0c05458..7c33a3b0c9 100644
--- a/backends/text-to-speech/macosx/macosx-text-to-speech.h
+++ b/backends/text-to-speech/macosx/macosx-text-to-speech.h
@@ -28,14 +28,14 @@
#if defined(USE_MACOSX_TTS)
#include "common/text-to-speech.h"
-#include "common/str.h"
+#include "common/queue.h"
class MacOSXTextToSpeechManager : public Common::TextToSpeechManager {
public:
MacOSXTextToSpeechManager();
virtual ~MacOSXTextToSpeechManager();
- virtual bool say(Common::String str, Common::String charset = "");
+ virtual bool say(Common::String str, Action action, Common::String charset = "");
virtual bool stop();
virtual bool pause();
@@ -57,8 +57,17 @@ public:
virtual void freeVoiceData(void *data);
+ bool startNextSpeech();
+
private:
virtual void updateVoices();
+
+ struct SpeechText {
+ Common::String text;
+ Common::String encoding;
+ SpeechText(const Common::String& txt, const Common::String& enc) : text(txt), encoding(enc) {}
+ };
+ Common::Queue<SpeechText> _messageQueue;
};
#endif
diff --git a/backends/text-to-speech/macosx/macosx-text-to-speech.mm b/backends/text-to-speech/macosx/macosx-text-to-speech.mm
index 281d92f926..9f668414b6 100644
--- a/backends/text-to-speech/macosx/macosx-text-to-speech.mm
+++ b/backends/text-to-speech/macosx/macosx-text-to-speech.mm
@@ -31,10 +31,32 @@
#include <Foundation/NSString.h>
#include <CoreFoundation/CFString.h>
-NSSpeechSynthesizer* synthesizer;
+@interface MacOSXTextToSpeechManagerDelegate : NSObject<NSSpeechSynthesizerDelegate> {
+ MacOSXTextToSpeechManager *_ttsManager;
+}
+- (id)initWithManager:(MacOSXTextToSpeechManager*)ttsManager;
+- (void)speechSynthesizer:(NSSpeechSynthesizer *)sender didFinishSpeaking:(BOOL)finishedSpeaking;
+@end
+
+@implementation MacOSXTextToSpeechManagerDelegate
+- (id)initWithManager:(MacOSXTextToSpeechManager*)ttsManager {
+ self = [super init];
+ _ttsManager = ttsManager;
+ return self;
+}
+
+- (void)speechSynthesizer:(NSSpeechSynthesizer *)sender didFinishSpeaking:(BOOL)finishedSpeaking {
+ _ttsManager->startNextSpeech();
+}
+@end
+
+NSSpeechSynthesizer *synthesizer;
+MacOSXTextToSpeechManagerDelegate *synthesizerDelegate;
MacOSXTextToSpeechManager::MacOSXTextToSpeechManager() : Common::TextToSpeechManager() {
synthesizer = [[NSSpeechSynthesizer alloc] init];
+ synthesizerDelegate = [[MacOSXTextToSpeechManagerDelegate alloc] initWithManager:this];
+ [synthesizer setDelegate:synthesizerDelegate];
#ifdef USE_TRANSLATION
setLanguage(TransMan.getCurrentLanguage());
@@ -45,30 +67,52 @@ MacOSXTextToSpeechManager::MacOSXTextToSpeechManager() : Common::TextToSpeechMan
MacOSXTextToSpeechManager::~MacOSXTextToSpeechManager() {
[synthesizer release];
+ [synthesizerDelegate release];
}
-bool MacOSXTextToSpeechManager::say(Common::String text, Common::String encoding) {
+bool MacOSXTextToSpeechManager::say(Common::String text, Action action, Common::String encoding) {
+ if ([synthesizer isSpeaking]) {
+ if (action == DROP)
+ return true;
+ else if (action == INTERRUPT) {
+ _messageQueue.clear();
+ // Should we use NSSpeechImmediateBoundary, or even NSSpeechSentenceBoundary?
+ [synthesizer stopSpeakingAtBoundary:NSSpeechWordBoundary];
+ }
+ }
+
if (encoding.empty()) {
#ifdef USE_TRANSLATION
encoding = TransMan.getCurrentCharset();
#endif
}
+ _messageQueue.push(SpeechText(text, encoding));
+ if (![synthesizer isSpeaking])
+ startNextSpeech();
+ return true;
+}
+
+bool MacOSXTextToSpeechManager::startNextSpeech() {
+ if (_messageQueue.empty())
+ return false;
+ SpeechText text = _messageQueue.pop();
// Get current encoding
CFStringEncoding stringEncoding = kCFStringEncodingASCII;
- if (!encoding.empty()) {
- CFStringRef encStr = CFStringCreateWithCString(NULL, encoding.c_str(), kCFStringEncodingASCII);
+ if (!text.encoding.empty()) {
+ CFStringRef encStr = CFStringCreateWithCString(NULL, text.encoding.c_str(), kCFStringEncodingASCII);
stringEncoding = CFStringConvertIANACharSetNameToEncoding(encStr);
CFRelease(encStr);
}
- CFStringRef textNSString = CFStringCreateWithCString(NULL, text.c_str(), stringEncoding);
+ CFStringRef textNSString = CFStringCreateWithCString(NULL, text.text.c_str(), stringEncoding);
bool status = [synthesizer startSpeakingString:(NSString *)textNSString];
CFRelease(textNSString);
return status;
}
bool MacOSXTextToSpeechManager::stop() {
+ _messageQueue.clear();
// Should we use NSSpeechImmediateBoundary, or even NSSpeechSentenceBoundary?
[synthesizer stopSpeakingAtBoundary:NSSpeechWordBoundary];
return true;