Audio Format Standards
All internal audio in Voxray uses PCM 16-bit little-endian mono. Providers that deliver other encodings (G.711 telephony, Opus/WebRTC) are converted at the transport boundary before frames enter the pipeline.
The two canonical constants used throughout the codebase:
Always resample to
DefaultInSampleRate (16 kHz) before pushing audio into the pipeline. Always resample from DefaultOutSampleRate (24 kHz) when encoding for outbound WebRTC or telephony. Mismatched rates produce audio that plays at the wrong speed and causes STT errors.G.711 Codecs
G.711 is the standard codec for telephony (PSTN). Voxray includes two implementations for both the A-law and μ-law variants.μ-law (PCMU, G.711)
μ-law is used by Twilio, Telnyx, Plivo, and Exotel. It delivers 8-bit samples at 8 kHz that are logarithmically compressed for telephone-grade dynamic range.pkg/audio/ulaw.go
A-law (PCMA, G.711)
A-law is the European equivalent of μ-law, used by some SIP/VoIP providers.pkg/audio/alaw.go
Both codecs operate sample-by-sample. The telephony adapter loops over each inbound byte, decodes it to a 16-bit PCM sample, collects samples into a buffer, and then resamples 8 kHz → 16 kHz before handing the AudioRawFrame to the pipeline. The reverse happens on output.
Resampling
pkg/audio/resample.go provides linear interpolation resampling for 16-bit mono PCM. It is fast, allocation-efficient, and correct for the moderate ratio conversions used by Voxray (2:1, 3:1, 6:1).
Function Signature
Key Conversion Paths
How Linear Interpolation Works
For each output sample indexi, the resampler maps it back to a floating-point position in the input:
Voice Activity Detection (VAD)
VAD determines whether a given audio buffer contains human speech. Voxray uses VAD to gate STT calls — only segments classified as speech are transcribed, which reduces cost and latency.Detector Interface
IsSpeech returns true when the internal state machine is in StateSpeaking. SetSampleRate must be called with the pipeline’s input rate (typically 16000) before the first frame is processed.
VAD State Machine
The VAD analyzer implements a four-state machine to avoid false positives from transient noise and to avoid false negatives from brief pauses within speech: State transition logic in detail:StateQuiet → StateStarting: A 10 ms audio window has confidence ≥vad_confidenceand smoothed volume ≥vad_min_volume.StateStarting → StateSpeaking: Speech conditions have held continuously forvad_start_secs_vadseconds. Short noises (coughs, clicks) that don’t sustain are rejected here.StateStarting → StateQuiet: A single silent window while inStateStartingresets back to quiet — the noise was transient.StateSpeaking → StateStopping: A 10 ms window is silent.StateStopping → StateQuiet: Silence has held forvad_stop_secsseconds.StateStopping → StateSpeaking: Speech is detected again before the stop timer expires — the user is still talking.
[0, 1], applies exponential smoothing to the volume track, and advances the state machine.
VAD Configuration
Example configuration for a quiet office environment:
Energy-Based VAD
The default backend (vad_type: "energy") computes RMS energy over each 10 ms window and normalizes it against vad_threshold to produce a confidence score:
vad_threshold — if too low, ambient noise triggers speech; if too high, quiet speech is missed.
Silero VAD
vad_type: "silero" uses the Silero VAD neural network model. It produces more accurate confidence scores than energy-based detection, particularly for:
- Soft-spoken users
- Environments with variable background noise
- Non-English speech patterns
Turn Detection
Turn detection determines when the user has finished speaking and the pipeline should trigger STT and the LLM response. It operates above VAD — VAD detects per-frame speech/silence, while turn detection tracks the overall conversational turn.Silence-Based Turn Detection (default)
StateSpeaking to StateQuiet and the silence persists for turn_stop_secs, the pipeline emits an end-of-turn signal, sends the buffered audio to STT, and starts the LLM response.
Disabled Turn Detection
EndFrame signals over the transport.
Turn Detection Configuration
turn_pre_speech_ms
When VAD detects the start of speech, the pipeline needs a small buffer of audio that arrived just before the detection threshold was crossed — otherwise the first syllable of the user’s utterance is clipped.turn_pre_speech_ms controls how much pre-speech audio is prepended to the turn buffer.
UserIdleFrame
When the bot finishes its response and the user has not begun speaking withinuser_idle_timeout_secs, the pipeline emits a UserIdleFrame. Your pipeline handler can react to this frame by:
- Prompting the user (sending a TTS message like “Are you still there?”)
- Ending the session gracefully
- Incrementing an idle counter and escalating after multiple idle events