Аудио pipeline
Аудио модулът (client/src/audio/) отговаря за захващане на звук от микрофона, генериране на звукови нотификации и управление на системния mute. Той е първото звено в pipeline-а: микрофон -> f32 samples -> WAV кодиране -> WebSocket.
Архитектура
Модул capture.rs
AudioCapture struct
AudioCapture е основният интерфейс за управление на записа:
pub struct AudioCapture {
device_name: Option<String>, // Избран микрофон (None = default)
audio_tx: Sender<Vec<f32>>, // Канал за изпращане на samples
capturing: Arc<AtomicBool>, // Флаг за спиране
thread: Option<JoinHandle<()>>, // Capture thread handle
}
Методи:
new(audio_tx, device_name)-- създава инстанция без да стартира записstart()-- spawn-ва capture нишкаstop()-- спира записа и join-ва нишкатаlist_devices()-- изброява налични capture устройства
WASAPI Capture Loop (Windows)
Ключови параметри
| Параметър | Стойност | Описание |
|---|---|---|
| TARGET_SAMPLE_RATE | 16,000 Hz | Честота за ASR модела |
| Формат | mono float32 | 32-bit floating point, 1 канал |
| autoconvert | true | WASAPI автоматично ресемплира от native формата на устройството |
| StreamMode | EventsShared | Споделен режим с event-based wake |
| Chunk size | 1600 frames | ~100ms при 16kHz |
| Event timeout | 500ms | Максимално изчакване за данни |
Избор на микрофон
Потребителят може да избере конкретен микрофон от настройките. list_devices() изброява всички capture устройства чрез WASAPI DeviceEnumerator. Списъкът се генерира в отделна нишка за да не замърсява COM apartment-а на main thread-а (който трябва да остане STA за egui/winit).
Ако избраното устройство не бъде намерено, се използва default capture device.
macOS (TODO)
macOS имплементацията е stub -- планирана е чрез cpal crate с rubato resampler за конверсия от 48kHz към 16kHz.
Модул sound.rs
Генерира звукови нотификации за начало и край на запис. Звуците са синусоидални бипове, генерирани в паметта като PCM WAV:
| Звук | Описание | Честоти | Продължителност |
|---|---|---|---|
| Start | Нарастващ двутонов бип | 600Hz -> 900Hz | 2 x 120ms |
| Stop | Падащ двутонов бип | 900Hz -> 600Hz | 2 x 120ms |
Характеристики
- Sample rate: 22,050 Hz
- Формат: PCM 16-bit mono WAV
- Envelope: 5ms attack + 15ms release (елиминира клик-артефакти)
- Кеширане: WAV байтовете се генерират веднъж чрез
OnceLockи се преизползват - Възпроизвеждане: Win32
PlaySoundW(SND_MEMORY | SND_SYNC) в background нишка
Mute интеграция
Звуковият модул координира с volume модула при mute_on_record настройка:
Модул volume.rs
Управлява системния mute/unmute чрез Windows Core Audio COM API:
CoCreateInstance->IMMDeviceEnumeratorGetDefaultAudioEndpoint(eRender, eConsole)->IMMDeviceActivate(IID_IAudioEndpointVolume)->IAudioEndpointVolumeSetMute(true/false)илиGetMute()
Имплементацията използва ръчни COM vtable извиквания (без windows-rs bindings) за минимален binary размер.
WAV кодиране
WAV кодирането се извършва в transcription/client.rs чрез hound crate:
fn encode_wav(audio: &[f32]) -> Result<Vec<u8>, String> {
let spec = hound::WavSpec {
channels: 1,
sample_rate: 16_000,
bits_per_sample: 32,
sample_format: hound::SampleFormat::Float,
};
// ... write to in-memory Cursor
}
Формат на WAV файла:
- Канали: 1 (mono)
- Sample rate: 16,000 Hz
- Bits per sample: 32 (float)
- Encoding: IEEE Float
Целият WAV се записва в Vec<u8> в паметта (без файл на диска) и се изпраща като Binary WebSocket frame.