This directory provides the TensorFlow Lite for Microcontrollers (TFLM) classification module (TFLMCLY) for Sound Open Firmware (SOF), including integration with MFCC feature extraction, mtrace logging, IPC host notifications, and Key Phrase Buffer (KPB) Wake-on-Voice (WoV) trigger infrastructure.
The TFLM module evaluates pre-trained micro speech neural network models inline within the SOF audio processing graph. It receives pre-processed audio feature tensors (e.g. 40-bin mel spectrograms from the MFCC component), runs model inference, logs keyword detections to mtrace, issues IPC4 notifications to the host audio driver, and signals the KPB module to drain buffered pre-keyword audio for Wake-on-Voice.
To allow continuous keyword evaluation without streaming audio to the host until a keyword is detected, the pipeline separates real-time keyword detection from host PCM draining via KPB:
graph TD
DAI[HDA Mic DAI] --> Gain[Gain Component]
Gain --> KPB[KPB Buffer Module]
subgraph "Real-Time Detection Path (KPB Pin 1)"
KPB -- Live Audio Stream --> SRC[SRC: 48kHz -> 16kHz]
SRC --> MFCC[MFCC Feature Extractor]
MFCC -- 40-bin Mel Tensors --> TFLM[TFLM Classifier: tflmcly]
TFLM --> VSink[Virtual Sink: virtual.tflm_sink]
end
subgraph "Host Draining Path (KPB Pin 2)"
KPB -- History Draining Stream --> Host[Host Copier: PCM Capture]
end
TFLM -- "1. Log to mtrace (comp_info)" --> MTrace[mtrace / SOF Trace Log]
TFLM -- "2. IPC4 Host Notification" --> IPC[Host Audio Driver]
TFLM -- "3. KPB_EVENT_BEGIN_DRAINING (notifier_event)" --> KPB
-
Continuous Real-Time Listening:
- Live microphone audio is captured by the HDA DAI and passed into
KPB(kpb.2.1). - KPB Output Pin 1 continuously streams audio to
SRC(resampling 48kHz$\to$ 16kHz),MFCC(generating 40-binint8_tmel spectrogram features), andTFLM(tflmcly.1.1). - KPB stores the raw PCM audio continuously in its circular history buffer (e.g. 2100ms – 3000ms history).
- Live microphone audio is captured by the HDA DAI and passed into
-
Inference & Keyword Detection:
-
tflm_process()feeds 1960-byte feature tensors ($40 \text{ features} \times 49 \text{ windows}$ ) into the Micro Speech TFLM interpreter ([1, 49, 40]int8_tinput tensor). - Upon
TF_ProcessClassify(), predictions are evaluated across categories:-
0:silence -
1:unknown -
2:yes(Keyword) -
3:no(Keyword)
-
-
-
Wake-on-Voice Trigger & Notification: When a keyword (
yesorno) is detected with$\ge 0.70$ confidence:-
mtrace Logging: Logs detection with keyword label and confidence score via
comp_info():"TFLM keyword detected: yes (confidence 0.852)" -
Host IPC Notification: Sends an IPC4 module notification (
SOF_IPC4_MODULE_NOTIFICATION) to inform the host driver. -
KPB Draining Signal: Fires a system notification event (
NOTIFIER_ID_KPB_CLIENT_EVT) withKPB_EVENT_BEGIN_DRAINING. -
Host PCM Draining: KPB opens Output Pin 2 to
host-copier, draining pre-keyword history buffer audio followed by live mic audio to the host capture stream.
-
mtrace Logging: Logs detection with keyword label and confidence score via
Defines Class.Widget."tflmcly":
- UUID:
42:c6:1d:c5:e1:a2:df:48:a4:90:e2:74:8c:b6:36:3e(c51dc642-a2e1-48df-a490e2748cb6363e) - Type:
effect
Instantiates the real-time detection graph:
Object.Widget {
virtual."1" { name "virtual.tflm_sink" }
src."1" { ... }
mfcc."1" { ... }
tflmcly."1" { ... }
}Instantiates the complete HDA Mic WoV topology with dual-path KPB routing:
Object.Base.route [
# DAI -> Gain -> KPB
{ source "dai-copier.HDA.Analog.capture"; sink "gain.2.1" }
{ source "gain.2.1"; sink "kpb.2.1" }
# KPB Pin 1 -> Real-time Detection Path
{ source "kpb.2.1"; sink "src.1.1" }
# KPB Pin 2 -> Host WoV Draining Path
{ source "kpb.2.1"; sink "host-copier.0.capture" }
]Build sof-hda-tflm.tplg using the Topology v2 pre-processor:
ALSA_CONFIG_DIR=tools/topology/topology2 \
tools/bin/alsatplg \
-I tools/topology/topology2/ \
-p -c tools/topology/topology2/sof-hda-tflm.conf \
-o build/sof-hda-tflm.tplgDecode and verify the compiled .tplg binary:
tools/bin/alsatplg -d build/sof-hda-tflm.tplg -o decoded.txt
grep -A 20 "SectionGraph" decoded.txtExpected graph output:
SectionGraph {
set0 {
gain.2.1 <- dai-copier.HDA.Analog.capture
kpb.2.1 <- gain.2.1
src.1.1 <- kpb.2.1 (Real-Time Detection Path)
host-copier.0.capture <- kpb.2.1 (Host WoV Draining Path)
}
set1 {
mfcc.1.1 <- src.1.1
tflmcly.1.1 <- mfcc.1.1
virtual.tflm_sink <- tflmcly.1.1 (Detection Sink Termination)
}
}
- tflm-classify.c: SOF module adapter implementation for TFLM.
- speech.cc / speech.h: TFLM C++ API bridge & micro speech tensor wrapper.
- tflm.conf: Topology v2 widget class definition.
- host-gateway-src-mfcc-tflm-capture.conf: Detection pipeline template.
- sof-hda-tflm.conf: Top-level WoV topology configuration.