Skip to content

Commit d976cb1

Browse files
author
DavidQ
committed
Refine Text to Speech V2 layout voices presets and item controls - PR_26130_015-text-to-speech-v2-layout-controls
1 parent 8faa40e commit d976cb1

13 files changed

Lines changed: 661 additions & 82 deletions
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# PR_26130_015-text-to-speech-v2-layout-controls
2+
3+
## Purpose
4+
5+
Polish Text to Speech V2 layout controls, queue item actions, and speech option constraints while keeping the internal tool id `text2speach-V2`.
6+
7+
## Scope
8+
9+
Changed Text to Speech V2 runtime, schema/defaults, related shared audio TTS defaults/engine clamp behavior, and Workspace Manager V2 Playwright coverage for this tool only.
10+
11+
No unrelated files were modified. No `start_of_day` files were changed.
12+
13+
## Implementation Summary
14+
15+
- Set Pitch minimum to `0.1` in defaults, schema, and utterance clamp behavior.
16+
- Restored neutral/unknown voices to helper filtering buckets so preferred gender filters do not hide available language coverage.
17+
- Replaced the Text to Speech V2 header frame pattern with the same local common header layout pattern used by Palette Manager V2, while keeping the visible title `Text to Speech V2`.
18+
- Moved Text into the center column as its own accordion, removed the center speech preview div, and renamed the preview area to `Named Sentences`.
19+
- Replaced the named sentence dropdown with selectable tiles and moved Speak/Pause/Resume/Stop controls to the top of the Named Sentences accordion.
20+
- Changed the status action order to X then Clear.
21+
- Added the exact visible character preset label `D&D Dungeon Master`.
22+
- Added Speech Options Add, Duplicate, and Delete buttons.
23+
- Wired Add/Duplicate/Delete to maintain a complete schema-valid queue, preserve a selected item, and mark workspace toolState dirty for item and option changes.
24+
25+
## Playwright Impact
26+
27+
Playwright impacted: Yes.
28+
29+
The Workspace Manager V2 Playwright suite validates:
30+
31+
- Text to Speech V2 visible naming and header layout contract.
32+
- Pitch minimum `0.1` in UI and schema.
33+
- Neutral/unknown voices restored in preferred gender helper buckets.
34+
- Text accordion placement in the center column.
35+
- Named Sentences tiles replacing the old dropdown.
36+
- Speak/Pause/Resume/Stop at the top of Named Sentences.
37+
- Status action order as X then Clear.
38+
- `D&D Dungeon Master` preset presence and slider effects.
39+
- Add/Duplicate/Delete item behavior and dirty toolState persistence.
40+
41+
Expected pass behavior: controls render in the requested order/layout, speech items hydrate and mutate schema-valid queue data, and dirty state is updated after queue/text/options changes.
42+
43+
Expected fail behavior: Playwright fails if the legacy dropdown/header/preview patterns return, if queue item mutations leave invalid state, or if requested controls are missing or misordered.
44+
45+
## Validation
46+
47+
Passed:
48+
49+
```text
50+
npm run test:workspace-v2
51+
```
52+
53+
Result:
54+
55+
```text
56+
28 passed
57+
```
58+
59+
Additional checks passed:
60+
61+
```text
62+
node --check src/engine/audio/TextToSpeechDefaults.js
63+
node --check src/engine/audio/TextToSpeechEngine.js
64+
node --check tools/text2speach-V2/js/TextToSpeechToolApp.js
65+
node --check tools/text2speach-V2/js/bootstrap.js
66+
node --check tools/text2speach-V2/js/controls/QueueControl.js
67+
node --check tools/text2speach-V2/js/controls/OutputSummaryControl.js
68+
node --check tools/text2speach-V2/js/controls/SpeechOptionsControl.js
69+
node --check tools/text2speach-V2/js/controls/TextInputControl.js
70+
node --check tests/playwright/tools/WorkspaceManagerV2.spec.mjs
71+
node -e "JSON.parse(require('node:fs').readFileSync('tools/schemas/tools/text2speach-V2.schema.json','utf8')); console.log('schema ok')"
72+
git diff --check HEAD -- .
73+
rg -n -P "<script(?![^>]*\bsrc=)|<style|\son[a-zA-Z]+=" tools/text2speach-V2/index.html
74+
rg -n "tools/shared|imageDataUrl|start_of_day" src/engine/audio tools/text2speach-V2 tools/schemas/tools/text2speach-V2.schema.json tests/playwright/tools/WorkspaceManagerV2.spec.mjs
75+
```
76+
77+
The inline HTML restriction scan and forbidden-scope scan returned no matches. `git diff --check` reported only existing Windows line-ending warnings and no whitespace errors.
78+
79+
## V8 Coverage
80+
81+
The `npm run test:workspace-v2` run generated the Playwright V8 coverage report at:
82+
83+
```text
84+
docs/dev/reports/playwright_v8_coverage_report.txt
85+
```
86+
87+
Changed runtime JS coverage included:
88+
89+
- `src/engine/audio/TextToSpeechDefaults.js`
90+
- `src/engine/audio/TextToSpeechEngine.js`
91+
- `tools/text2speach-V2/js/TextToSpeechToolApp.js`
92+
- `tools/text2speach-V2/js/bootstrap.js`
93+
- `tools/text2speach-V2/js/controls/OutputSummaryControl.js`
94+
- `tools/text2speach-V2/js/controls/QueueControl.js`
95+
- `tools/text2speach-V2/js/controls/SpeechOptionsControl.js`
96+
- `tools/text2speach-V2/js/controls/TextInputControl.js`
97+
98+
The coverage guard reported no low-coverage changed runtime JS files.
99+
100+
## Full Samples Smoke Test
101+
102+
Skipped. This PR is limited to Text to Speech V2 layout, schema/defaults, runtime queue controls, and Workspace Manager V2 tool launch coverage. It does not modify the shared sample loader, sample JSON, or broad game launch behavior.
103+
104+
## ZIP Artifact
105+
106+
Repo-structured delta ZIP:
107+
108+
```text
109+
tmp/PR_26130_015-text-to-speech-v2-layout-controls_delta.zip
110+
```
111+
112+
## Manual Validation Steps
113+
114+
1. Open `tools/text2speach-V2/index.html`.
115+
2. Confirm the header matches the Palette Manager V2-style common header layout and the visible title is `Text to Speech V2`.
116+
3. Confirm the center column shows Text above Named Sentences, with no speech preview div.
117+
4. Confirm Named Sentences uses selectable tiles and has Speak, Pause, Resume, and Stop at the top.
118+
5. Confirm Speech Options shows Add, Duplicate, and Delete at the bottom.
119+
6. Select a named sentence tile and confirm Speech Options and Text hydrate from that item.
120+
7. Use Add, Duplicate, and Delete and confirm the queue never becomes empty or invalid.
121+
8. Change text/options and confirm Workspace Manager V2 marks the Text to Speech V2 toolState dirty when launched from the workspace.
122+
123+
Expected outcome: the requested Text to Speech V2 layout and controls are present, queue item actions preserve valid toolState data, and dirty state changes after edits.
124+
125+
## Changed Files
126+
127+
- `src/engine/audio/TextToSpeechDefaults.js`
128+
- `src/engine/audio/TextToSpeechEngine.js`
129+
- `tests/playwright/tools/WorkspaceManagerV2.spec.mjs`
130+
- `tools/schemas/tools/text2speach-V2.schema.json`
131+
- `tools/text2speach-V2/index.html`
132+
- `tools/text2speach-V2/js/TextToSpeechToolApp.js`
133+
- `tools/text2speach-V2/js/bootstrap.js`
134+
- `tools/text2speach-V2/js/controls/OutputSummaryControl.js`
135+
- `tools/text2speach-V2/js/controls/QueueControl.js`
136+
- `tools/text2speach-V2/js/controls/SpeechOptionsControl.js`
137+
- `tools/text2speach-V2/js/controls/TextInputControl.js`
138+
- `tools/text2speach-V2/styles/text2speach-V2.css`
139+
- `docs/dev/reports/PR_26130_015-text-to-speech-v2-layout-controls.md`
140+
- `docs/dev/reports/codex_review.diff`
141+
- `docs/dev/reports/codex_changed_files.txt`
142+
- `docs/dev/codex_commands.md`
143+
- `docs/dev/commit_comment.txt`

src/engine/audio/TextToSpeechDefaults.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const TEXT_TO_SPEECH_CHARACTER_PRESET_OPTIONS = Object.freeze([
4949
Object.freeze({ label: "Manual", value: "manual" }),
5050
Object.freeze({ label: "Alert", value: "alert" }),
5151
Object.freeze({ label: "Calm", value: "calm" }),
52+
Object.freeze({ label: "D&D Dungeon Master", value: "dnd-dungeon-master" }),
5253
Object.freeze({ label: "Dramatic", value: "dramatic" }),
5354
Object.freeze({ label: "Narrator", value: "narrator" }),
5455
Object.freeze({ label: "Robot", value: "robot" })
@@ -68,14 +69,15 @@ const TEXT_TO_SPEECH_SSML_LIKE_PRESET_DEFAULTS = Object.freeze({
6869

6970
const TEXT_TO_SPEECH_RANGE_DEFAULTS = Object.freeze({
7071
delayBetweenRepeatsMs: Object.freeze({ max: 5000, min: 0, step: 100, value: 0 }),
71-
pitch: Object.freeze({ max: 2, min: 0, step: 0.1, value: 1 }),
72+
pitch: Object.freeze({ max: 2, min: 0.1, step: 0.1, value: 1 }),
7273
rate: Object.freeze({ max: 2, min: 0.1, step: 0.1, value: 1 }),
7374
volume: Object.freeze({ max: 1, min: 0, step: 0.01, value: 1 })
7475
});
7576

7677
const TEXT_TO_SPEECH_CHARACTER_PRESET_DEFAULTS = Object.freeze({
7778
alert: Object.freeze({ pitch: 0.9, rate: 1.3, ssmlLikePreset: "normal", volume: 1 }),
7879
calm: Object.freeze({ pitch: 1, rate: 0.8, ssmlLikePreset: "normal", volume: 1 }),
80+
"dnd-dungeon-master": Object.freeze({ pitch: 0.7, rate: 0.9, ssmlLikePreset: "normal", volume: 1 }),
7981
dramatic: Object.freeze({ pitch: 1.2, rate: 1.1, ssmlLikePreset: "normal", volume: 1 }),
8082
manual: Object.freeze({ pitch: 1, rate: 1, ssmlLikePreset: "normal", volume: 1 }),
8183
narrator: Object.freeze({ pitch: 1, rate: 1, ssmlLikePreset: "normal", volume: 1 }),

src/engine/audio/TextToSpeechEngine.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,11 @@ class TextToSpeechEngine {
133133

134134
const utterance = new this.Utterance(normalizedText);
135135
utterance.lang = String(language || selectedVoice.lang || TEXT_TO_SPEECH_DEFAULTS.language);
136-
utterance.pitch = boundedNumber(pitch, { fallback: TEXT_TO_SPEECH_DEFAULTS.pitch, max: 2, min: 0 });
136+
utterance.pitch = boundedNumber(pitch, {
137+
fallback: TEXT_TO_SPEECH_DEFAULTS.pitch,
138+
max: TEXT_TO_SPEECH_RANGE_DEFAULTS.pitch.max,
139+
min: TEXT_TO_SPEECH_RANGE_DEFAULTS.pitch.min
140+
});
137141
utterance.rate = boundedNumber(rate, {
138142
fallback: TEXT_TO_SPEECH_DEFAULTS.rate,
139143
max: TEXT_TO_SPEECH_RANGE_DEFAULTS.rate.max,

0 commit comments

Comments
 (0)