Skip to content

Add voice profiles - #111

Open
aaron-gh wants to merge 19 commits into
trypsynth:masterfrom
aaron-gh:voice-profiles
Open

aaron-gh wants to merge 19 commits into
trypsynth:masterfrom
aaron-gh:voice-profiles

Conversation

@aaron-gh

@aaron-gh aaron-gh commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

A voice profile is a set of speech settings that you can switch to at once: a speech engine, language, voice, volume, rate and pitch, and Send long text a sentence at a time. For example, one profile can use a slower rate for long text while the usual settings stay fast. Profiles are added in Text-to-speech > Voice profiles. When a language is chosen, the voice list shows only the engine's voices in that language.

Backtalk default is always there, and is the existing text-to-speech settings, so nothing changes until you add a profile and switch to it.

Switching

  • The Voice profile reading control replaces Speech engine, and keeps its setting, so it is in the reading controls for anyone who had added Speech engine. It goes through Backtalk default and then the profiles in the order of the Voice profiles screen. With no profiles, it says "No voice profiles".
  • Voice profile in use on the Voice profiles screen.
  • A Voice profile item in the Backtalk menu, off by default and shown only once a profile exists. It lists the profiles and says which is in use.
  • Choose voice profile, Previous voice profile and Next voice profile actions for gestures and keyboard shortcuts. All are unassigned by default.

Behaviour

While a profile is in use, changing the speech rate or pitch with gestures or the reading controls changes that profile only. All speech uses the profile's engine and voice, so Backtalk doesn't switch language or dialect, and the Spoken language reading control and menu item are hidden. If Spoken language is still the selected reading control, swiping up or down says "Spoken language unavailable while using a voice profile".

The Voice profiles screen can reorder profiles by dragging, or with Move up and Move down actions, which say which profile it moved above or below. Rename and Delete are actions too, and a long press shows them. The Text-to-speech and Voice profiles screens show which profile is in use, and update when it is switched by a gesture, keyboard shortcut or the Backtalk menu.

A profile's name can't be blank, can't match another profile's name or Backtalk default (ignoring case and spaces), and is cut at 100 characters. If a damaged setting, such as one restored from a backup, leaves a blank or duplicate name or a profile listed twice, the profile gets the first unused "Voice profile N" name and is listed once. Other damaged settings give their defaults instead of crashing, and rate, pitch and volume are kept to the ranges that can be set.

Switching to a profile on another engine, then back before that engine has started, stays on the engine in use. If a profile's voice can't be set, its language is used, then the engine's default voice, so it never keeps another profile's voice. A voice that isn't installed is looked for once per engine, not on every utterance. Changing a profile's engine saves the engine, language and voice together, so the profile switches engines once.

FailoverTextToSpeech reads the profile in its own preference listener, like the language switches, so speaking doesn't read settings.

Limitations

  • No language or dialect switching under a profile.
  • Announce keyboard keys faster doesn't prepare keys while a profile is in use, because prepared speech is kept by language, not by voice. Speech prepared before switching is stopped, and keys are prepared again once Backtalk default is back.
  • Braille display commands can't switch profiles: they are fixed chords, not mapped by the user.

Parts

  • VoiceProfiles (utils): storage, names, order and the profile in use.
  • VoiceProfileNames (talkback): names with Backtalk default's and numbered names from resources, used by the service, reading control and menu.
  • VoiceProfilesFragment and VoiceProfileFragment: the list and one profile's settings.
  • FailoverTextToSpeech: engine, voice, language and sentence sending from the profile in use; prepared speech left alone under a profile; a pending engine switch cancelled when switching back.
  • SelectorController, SpeechRateAndPitchActor, LanguageActor: the reading control, rate and pitch per profile, and hiding Spoken language.
  • VoiceProfileMenuProcessor, gesture and keyboard shortcut actions.
  • The new strings have tools:ignore="MissingTranslation", so that CI lint passes before they are translated. The two Czech strings for Speech engine are removed, since the English ones are gone.
  • differences.md has a Voice profiles section in place of Speech engine reading control.

Testing

  • The new VoiceProfilesTest covers:
    • storage and order;
    • ids that are never reused;
    • deleting the profile in use;
    • wrapping through Backtalk default;
    • damaged settings, duplicate ids, and blank, duplicate and long names;
    • which settings count as profile settings;
    • that a profile never switches language.
  • Tested on a Galaxy Z Fold7, and on an Android 16 emulator with Google's engine and a second engine:
    • "No voice profiles" with no profiles;
    • switching by gesture with the settings screens open;
    • switching away from an engine and back before the other started;
    • changing the engine of the profile in use;
    • choosing a voice;
    • Announce keyboard keys faster with a profile in use, through keyboard windows and screen off and on;
    • menu order, moving, renaming and deleting profiles, and restarting Backtalk.

