An interactive application for learning Mandarin Chinese tone pronunciation with real-time feedback.
┌─────────────────────────────────────────────────────────────┐
│ Mandarin Tone Coach [─][□][×]│
├─────────────┬───────────────────────────────────────────────┤
│ │ │
│ Lessons │ 你好 │
│ ───────── │ nǐ hǎo (T3 T3) │
│ │ "hello" │
│ ▶ Basics │ │
│ Numbers │ ┌─────────────────────────────────────┐ │
│ Food │ │ F0 Pitch Visualization │ │
│ ... │ │ Reference (gray) vs You (blue) │ │
│ │ └─────────────────────────────────────┘ │
│ │ │
│ │ [Record] [Play Reference] │
│ │ │
│ │ Results: [你 T3 ✓] [好 T3 ✓] Score: 100% │
│ │ │
│ │ Automatic Mode [==○] │
└─────────────┴───────────────────────────────────────────────┘
Ubuntu/Debian:
sudo apt install python3-gi gir1.2-gtk-4.0 gir1.2-adw-1
Fedora:
sudo dnf install python3-gobject gtk4 libadwaita
Arch Linux:
sudo pacman -S python-gobject gtk4 libadwaita
# Create venv with system site packages (for GTK bindings)
python -m venv venv --system-site-packages
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Optional: Install pyctcdecode for improved ASR
pip install pyctcdecode
python run_gtk.py
Options:
--asr mms - Use only MMS ASR (lower GPU memory)--asr whisper - Use only Whisper ASR--asr both - Use dual ASR (default, best accuracy)--asr none - Disable ASR (tone classifier only)--cpu - Force CPU-only mode (no CUDA/GPU required)Toggle "Automatic Mode" in the GUI for hands-free practice:
This allows continuous drilling without touching the keyboard.
Hands-free operation, designed for Bluetooth headphones:
python run_voice.py
Chat with an AI coach that guides your practice:
python run_coach.py --backend ollama # Local LLM
python run_coach.py --backend claude # Claude API
| Lesson | Phrases | Description |
|---|---|---|
| Starter Words | 5 | Essential beginner phrases (你好, 谢谢, 再见) |
| Going to the Park | 6 | Outdoor activity vocabulary |
| At the Restaurant | 6 | Ordering food and drinks |
| Numbers | 10 | Counting 1-10 |
| Feelings | 7 | Express emotions |
| Daily Conversations | 18 | Common questions and responses |
| Shopping & Bargaining | 9 | Market and store phrases |
| Asking Directions | 10 | Navigation vocabulary |
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Record │───▶│ Segment │───▶│ Classify │
│ Audio │ │ by Syllable │ │ Tones │
└──────────────┘ └──────────────┘ └──────────────┘
│
┌──────────────┐ ┌──────────────┐ ▼
│ Display │◀───│ Combine │◀───┌──────────────┐
│ Results │ │ Signals │ │ Dual ASR │
└──────────────┘ └──────────────┘ │ MMS+Whisper │
└──────────────┘
The system uses multiple signals to determine correctness:
is_correct = (
classifier_detected_correct_tone # Direct match
or asr_detected_correct_tone # ASR-derived tone matches
or asr_recognized_character # ASR heard the right word
)
This maximizes user success while providing accurate feedback.
Automatically handles Chinese tone sandhi rules:
src/
├── coach/
│ ├── evaluator.py # Unified evaluation pipeline
│ ├── aligner.py # Syllable boundary detection
│ ├── mms_asr.py # MMS + Whisper ASR with contextual biasing
│ ├── sandhi.py # Tone sandhi rules
│ ├── tts.py # Dual TTS (edge-tts + Qwen3-TTS)
│ ├── llm.py # LLM backends (Claude, Ollama, Transformers)
│ ├── coach.py # Conversational coach
│ ├── progress.py # Progress tracking
│ └── voice_menu.py # Voice-controlled menu + lesson definitions
├── gtk_ui/
│ ├── views/
│ │ └── practice_view.py # Main practice interface
│ └── widgets/
│ ├── pitch_visualizer.py # F0 contour visualization
│ └── tone_result_card.py # Per-syllable results
└── features/
└── f0_extract.py # F0 extraction (pYIN)
| Component | Model | Purpose |
|---|---|---|
| Acoustic Features | facebook/mms-1b-all | Encode audio for classification |
| Tone Classifier | Custom MLP | Classify tones 1-5 |
| ASR (primary) | facebook/mms-1b-all | Chinese speech recognition |
| ASR (secondary) | openai/whisper-base | Backup recognition with prompting |
| TTS (fast) | edge-tts | English prompts, Chinese fallback |
| TTS (quality) | Qwen3-TTS | High-quality Chinese audio |
Both ASR models use the expected phrase to improve recognition:
prompt_ids to hint expected vocabularyThis significantly improves recognition of short phrases like "你好".
pytest tests/ -v
run_gtk.py - GTK4 GUI entry pointrun_voice.py - Voice menu entry pointrun_coach.py - Conversational mode entry pointsrc/coach/ - Core evaluation and coaching logicsrc/gtk_ui/ - GTK4 user interfacedocs/ - Architecture documentationMIT License
20 commits
Python
93.1%
Shell
6.9%
An interactive application for learning Mandarin Chinese tone pronunciation with real-time feedback.
┌─────────────────────────────────────────────────────────────┐
│ Mandarin Tone Coach [─][□][×]│
├─────────────┬───────────────────────────────────────────────┤
│ │ │
│ Lessons │ 你好 │
│ ───────── │ nǐ hǎo (T3 T3) │
│ │ "hello" │
│ ▶ Basics │ │
│ Numbers │ ┌─────────────────────────────────────┐ │
│ Food │ │ F0 Pitch Visualization │ │
│ ... │ │ Reference (gray) vs You (blue) │ │
│ │ └─────────────────────────────────────┘ │
│ │ │
│ │ [Record] [Play Reference] │
│ │ │
│ │ Results: [你 T3 ✓] [好 T3 ✓] Score: 100% │
│ │ │
│ │ Automatic Mode [==○] │
└─────────────┴───────────────────────────────────────────────┘
Ubuntu/Debian:
sudo apt install python3-gi gir1.2-gtk-4.0 gir1.2-adw-1
Fedora:
sudo dnf install python3-gobject gtk4 libadwaita
Arch Linux:
sudo pacman -S python-gobject gtk4 libadwaita
# Create venv with system site packages (for GTK bindings)
python -m venv venv --system-site-packages
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Optional: Install pyctcdecode for improved ASR
pip install pyctcdecode
python run_gtk.py
Options:
--asr mms - Use only MMS ASR (lower GPU memory)--asr whisper - Use only Whisper ASR--asr both - Use dual ASR (default, best accuracy)--asr none - Disable ASR (tone classifier only)--cpu - Force CPU-only mode (no CUDA/GPU required)Toggle "Automatic Mode" in the GUI for hands-free practice:
This allows continuous drilling without touching the keyboard.
Hands-free operation, designed for Bluetooth headphones:
python run_voice.py
Chat with an AI coach that guides your practice:
python run_coach.py --backend ollama # Local LLM
python run_coach.py --backend claude # Claude API
| Lesson | Phrases | Description |
|---|---|---|
| Starter Words | 5 | Essential beginner phrases (你好, 谢谢, 再见) |
| Going to the Park | 6 | Outdoor activity vocabulary |
| At the Restaurant | 6 | Ordering food and drinks |
| Numbers | 10 | Counting 1-10 |
| Feelings | 7 | Express emotions |
| Daily Conversations | 18 | Common questions and responses |
| Shopping & Bargaining | 9 | Market and store phrases |
| Asking Directions | 10 | Navigation vocabulary |
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Record │───▶│ Segment │───▶│ Classify │
│ Audio │ │ by Syllable │ │ Tones │
└──────────────┘ └──────────────┘ └──────────────┘
│
┌──────────────┐ ┌──────────────┐ ▼
│ Display │◀───│ Combine │◀───┌──────────────┐
│ Results │ │ Signals │ │ Dual ASR │
└──────────────┘ └──────────────┘ │ MMS+Whisper │
└──────────────┘
The system uses multiple signals to determine correctness:
is_correct = (
classifier_detected_correct_tone # Direct match
or asr_detected_correct_tone # ASR-derived tone matches
or asr_recognized_character # ASR heard the right word
)
This maximizes user success while providing accurate feedback.
Automatically handles Chinese tone sandhi rules:
src/
├── coach/
│ ├── evaluator.py # Unified evaluation pipeline
│ ├── aligner.py # Syllable boundary detection
│ ├── mms_asr.py # MMS + Whisper ASR with contextual biasing
│ ├── sandhi.py # Tone sandhi rules
│ ├── tts.py # Dual TTS (edge-tts + Qwen3-TTS)
│ ├── llm.py # LLM backends (Claude, Ollama, Transformers)
│ ├── coach.py # Conversational coach
│ ├── progress.py # Progress tracking
│ └── voice_menu.py # Voice-controlled menu + lesson definitions
├── gtk_ui/
│ ├── views/
│ │ └── practice_view.py # Main practice interface
│ └── widgets/
│ ├── pitch_visualizer.py # F0 contour visualization
│ └── tone_result_card.py # Per-syllable results
└── features/
└── f0_extract.py # F0 extraction (pYIN)
| Component | Model | Purpose |
|---|---|---|
| Acoustic Features | facebook/mms-1b-all | Encode audio for classification |
| Tone Classifier | Custom MLP | Classify tones 1-5 |
| ASR (primary) | facebook/mms-1b-all | Chinese speech recognition |
| ASR (secondary) | openai/whisper-base | Backup recognition with prompting |
| TTS (fast) | edge-tts | English prompts, Chinese fallback |
| TTS (quality) | Qwen3-TTS | High-quality Chinese audio |
Both ASR models use the expected phrase to improve recognition:
prompt_ids to hint expected vocabularyThis significantly improves recognition of short phrases like "你好".
pytest tests/ -v
run_gtk.py - GTK4 GUI entry pointrun_voice.py - Voice menu entry pointrun_coach.py - Conversational mode entry pointsrc/coach/ - Core evaluation and coaching logicsrc/gtk_ui/ - GTK4 user interfacedocs/ - Architecture documentationMIT License
20 commits
Python
93.1%
Shell
6.9%