Documentation
¶
Overview ¶
Package voice provides live microphone/speaker audio for the interactive console. Hardware I/O (PortAudio) is compiled only under the `voice` build tag; everything else here is pure Go so it builds and tests without cgo.
Index ¶
Constants ¶
const ( // CaptureSampleRate is the mic capture rate (16 kHz mono PCM16), matching // the VAD/STT pipeline default. CaptureSampleRate = 16000 // PlaybackSampleRate is the speaker playback rate (24 kHz mono PCM16), // matching TTS / realtime-provider output. PlaybackSampleRate = 24000 )
Variables ¶
var ErrVoiceNotCompiled = errors.New("voice not compiled in (build with -tags voice)")
ErrVoiceNotCompiled is returned by NewAudioIO in builds without the `voice` build tag. It is defined here (not in the stub) so callers can errors.Is check it regardless of build mode.
Functions ¶
This section is empty.
Types ¶
type AudioIO ¶
type AudioIO interface {
// Start opens the mic and speaker devices.
Start(ctx context.Context) error
// CaptureChunks yields mic PCM16 frames (CaptureSampleRate, mono).
CaptureChunks() <-chan []byte
// Play enqueues a PCM16 frame (PlaybackSampleRate, mono) for the speaker.
Play(frame []byte)
// Close stops devices and releases resources.
Close() error
}
AudioIO is hardware mic capture + speaker playback as PCM16 byte streams. Implementations are platform audio backends; the driver depends only on this interface so it is testable without audio hardware.
func NewAudioIO ¶
NewAudioIO returns ErrVoiceNotCompiled in non-voice builds. Build with -tags voice (and PortAudio installed) to enable voice.
type Driver ¶
type Driver struct {
// contains filtered or unexported fields
}
Driver wires hardware AudioIO to a LiveRunner and (optionally) reports RMS levels for the TUI meter. It owns no LLM or pipeline knowledge.
func NewDriver ¶
func NewDriver(io AudioIO, run LiveRunner, onLevel func(user, agent float32)) *Driver
NewDriver constructs a Driver. onLevel may be nil.
func NewDriverWithGuard ¶
func NewDriverWithGuard(io AudioIO, run LiveRunner, onLevel func(user, agent float32), guard *EchoGuard) *Driver
NewDriverWithGuard constructs a Driver with an optional half-duplex echo guard. When guard is non-nil, mic frames are gated by g.Allow before reaching the runner, and g.SetAgentSpeaking is toggled around each playback frame.
v1 limitation: the per-frame SetAgentSpeaking toggle is effective only for synchronous playback (where Play blocks for the full frame duration). Real buffered hardware drivers return from Play before the audio is audible, so the flag stays true for only microseconds and does not suppress echo. Hardware wiring must hold SetAgentSpeaking true for the entire audible playback duration — see the TODO in Driver.Run.
type EchoGuard ¶
type EchoGuard struct {
// contains filtered or unexported fields
}
EchoGuard implements an optional half-duplex mic gate: while the agent is speaking, mic frames quieter than threshold are dropped (they are most likely the agent's own audio bleeding into the mic). Louder frames still pass so a deliberate barge-in interrupts. Off (always-allow) unless enabled by Run.
func NewEchoGuard ¶
NewEchoGuard builds a guard with the given RMS threshold (0..1).
func (*EchoGuard) SetAgentSpeaking ¶
SetAgentSpeaking marks whether agent audio is currently playing.
type LiveRunner ¶
LiveRunner consumes mic frames and emits playback frames, returning when mic closes or ctx ends. engine.(*DuplexConversationExecutor).RunInteractiveVoice is adapted to this signature by the chat command.