A voice profile is a set of speech settings with its own engine,
language, voice, volume, rate, pitch, and "Send long text a sentence at
a time". Profiles are added and changed in Text-to-speech > Voice
profiles. The "Speech engine" reading control becomes "Voice profile",
which moves between Backtalk default and each profile and says the
profile's name. Backtalk default is always there, and is the
text-to-speech settings as before.

While a profile is in use, changing the speech rate or pitch with
gestures, the reading controls or the keyboard changes that profile
only. The profile speaks everything in its own voice: language marks in
text are ignored, mixed-language text is not split at them, and the
Language reading control and menu are hidden. Backtalk default keeps
its language choice and its automatic language and dialect switches.

A profile's language is Default unless one is chosen, and choosing one
narrows the voice list to the engine's voices in that language. A
profile's Default voice is the language's default voice, or the
engine's own default voice when the language is Default too.

Limitations: the languages and voices are the ones the engine gives
Backtalk. Google's speech engine gives TalkBack extra voices by its
package name, and those can't be listed. If a profile's voice is
removed, the profile falls back to its language's default voice, then
to the engine's. The speech cache is not used while a profile is in
use, since it keeps speech by language rather than by voice. Profile
switches between engines wait for the new engine to start, as engine
switches did before.

- VoiceProfiles: the profiles, stored as separate settings per profile
  so screens bind to them, and the profile in use.
- FailoverTextToSpeech: the profile's engine, voice or language, and
  sentence sending; no speech cache while a profile is in use.
- LanguageSwitch: no language changes while a profile is in use.
- Speech rate, pitch and volume come from the profile in use, and rate
  and pitch changes go to it.
- Voice profiles screen, with the profile in use and Add voice profile,
  and a screen for each profile with Delete voice profile.
- The reading control keeps the old item's setting, so anyone who had
  "Speech engine" on gets "Voice profile".
- Unit tests for the profile settings and for no language switching
  while a profile is in use.
…enamed profile, and describe voice profiles in Differences from TalkBack
- A damaged profile setting, such as one restored from a backup with
  the wrong type or an out-of-range value, now gives its default value
  instead of stopping the screen reader as it starts. Rate, pitch and
  volume are kept to the ranges that can be set, so a bad value can't
  silence speech.
- Profile names are limited to 100 characters.
- The Voice profiles list makes a new row adapter each time the screen
  is shown again, so lists from earlier visits aren't kept in memory.
- The engine's voice list is kept from engine start, so switching
  profiles doesn't list every voice on the main thread each time. It
  is listed again only when a voice isn't found.
- The Voice profile reading control says its own name for a profile
  with no name, rather than nothing.
…ashed

Watch settings rows are drawn with Compose and have no title or summary
views, so the Voice profiles list crashed on a watch as soon as it
showed a profile row, taking the screen reader's process with it. On a
watch the rows are now ordinary preferences, and each profile's own
screen has Move up and Move down, which say where the profile went.
Phones keep dragging and the list's actions.

A long press that ends after the screen has closed no longer opens the
menu.
Voice profiles could only be switched with the reading control or from
settings. Now the Backtalk menu can show a Voice profile item, and
gestures and keyboard shortcuts can open the same menu or go straight to
the previous or next profile.

The menu lists Backtalk default and then each profile, in the order of
the Voice profiles screen, and marks the one in use. Choosing one says
its name. Previous and next go round the same list as the reading
control, say the new profile's name and show it on screen, without the
reading control's hint.

Limitations:
- The Backtalk menu item is off by default, like Spoken language, and
  is left out until at least one profile exists. The menu shortcut and
  previous/next say "No voice profiles" until then.
- The actions have no default gestures or keyboard shortcuts.
- Braille displays get no commands for these. Their commands are fixed
  key bindings that users can't reassign.

- VoiceProfiles.adjacentId: the profile before or after the one in use,
  now shared by the reading control and the shortcuts, with a unit test.
- VoiceProfileMenuProcessor fills the menu, opened as a Backtalk menu
  submenu or on its own (ListMenuManager.MenuId.VOICE_PROFILE).
- Backtalk menu settings: Voice profile checkbox, on phones and watches.
- Gesture actions under reading control: Choose voice profile, Previous
  voice profile and Next voice profile.
- Keyboard shortcuts with the same names, unassigned, in both keymaps.
- README: how to add the menu item and assign the actions.
…bandoned engine, or keeping another profile's voice
aaron-gh added a commit to aaron-gh/backtalk that referenced this pull request Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant