stt

package
v0.14.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 5, 2026 License: GPL-3.0 Imports: 13 Imported by: 0

Documentation

Overview

Package stt provides a local algorithmic speech-to-command parser for ATC transcripts, replacing the LLM-based approach with fast fuzzy matching.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BestMatch

func BestMatch(word string, candidates []string, threshold float64) (string, float64)

BestMatch finds the best matching string from candidates. Returns the match and its score, or empty string and 0 if none found above threshold.

func CleanWord

func CleanWord(w string) string

CleanWord removes non-alphanumeric characters from a word.

func CommandsEquivalent

func CommandsEquivalent(expected, actual string, aircraft map[string]Aircraft) bool

CommandsEquivalent checks if two command strings are equivalent, considering altitude-aware flexibility for A/D/C commands. For example, "A40" and "D40" are equivalent if the aircraft is above 4000 ft.

func ConvertNATOLetter

func ConvertNATOLetter(word string) (string, bool)

ConvertNATOLetter converts a NATO phonetic word to its letter. Returns the letter and true if found, empty string and false otherwise.

func CountTokenType

func CountTokenType(tokens []Token, tokenType TokenType) int

CountTokenType counts tokens of a given type.

func DoubleMetaphone

func DoubleMetaphone(word string) (primary, alternate string)

DoubleMetaphone generates phonetic encodings for a word. Returns primary and alternate encodings. The alternate may be empty. This is a simplified implementation covering common ATC vocabulary.

func ExtractNATOSpelling

func ExtractNATOSpelling(words []string) (string, int)

ExtractNATOSpelling extracts consecutive NATO phonetic letters from words. Returns the spelled-out string (uppercase) and number of words consumed. Stops at the first non-NATO word.

func FindNumber

func FindNumber(tokens []Token, start int) (int, int)

FindNumber finds the first numeric token starting at index.

func FindTokenOfType

func FindTokenOfType(tokens []Token, start int, tokenType TokenType) int

FindTokenOfType finds the first token of the given type starting at index.

func FuzzyMatch

func FuzzyMatch(word, target string, threshold float64) bool

FuzzyMatch returns true if word matches target with Jaro-Winkler >= threshold or if they match phonetically.

func IsCommandKeyword

func IsCommandKeyword(w string) bool

IsCommandKeyword returns true if the word is a command keyword that indicates the start of a new command context. Used by the slack mechanism to avoid searching past command boundaries.

func IsDigit

func IsDigit(s string) bool

IsDigit returns true if the string is a single digit (0-9).

func IsFillerWord

func IsFillerWord(w string) bool

IsFillerWord returns true if the word should be ignored during parsing.

func IsNumber

func IsNumber(s string) bool

IsNumber returns true if the string is a sequence of digits.

func IsSingleDigit19

func IsSingleDigit19(s string) bool

IsSingleDigit19 returns true if the string is a single digit 1-9.

func IsSpellingTrigger

func IsSpellingTrigger(word string) bool

IsSpellingTrigger returns true if the word introduces a spelling correction.

func JaroWinkler

func JaroWinkler(s1, s2 string) float64

JaroWinkler computes the Jaro-Winkler similarity between two strings. Returns a value between 0.0 (no similarity) and 1.0 (identical). Jaro-Winkler gives higher weight to strings that match from the beginning.

func MatchCallsign

func MatchCallsign(tokens []Token, aircraft map[string]Aircraft) (CallsignMatch, []Token)

MatchCallsign attempts to match tokens to an aircraft callsign. Tries starting at different positions to handle garbage words at the beginning. Returns the best match and remaining tokens after the callsign.

Matching proceeds using a declarative pattern-based approach:

  1. Weight class filtering - if "heavy"/"super" found, filter aircraft first
  2. Pattern-based matching - uses DSL patterns in priority order

func NormalizeTranscript

func NormalizeTranscript(transcript string) []string

NormalizeTranscript normalizes a raw STT transcript for parsing. Handles phonetic corrections and cleanup. Disregard handling is done at a higher level after callsign matching.

func ParseCommands

func ParseCommands(tokens []Token, ac Aircraft) ([]string, float64)

ParseCommands parses tokens into a sequence of commands using the registered command templates.

func ParseDigit

func ParseDigit(s string) int

ParseDigit converts a digit string to int. Returns -1 on error.

func ParseNumber

func ParseNumber(s string) int

ParseNumber converts a digit sequence to int. Returns -1 on error.

func PhoneticMatch

func PhoneticMatch(w1, w2 string) bool

PhoneticMatch returns true if two words are phonetically similar.

func RegisterCallsignPattern

func RegisterCallsignPattern(template string, opts ...CallsignPatternOption)

RegisterCallsignPattern registers a callsign matching pattern.

func StopCapture

func StopCapture() []string

StopCapture stops capturing and returns the captured lines.

