DECtalk - Host GUI & Serial API

This directory contains host applications for controlling the DECtalk text-to-speech engine running on an ESP32 microcontroller:

Table of Contents

Overview

The host communicates with the ESP32 over USB using the DECtalk ESPress serial protocol. The ESP32 firmware boots directly into ESPress protocol mode on its host USB port, which appears as a standard serial port on the host computer (for example COM, /dev/ttyACM*, or /dev/ttyUSB* depending on the board and driver). On ESP32-S3 the host link uses USB CDC-ACM (TinyUSB); on ESP32-C6 it uses the built-in USB Serial/JTAG interface. The dedicated physical-device guide in ../HARDWARE.md covers the photographed ESP32-C6 perfboard build; the host tools themselves support either firmware target.

Requirements

Quick Start

Option 1 — Web GUI (no install)

  1. Flash the DECtalk firmware to your ESP32 (see ../README.md).
  2. Open host/web/index.html in Chrome or Edge 89+ (either by double-clicking the file, serving it from any static web server, or visiting the published GitHub Pages site).
  3. Click Connect and select the ESP32 serial port from the browser chooser.
  4. Type text and click Speak.

Option 2 — Qt desktop GUI

  1. Flash the DECtalk firmware to your ESP32 (see ../README.md).

  2. Install the Python dependencies:

    pip install pyserial PySide6
  3. Run the ESPress GUI:

    python dtesp_gui_qt.py
  4. Select the serial port for your ESP32 and click Connect. On Linux this is often /dev/ttyACM* on ESP32-S3 and may be either /dev/ttyACM* or /dev/ttyUSB* on ESP32-C6 depending on the USB bridge/driver.

  5. Type text in the text box and click Speak.

Web GUI (web/index.html)

A single self-contained HTML page that talks to the ESP32 directly from the browser via the Web Serial API (Chrome / Edge 89+). No Python, backend, or local install is required. It mirrors the Qt GUI feature for feature, reorganised into a vertical browser-friendly layout:

The page is dark-themed to match the project's GitHub Pages site and the existing Web Flasher. Because it runs entirely in the browser, the same index.html file works whether opened from disk, served from a static web server, or hosted alongside the Web Flasher on GitHub Pages.

Browser support: the Web Serial API is currently only available in Chromium-based browsers (Chrome, Edge, Opera, Brave, …) on desktop. Firefox and Safari are not supported. On Linux, ensure your user has access to the serial device (typically by being in the dialout or uucp group).

GUI Features

Voice Selection

Choose from 9 built-in DECtalk voices:

Voice Description
Paul Standard male (default)
Betty Standard female
Harry Deep male
Frank Older male
Dennis Breathy male
Kit Child (~10 years)
Ursula Light female
Rita Deep female
Wendy Whispery female

Rate Control

Adjust the speaking rate from 75 to 600 words per minute (WPM) using the slider. The default is 200 WPM.

Pitch Control

Adjust the average pitch from 50 to 400 Hz using the slider. The leftmost position uses the voice's default pitch.

Text Editing

The multi-line text box supports standard editing operations (Cut/Copy/Paste, Select All, Undo/Redo) and keyboard navigation.

DECtalk Inline Commands

You can include DECtalk inline commands directly in the text box. These are processed by the DECtalk engine on the ESP32. For example:

[:phoneme on][hxeh<500,20>low<500,22>]
[:np] Hello, I am Paul. [:nb] And I am Betty.
[:dv ap 160 pr 50] This voice has modified pitch.
[:tone 500,500] A tone before speech.

For the full DECtalk inline-command reference, use the upstream DECtalk documentation that matches your language/voice package.

ESPress GUI (dtesp_gui_qt.py)

A Qt-based (PySide6/PyQt6) GUI for the DECtalk ESPress serial protocol with full accessibility support. Features:

DECtalk ESPress Protocol

The ESP32 firmware boots directly into ESPress protocol mode on its host USB port. No handshake or mode-switch command is needed. On ESP32-S3, opening the USB CDC-ACM port triggers a DTR assertion that the firmware detects, causing it to reset protocol state and send XON to indicate readiness. On ESP32-C6, connection detection uses the USB Serial/JTAG connected state; the firmware disables the RTS-triggered chip reset so opening the port does not reboot the device.

Key Protocol Elements

Feature Description
Transport USB CDC-ACM on ESP32-S3; USB Serial/JTAG on ESP32-C6 (both appear as normal serial ports such as COM, /dev/ttyACM*, or /dev/ttyUSB*)
Text format Plain ASCII text + CR
Flush/stop ETX (0x03)
Status query ENQ (0x05) → 4-byte DLE status response
Pause/Resume SO (0x0E) / SI (0x0F)
Flow control XON/XOFF (application-level, in-band)
Device ready XON sent on startup / reconnect

Python API Module

The dtesp_serial.py module can be used independently from the GUI:

from dtesp_serial import DECtalkESPressSerial

dtesp = DECtalkESPressSerial()

# List available serial ports
print(DECtalkESPressSerial.list_ports())

# Connect to the ESP32
dtesp.connect("/dev/ttyACM0")

# Detect device (same probe as the original comchk utility)
if dtesp.detect_device():
    print("DECtalk device detected!")

# Send text (device speaks it immediately)
dtesp.send_text("Hello world.")

# Speak with voice and rate (uses inline commands)
dtesp.speak("Now I am Betty.", voice="Betty", rate=250)

# Request device status
status = dtesp.request_status()
if status >= 0:
    print("Device status: 0x%04X" % status)

# Pause and resume speech
dtesp.pause()
dtesp.resume()

# Flush (cancel) all speech
dtesp.flush()

# Flush with acknowledgment (TSR FLUSH_TEXT sequence)
if dtesp.flush_with_ack():
    print("Flush acknowledged")

# Disconnect
dtesp.disconnect()

Available Voices

from dtesp_serial import VOICES
print(list(VOICES.keys()))
# ['Paul', 'Betty', 'Harry', 'Frank', 'Dennis', 'Kit', 'Ursula', 'Rita', 'Wendy']

Building DECtalk Command Strings

from dtesp_serial import build_dtesp_prefix

# Build inline command prefix
prefix = build_dtesp_prefix(voice="Harry", rate=150, pitch=90)
print(prefix)  # "[:nh][:ra 150][:dv ap 90]"