# 07 — سیستم صوتی (فایل ضبط‌شده + TTS)

صدا در آموزش سوادآغازین **اولویت اول** است: کودکی که نمی‌خواند، همه‌ی دستورالعمل‌ها را از صدا می‌گیرد.

## 1. معماری AudioEngine

```
EventBus: 'audio:play' {kind, ref}
        │
        ▼
┌───────────────────────────────────────────────────────────┐
│ AudioEngine                                               │
│                                                           │
│  کانال‌ها (۲ کانال هم‌زمان):                                │
│   • voice  — تلفظ حروف/کلمات (اولویت بالا)                  │
│   • sfx    — افکت‌ها: pop، تشویق، خطا، ستاره (اولویت پایین) │
│                                                           │
│  حل‌کننده‌ی منبع (Source Resolver):                          │
│   1. فایل از پک  → audio/<pack>/…            (کیفیت ثابت)  │
│   2. Web Speech  → speechSynthesis, lang=pack.lang (fallback)│
│   3. هیچ‌کدام    → بازخورد تصویری + navigator.vibrate?.()   │
└───────────────────────────────────────────────────────────┘
```

```js
// نمونه‌ی قرارداد داخلی
audio.playVoice({ kind: 'letter-sound', letterId: 'fa_be' });
// 1) assets/audio/fa/letters/be/sound.mp3  → HTMLAudioElement (کش‌شده)
// 2) خطا/نبودن → speechSynthesis.speak(new SpeechSynthesisUtterance('بِه')) با lang='fa-IR'
// 3) خطا → ui:flashSpeakerIcon + haptic
```

## 2. دارایی‌های صوتی — جدول کامل

| نوع | مسیر | تعداد (به‌ازای پک) | فرمت |
|---|---|---|---|
| نام حرف | `audio/<pack>/letters/<id>/name.mp3` | ۲۶–۳۲ | MP3 + OGG |
| صدای حرف (phoneme) | `audio/<pack>/letters/<id>/sound.mp3` | ۲۶–۳۲ | MP3 + OGG |
| تلفظ کلمات نمونه | `audio/<pack>/words/<id>.mp3` | ~۱۵۰ | MP3 + OGG |
| دستور بازی‌ها | `audio/<pack>/instructions/<game>.mp3` | ~۲۰ | MP3 + OGG |
| تشویق‌ها | `audio/sfx/praise-<1..5>.mp3` | مشترک | MP3 |
| افکت‌ها | `audio/sfx/pop·error-soft·star·confetti.mp3` | مشترک | MP3 |

**قواعد ضبط:** گوینده‌ی بومی، سرعت ۰.۹×، هر فایل ≤ 2 ثانیه (حروف) / ≤ 4 ثانیه (کلمات)، sample-rate 44.1k → انکود MP3 96kbps mono + OGG 64kbps (~۳۰KB به‌ازای هر کلیپ).

## 3. استراتژی پیش‌بارگذاری (Preload)

```
اولویت ۱ (هنگام شروع جلسه):  حروف جلسه‌ی جاری (voice + sfx پایه)   → preload=auto
اولویت ۲ (پس‌زمینه):           ۲ حرف بعدی مسیر + صداهای مراسم پاداش  → idle callback
بقیه:                          بارگذاری تنبل هنگام اولین نیاز          → lazy
```
- سقف حافظه‌ی صوتی: ~۲۰ فایل کش‌شده؛ سیاست LRU (قدیمی‌ترین جلسه حذف می‌شود).
- Service Worker دارایی‌های صوتی مشترک (sfx) را `cache-first` و صداهای پک را `stale-while-revalidate` نگه می‌دارد (سند 08).

## 4. Web Speech API — محدودیت‌ها و رفتار

| محدودیت | راهکار |
|---|---|
| کیفیت صدا بسته به voice سیستم | فقط fallback است؛ در تبلت/موبایل مدرن کیفیت قابل قبول |
| پشتیبانی نشدن زبان روی دستگاه | تشخیص با `speechSynthesis.getVoices()` → اگر voice با `lang` پک نبود، مستقیم به بازخورد تصویری |
| قفل پس از چند بار پخش در برخی مرورگرها | هر utterance بعد از `end`/`error` حتماً dereference می‌شود |
| صدای خفه در iOS تا اولین تعامل کاربر | AudioEngine در اولین touch، کانال‌ها را unlock می‌کند (الگوی رایج) |

**قاعده‌ی UX:** هیچ‌وقت صدا به‌تنهایی تنها حامل اطلاعات نیست — همیشه آیکون/انیمیشن بلندگوی هم‌زمان نمایش داده می‌شود (طراحی برای کودکان با اختلال شنوایی و محیط‌های شلوغ).

## 5. سکوت و تنظیمات

- کلید صدا در هر صفحه (آیکون بلندگو، بالا-چپ/راست منطقی).
- والد می‌تواند موسیقی پس‌زمینه را خاموش کند (SFX و voice همیشه روشن می‌مانند — جزء آموزش‌اند).
