Five tasks: scaffold csproj, copy WakewordModel + models with Reset(),
write Program.cs with the four-state machine, write bin/probe-cs-3
deploy script, and hardware verification on the Pi.
State machine on a single persistent input stream: IDLE → BEEPING →
RECORDING → PLAYBACK → IDLE. Detector gated during non-IDLE states;
WakewordModel.Reset() called on IDLE re-entry to clear stale ring
buffers and re-arm the warmup guard.
Add PrintShapes() helper that writes input/output name, shape, and dtype
for each InferenceSession to stderr at construction time, prefixed with
[wakeword-model]. Called after each of the three session creations so the
geometry is visible on first run without grep-ing logs.
Also rephrase the stale "FIXED:" comment on the mel Dimensions[2] indexing
to plain explanatory text that describes the current invariant.
Replaces the Task 3 smoke-test Program.cs with the full inference loop:
- PA_ALSA_PLUGHW=1 and ORT_LOGGING_LEVEL=3 via both Environment.SetEnvironmentVariable
and Libc.setenv (P/Invoke) per the Test 1 findings.md env-var gotcha.
- OrtEnv.CreateInstanceWithOptions with ORT_LOGGING_LEVEL_ERROR to suppress
early GPU-discovery warnings from device_discovery.cc in ORT 1.26.0
(the env var alone does not silence these; CreateInstanceWithOptions does).
- Callback-driven PortAudio input stream at 16 kHz / Int16 / 1280 frames/block.
- BlockingCollection<short[]>(16) queue; per-call new short[1280] allocation (no races).
- Main loop: Take() -> WakewordModel.Predict() -> threshold >= 0.5 with 1.0s cooldown
-> DETECTED alexa score=... t=...s. No beep (Task 5 adds it).
- Console.CancelKeyPress -> cts.Cancel() -> graceful stream.Stop() + model.Dispose()
+ PortAudio.Terminate().
Ports openwakeword 0.6.0's AudioFeatures._streaming_features() and
Model.predict() to C# / Microsoft.ML.OnnxRuntime 1.26.0.
Bug fixed vs plan: actual melspectrogram.onnx output shape is
(1, 1, n_frames, 32) — n_frames lives at Dimensions[2], not [1].
Access pattern corrected to melOut[0, 0, f, b].
Smoke test on Pi: 25/50 non-zero silence scores, max ≈ 0.000064
(matches Python reference: 45/50 non-zero, same magnitude).
"Predict pipeline ran without throwing." confirmed.
Models sourced from openwakeword==0.6.0 on the Pi (alexa_v0.1.onnx
vendored as alexa.onnx). ORT 1.26.0 loads all three on linux-arm64
self-contained publish; libonnxruntime.so confirmed in publish dir.
SHA-256:
melspectrogram.onnx ba2b0e0f8b7b875369a2c89cb13360ff53bac436f2895cced9f479fa65eb176f
embedding_model.onnx 70d164290c1d095d1d4ee149bc5e00543250a7316b59f31d056cff7bd3075c1f
alexa.onnx 6ff566a01d12670e8d9e3c59da32651db1575d17272a601b7f8a39283dfbae3e