Skip to content

DRASCULA: Add text-to-speech (TTS)#6526

Merged
criezy merged 4 commits intoscummvm:masterfrom
ellm135:master
May 14, 2025
Merged

DRASCULA: Add text-to-speech (TTS)#6526
criezy merged 4 commits intoscummvm:masterfrom
ellm135:master

Conversation

@ellm135
Copy link
Contributor

@ellm135 ellm135 commented Mar 31, 2025

Adds a toggle for text-to-speech under the game options.
Adds text-to-speech for the following:

  • Intro line describing the game's setting
  • Dialogue options
  • Menu and menu bar actions/verbs
  • Names of interactable objects when hovered over
  • Messages related to save slots in the original save/load screen
  • Lines in the drunkard's cutscene explaining the history of Von Braun
  • Subtitles enabled/disabled messages
  • Exit confirmation message
  • Verb selection with F1 to F6 keys
  • Volume controls menu

@bluegr bluegr added the GSoC Part of a Google Summer of Code project label Apr 1, 2025
Copy link
Member

@criezy criezy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very good start.

I made a couple of comments.
There are also a few more places that I think could benefit from TTS in this game:

  • To help visually impaired players we could speak the selected verb when switching between verbs using the F1 to F6 keys (even though the text is not shown on screen).
  • We could add TTS on the options dialog shown with F9.

if (ConfMan.getBool("tts_enabled") && ttsMan != nullptr && phrase1 != _previousSaid) {
_previousSaid = phrase1;
ttsMan->say(phrase1);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also comment on the reason why you are tracking the last spoken sentence with _previousSaid (here and in other places) rather than use Common::TextToSpeechManager::INTERRUPT_NO_REPEAT?
There is a slight difference between the two behaviours, but I am not sure it is intentional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue I had with using only Common::TextToSpeechManager::INTERRUPT_NO_REPEAT was that, because these ttsMan->say(...) calls were inside loops, once the initial speech finished, the text-to-speech manager would see that there was currently no speech and repeat it again. This resulted in endless looping of the same speech for as long as the user was hovered over an option or object, for example. I thought that this endless looping was unintuitive, and I could not always find a place where the text to be spoken was not in a loop, so I used this method of tracking the previous sentence instead. To still allow for appropriate repeat requests, I tried to clear or override _previousSaid when possible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the explanation. It makes sense. I think we indeed do not want to have the text repeated again and again in a loop when the cursor stays on that text. I will take another look at the changes with that in mind in a few days.
And adding a comment to explain this could be useful since it confused both myself and @sev- .

@sev-
Copy link
Member

sev- commented Apr 27, 2025

@ellm135 any updates?

Copy link
Member

@sev- sev- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added my review comments

color_abc(kColorLightGreen);
if (_hasName && !_menuScreen)
if (_hasName && !_menuScreen) {
if (_previousSaid != textName) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the same problem as in another, more recent PR. You need to check here that TTS is pronouncing text still, and if it is not saying, then still say the phrase. Otherwise, if two consequent request have the same phrase, e.g. when a player clicks on the same item twice in a row, the second phrase will be not pronounced.


Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
if (ConfMan.getBool("tts_enabled") && ttsMan != nullptr) {
ttsMan->say(_textsys[1]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better replace 1 with something like VERB_LOOK or similarly named constant

Copy link
Member

@criezy criezy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just made one small suggestion. But otherwise it looks good to me now.

Comment on lines +1168 to +1170
// _previousSaid is used to prevent the TTS from looping when sayText is called inside a loop
// (Once the text ends, it will see that there is currently no speech and speak the same text again)
// _previousSaid is cleared when appropriate to allow for repeat requests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// _previousSaid is used to prevent the TTS from looping when sayText is called inside a loop
// (Once the text ends, it will see that there is currently no speech and speak the same text again)
// _previousSaid is cleared when appropriate to allow for repeat requests
// _previousSaid is used to prevent the TTS from looping when sayText is called inside a loop,
// for example when the cursor stays on a verb icon. Without it when the text ends it would speak
// the same text again.
// _previousSaid is cleared when appropriate to allow for repeat requests

Suggestion to given an example to clarify what "called inside a loop" means.

@criezy
Copy link
Member

criezy commented May 14, 2025

Thank you. It looks all good now.

@criezy criezy merged commit 26f1b8d into scummvm:master May 14, 2025
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

GSoC Part of a Google Summer of Code project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants