phoneme-wake-word / engine_c /pww_decoder.h
JoelAjitesh's picture
Phoneme wake word engine: student+teacher models, INT8 export, C engine, enrollment tooling
f6aec75 verified
Raw
History Blame Contribute Delete
1.8 kB
// Keyword-filler Viterbi spotter over streaming logits - C port of
// phoneme_engine/decoder.py (KeywordSpotter). Same states, gates and
// scoring; consumes raw logits (only within-frame differences matter).
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define PWW_DEC_MAX_PHONES 24
#define PWW_DEC_MAX_STATES (3 * PWW_DEC_MAX_PHONES + 1)
#define PWW_DEC_MAX_ALLOWED 3
typedef struct {
int n_phones;
int n_states;
uint8_t labels[PWW_DEC_MAX_STATES]; // class id per state
uint8_t n_allowed[PWW_DEC_MAX_STATES];
uint8_t allowed[PWW_DEC_MAX_STATES][PWW_DEC_MAX_ALLOWED];
int8_t preds[PWW_DEC_MAX_STATES][2]; // predecessor ids, -1 unused
uint8_t entry[PWW_DEC_MAX_STATES];
int min_dur, max_dur;
float threshold;
float strong_margin; // 1.5
float strong_ratio; // 0.5
int refractory; // frames
// runtime state
float rel[PWW_DEC_MAX_STATES];
int32_t start[PWW_DEC_MAX_STATES];
int32_t pframes[PWW_DEC_MAX_STATES];
int32_t strong[PWW_DEC_MAX_STATES];
int cooldown;
int32_t t;
float best_seen; // best gate-passing score since last clear (diag)
} pww_spotter_t;
// phone_ids: sequence of class ids (1..39, from PWW_PHONES order +1).
// Returns 0 on success, -1 if too long/short.
int pww_spotter_init(pww_spotter_t *sp, const uint8_t *phone_ids,
int n_phones, float threshold);
void pww_spotter_reset(pww_spotter_t *sp);
// One frame of logits (PWW_NUM_CLASSES floats). Returns 1 and fills
// score/dur when the keyword fires, else 0.
int pww_spotter_step(pww_spotter_t *sp, const float *logits,
float *score_out, int *dur_out);
#ifdef __cplusplus
}
#endif