func TokensToString

func TokensToString(tokens []Token) string

TokensToString converts tokens back to a space-separated string (for debugging).

func ValidateCommandsForState

func ValidateCommandsForState(commands []string, state string) []string

ValidateCommandsForState filters commands based on aircraft state likelihood. Returns commands that are appropriate for the current state.

Types

type Aircraft

type Aircraft struct {
	Callsign            string
	AircraftType        string                       // Aircraft type code (e.g., "C172", "BE36")
	Fixes               map[string]string            // spoken name -> fix ID
	CandidateApproaches map[string]string            // spoken name -> approach ID
	ApproachFixes       map[string]map[string]string // approach ID -> (spoken name -> fix ID)
	AssignedApproach    string
	SID                 string
	STAR                string
	Altitude            int                        // Current altitude in feet
	State               string                     // "departure", "arrival", "cleared approach", "overflight", "vfr flight following"
	ControllerFrequency string                     // Current controller position the aircraft is tuned to
	TrackingController  string                     // Controller tracking this aircraft (from flight plan)
	AddressingForm      sim.CallsignAddressingForm // How this aircraft was addressed (based on which key matched)
	LAHSORunways        []string                   // Runways that intersect the approach runway (for LAHSO matching)
}

Aircraft holds context for a single aircraft for STT processing.

type CallsignMatch

type CallsignMatch struct {
	Callsign       string                     // The matched ICAO callsign (e.g., "AAL5936")
	SpokenKey      string                     // The key in the aircraft context map
	Confidence     float64                    // Match confidence (0.0-1.0)
	Consumed       int                        // Number of tokens consumed for the callsign
	AddressingForm sim.CallsignAddressingForm // How the callsign was addressed (full vs type+trailing3)
}

CallsignMatch represents a matched callsign with confidence score.

type CallsignPattern

type CallsignPattern struct {
	Name            string                                    // Human-readable name for debugging
	Template        string                                    // Original template string
	Priority        int                                       // Higher priority patterns are tried first
	Matchers        []callsignMatcher                         // Parsed from template
	MinScore        float64                                   // Minimum score to accept a match
	FixedConfidence float64                                   // If > 0, use this confidence instead of computed
	ScoringFunc     func(result *callsignMatchResult) float64 // Custom scoring function
	Condition       func(Aircraft) bool                       // Pre-filter aircraft (returns true to include)
	RequireUnique   bool                                      // Only accept if exactly one aircraft matches
}

CallsignPattern represents a declarative callsign matching rule.

type CallsignPatternOption

type CallsignPatternOption func(*CallsignPattern)

CallsignPatternOption configures a callsign pattern registration.

func WithCallsignConfidence

func WithCallsignConfidence(conf float64) CallsignPatternOption

WithCallsignConfidence sets a fixed confidence value for matches from this pattern.

func WithCallsignMinScore

func WithCallsignMinScore(score float64) CallsignPatternOption

WithCallsignMinScore sets the minimum score threshold for accepting a match.

func WithCallsignName

func WithCallsignName(name string) CallsignPatternOption

WithCallsignName sets a human-readable name for the pattern.

func WithCallsignPriority

func WithCallsignPriority(priority int) CallsignPatternOption

WithCallsignPriority sets the pattern priority (higher = tried first).

func WithCallsignRequire

func WithCallsignRequire(fn func(Aircraft) bool) CallsignPatternOption

WithCallsignRequire sets a condition function to pre-filter aircraft.

func WithCallsignRequireUnique

func WithCallsignRequireUnique() CallsignPatternOption

WithCallsignRequireUnique requires exactly one aircraft to match.

func WithCallsignScoring

func WithCallsignScoring(fn func(*callsignMatchResult) float64) CallsignPatternOption

WithCallsignScoring sets a custom scoring function.

type CommandMatch

type CommandMatch struct {
	Command    string  // The output command string
	Confidence float64 // Match confidence
	Consumed   int     // Tokens consumed
	IsThen     bool    // Whether this is a "then" sequenced command
	IsSayAgain bool    // True if this is a partial match that needs say-again
}

CommandMatch represents a matched command.

type CommandOption

type CommandOption func(*sttCommand)

CommandOption configures a command registration.

func WithName

func WithName(name string) CommandOption

WithName sets a human-readable name for debugging.

func WithPriority

func WithPriority(p int) CommandOption

WithPriority sets the command priority.

func WithSayAgainOnFail

func WithSayAgainOnFail() CommandOption

WithSayAgainOnFail enables emitting SAYAGAIN when a type parser fails. Use this for commands where the controller clearly requested something specific (like "expect approach") and we should ask for clarification.

func WithThenVariant

func WithThenVariant(format string) CommandOption

WithThenVariant sets the format for "then" sequenced commands.

type LogBuffer

