feat: голосовой ввод на очках — TripleClick + PCM → телефон → текст на очки
Протокол: SttAudio (PCM s16 16k mono кусками), SttPhrase/SttDone/SttCancel
(host→очки), StopStt(cancel) (очки→host).
Очки: TripleClick — безусловный вызов (кино: пауза + затемнение + слушаем);
во время распознавания Click — завершить (весь текст в консоль, затемнение
уходит, видео на паузе), DoubleClick — отмена; VAD-тишина 30с — автоотмена.
Микрофон (AudioRecord 16k) → SttAudio; на эмуляторе — PCM из filesDir/samples
(куски 3200 + пауза 200мс). Оверлей текста в Binocular (полупрозрачный фон,
текст по центру, в оба глаза). RECORD_AUDIO в манифесте. DEBUG-ресивер
(am broadcast DEBUG_GESTURE type=triple_click|click|double_click).
Телефон: SttStreamer — стриминговый VAD (Silero fp32, окна 512) → фразы →
Whisper-small int8 (executor, не блокирует приём) → SttPhrase на очки;
StopStt → SttDone (полный текст) / SttCancel; watchdog 30с тишины.
Фиксы (найдены на эмуляторе): IllegalThreadStateException — двойной старт
watchdog-потока (thread{}.apply{start()}); decode входящих — try/catch с
логом (не роняет сессию).
Проверено на эмуляторах (5554 очки + 5556 телефон, forward 8080):
triple_click → фразы «Раз, два» и «3 4 5» на очках (оверлей) → click →
«ВЕСЬ ТЕКСТ: Раз, два 3 4 5»; 30с-тишина → «отменено». Тесты: lib-core,
phone, glasses — зелёные.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
package pw.binom.viewmate.phone.stt
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class S16ToFloatTest {
|
||||
|
||||
@Test
|
||||
fun convertsSignedSamples() {
|
||||
val pcm = byteArrayOf(0x00, 0x00, 0xff.toByte(), 0x7f, 0x00, 0x80.toByte())
|
||||
val out = s16leToFloat(pcm)
|
||||
assertEquals(3, out.size)
|
||||
assertEquals(0f, out[0], 1e-6f) // 0
|
||||
assertEquals(32767f / 32768f, out[1], 1e-6f) // 0x7fff
|
||||
assertEquals(-32768f / 32768f, out[2], 1e-6f) // 0x8000
|
||||
}
|
||||
|
||||
@Test
|
||||
fun minMaxSamples() {
|
||||
val pcm = byteArrayOf(0xff.toByte(), 0x7f, 0x00, 0x80.toByte())
|
||||
val out = s16leToFloat(pcm)
|
||||
assertEquals(2, out.size)
|
||||
assertEquals(32767f / 32768f, out[0], 1e-6f)
|
||||
assertEquals(-1f, out[1], 1e-6f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun emptyInput() {
|
||||
assertEquals(0, s16leToFloat(ByteArray(0)).size)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user