type LogBuffer struct {
	// contains filtered or unexported fields
}

LogBuffer captures STT processing logs for bug reports.

func StartCapture

func StartCapture() *LogBuffer

StartCapture begins capturing log lines to a buffer. Returns the buffer that will collect the logs.

type ParseResult

type ParseResult struct {
	Callsign       string
	Commands       []string
	Confidence     float64
	CallsignConf   float64
	CommandConf    float64
	ValidationConf float64
	Errors         []string
}

ParseResult holds detailed parsing results for debugging/testing.

type Token

type Token struct {
	Original string    // Original text from STT (before normalization)
	Text     string    // Normalized text
	Type     TokenType // Token type
	Value    int       // Numeric value if applicable (-1 if not)
}

Token represents a normalized piece of the transcript.

func Tokenize

func Tokenize(words []string) []Token

Tokenize converts normalized words into structured tokens. Handles number merging, altitude patterns, and type detection.

type TokenType

type TokenType int

TokenType represents the type of a parsed token.

const (
	TokenWord TokenType = iota
	TokenNumber
	TokenAltitude // Specifically identified as an altitude (e.g., "8 thousand")
	TokenFix      // Matched against aircraft fixes
	TokenApproach // Matched against candidate approaches
	TokenCallsign // Part of callsign
	TokenICAO     // Airline ICAO code
)

type Transcriber

type Transcriber struct {
	// contains filtered or unexported fields
}

Transcriber converts speech transcripts to aircraft control commands using local algorithmic parsing with fast fuzzy matching.

func NewTranscriber

func NewTranscriber(lg *log.Logger) *Transcriber

NewTranscriber creates a new STT transcriber.

func (*Transcriber) BuildAircraftContext

func (p *Transcriber) BuildAircraftContext(
	state *sim.UserState,
	userTCW sim.TCW,
) map[string]Aircraft

BuildAircraftContext creates the STT aircraft context from simulation state.

func (*Transcriber) DecodeCommandsForCallsign

func (p *Transcriber) DecodeCommandsForCallsign(
	aircraft map[string]Aircraft,
	transcript string,
	callsign string,
) (string, error)

DecodeCommandsForCallsign parses commands from a transcript for a known callsign. This is used when the controller repeats a command without saying the callsign after an aircraft replied "AGAIN". It skips callsign matching and directly parses the entire transcript as commands for the specified aircraft. Returns one of:

  • "{commands}" for successfully parsed commands
  • "AGAIN" if no commands could be parsed
  • "" if transcript is empty

func (*Transcriber) DecodeFromState

func (p *Transcriber) DecodeFromState(
	state *sim.UserState,
	userTCW sim.TCW,
	transcript string,
) (string, error)

DecodeFromState decodes a transcript using the simulation state directly. It builds the aircraft context internally from the provided state. Only tracks on the user's frequency (ControllerFrequency) are included in the context.

func (*Transcriber) DecodeTranscript

func (p *Transcriber) DecodeTranscript(
	aircraft map[string]Aircraft,
	transcript string,
	controllerRadioName string,
) (string, error)

DecodeTranscript converts a speech transcript to aircraft control commands. It returns one of:

  • "{CALLSIGN} {CMD1} {CMD2} ..." for successful parsing
  • "{CALLSIGN} AGAIN" if callsign identified but commands unclear
  • "" if transcript is empty, only contains position identification, or no callsign could be matched

Commands may include SAYAGAIN/TYPE for partial parses where keywords were recognized but the associated value couldn't be extracted (e.g., "fly heading blark" would return "SAYAGAIN/HEADING"). Valid types are: HEADING, ALTITUDE, SPEED, APPROACH, TURN, SQUAWK, FIX. When combined with other commands, e.g., "{CALLSIGN} C50 SAYAGAIN/HEADING", the aircraft will execute the valid commands and ask for clarification on the missed part.

controllerRadioName is the user's controller radio name (e.g., "New York Departure") used to detect position identification phrases. Pass empty string if not available.

func (*Transcriber) GetUsageStats

func (p *Transcriber) GetUsageStats() string

GetUsageStats returns usage statistics for this provider.

func (*Transcriber) ParseTranscriptDetailed

func (p *Transcriber) ParseTranscriptDetailed(
	aircraft map[string]Aircraft,
	transcript string,
) ParseResult

ParseTranscriptDetailed provides detailed parsing results for testing.

type ValidationResult

type ValidationResult struct {
	ValidCommands []string // Commands that passed validation
	Confidence    float64  // Adjusted confidence based on validation
	Errors        []string // Validation error messages (for debugging)
}

ValidationResult holds the result of command validation.

func ValidateCommands

func ValidateCommands(commands []string, ac Aircraft) ValidationResult

ValidateCommands validates a list of commands against aircraft state. Returns filtered commands and adjusted confidence.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL