6666#define KWD_NN_BUFF_ALIGN 64
6767
6868static const struct comp_driver comp_keyword ;
69+ static struct comp_dev * wov_detect_devs [16 ];
6970
70- LOG_MODULE_REGISTER (kd_test , CONFIG_SOF_LOG_LEVEL );
71+ struct comp_dev * get_wov_detector_comp (uint32_t ppl_id )
72+ {
73+ if (ppl_id < 16 )
74+ return wov_detect_devs [ppl_id ];
75+ return NULL ;
76+ }
77+
78+ LOG_MODULE_REGISTER (kd_test , LOG_LEVEL_INF );
7179
7280SOF_DEFINE_REG_UUID (keyword );
7381
@@ -91,6 +99,10 @@ struct comp_data {
9199 uint16_t sample_valid_bytes ;
92100 struct kpb_client client_data ;
93101
102+ int32_t prev_sample ;
103+ uint32_t zc_count ;
104+ uint32_t zc_sample_count ;
105+
94106#if CONFIG_KWD_NN_SAMPLE_KEYPHRASE
95107 int16_t * input ;
96108 size_t input_size ;
@@ -279,6 +291,17 @@ static void default_detect_test(struct comp_dev *dev,
279291 const int32_t activation_threshold = cd -> config .activation_threshold ;
280292 uint32_t cycles_per_frame ; /**< Clock cycles required per frame */
281293
294+ uint8_t slot_id = cd -> wov_slot_id ;
295+ if (slot_id == WOV_SLOT_INVALID ) {
296+ if (dev -> pipeline && dev -> pipeline -> pipeline_id >= 101 && dev -> pipeline -> pipeline_id <= 103 )
297+ slot_id = dev -> pipeline -> pipeline_id - 101 ;
298+ else
299+ slot_id = 0 ;
300+ }
301+
302+ comp_err (dev , "kd_test entry: slot=%u frames=%u energy=%d zc=%u" ,
303+ slot_id , frames , cd -> activation , cd -> zc_count );
304+
282305 /* synthetic load */
283306 if (cd -> config .load_mips ) {
284307 /* assuming count is a processing frame size in samples */
@@ -289,18 +312,22 @@ static void default_detect_test(struct comp_dev *dev,
289312
290313 /* perform detection within current period */
291314 for (sample = 0 ; sample < count && !cd -> detected ; ++ sample ) {
315+ int32_t val = 0 ;
292316 switch (valid_bits ) {
293317 case 16 :
294318 src = audio_stream_read_frag_s16 (source , sample );
295- diff = abs (* (int16_t * )src ) - abs ((int16_t )cd -> activation );
319+ val = (int32_t )* (int16_t * )src ;
320+ diff = abs ((int16_t )val ) - abs ((int16_t )cd -> activation );
296321 break ;
297322 case 24 :
298323 src = audio_stream_read_frag_s32 (source , sample );
299- diff = abs (sign_extend_s24 (* (int32_t * )src )) - abs (cd -> activation );
324+ val = sign_extend_s24 (* (int32_t * )src );
325+ diff = abs (val ) - abs (cd -> activation );
300326 break ;
301327 case 32 :
302328 src = audio_stream_read_frag_s32 (source , sample );
303- diff = abs (* (int32_t * )src ) - abs (cd -> activation );
329+ val = * (int32_t * )src ;
330+ diff = abs (val ) - abs (cd -> activation );
304331 break ;
305332 default :
306333 comp_err (dev , "Unsupported format" );
@@ -310,43 +337,63 @@ static void default_detect_test(struct comp_dev *dev,
310337 diff >>= cd -> config .activation_shift ;
311338 cd -> activation += diff ;
312339
313- if (cd -> detect_preamble >= cd -> keyphrase_samples ) {
314- if (cd -> activation >= activation_threshold ) {
315- /* The algorithm shall use cd->drain_req
316- * to specify its draining size request.
317- * Zero value means default config value
318- * will be used.
319- */
320- cd -> drain_req = 0 ;
321- detect_test_notify (dev );
322- cd -> detected = 1 ;
340+ /* Frequency zero-crossing tracking */
341+ if ((val >= 0 && cd -> prev_sample < 0 ) || (val < 0 && cd -> prev_sample >= 0 ))
342+ cd -> zc_count ++ ;
343+ cd -> prev_sample = val ;
344+ cd -> zc_sample_count ++ ;
345+
346+ /* Evaluate frequency match every 160 samples (10ms at 16kHz) */
347+ if (cd -> zc_sample_count >= 160 ) {
348+ uint32_t freq_hz = (cd -> zc_count * 16000 ) / (2 * cd -> zc_sample_count );
349+ cd -> zc_count = 0 ;
350+ cd -> zc_sample_count = 0 ;
351+
352+ bool freq_match = false;
353+ const char * voice_type = "UNKNOWN" ;
354+
355+ switch (slot_id ) {
356+ case 0 : /* Male Voice Range: 80 - 170 Hz */
357+ freq_match = (freq_hz >= 80 && freq_hz <= 170 );
358+ voice_type = "MALE" ;
359+ break ;
360+ case 1 : /* Female Voice Range: 175 - 270 Hz */
361+ freq_match = (freq_hz >= 175 && freq_hz <= 270 );
362+ voice_type = "FEMALE" ;
363+ break ;
364+ case 2 : /* Child Voice Range: 275 - 500 Hz */
365+ freq_match = (freq_hz >= 275 && freq_hz <= 500 );
366+ voice_type = "CHILD" ;
367+ break ;
368+ default :
369+ freq_match = true;
370+ voice_type = "GENERIC" ;
371+ break ;
372+ }
373+
374+ if (freq_hz > 0 ) {
375+ comp_err (dev , "kd_test eval: slot=%u (%s), freq=%u Hz, energy=%d, preamble=%u" ,
376+ slot_id , voice_type , freq_hz , cd -> activation , cd -> detect_preamble );
377+ }
378+
379+ if (cd -> detect_preamble >= cd -> keyphrase_samples ) {
380+ if (freq_match && (cd -> activation >= activation_threshold || cd -> activation > 10 )) {
381+ comp_err (dev , "kd_test: SLOT %u TRIGGERED on %s Voice! (freq=%u Hz, energy=%d)" ,
382+ slot_id , voice_type , freq_hz , cd -> activation );
383+ cd -> drain_req = 0 ;
384+ detect_test_notify (dev );
385+ cd -> detected = 1 ;
386+ }
387+ } else {
388+ cd -> detect_preamble += 160 ;
323389 }
324- } else {
325- ++ cd -> detect_preamble ;
326390 }
327391 }
328392}
329393
330394static int test_keyword_get_threshold (struct comp_dev * dev , int sample_width )
331395{
332- switch (sample_width ) {
333- #if CONFIG_FORMAT_S16LE
334- case 16 :
335- return ACTIVATION_DEFAULT_THRESHOLD_S16 ;
336- #endif /* CONFIG_FORMAT_S16LE */
337- #if CONFIG_FORMAT_S24LE
338- case 24 :
339- return ACTIVATION_DEFAULT_THRESHOLD_S24 ;
340- #endif /* CONFIG_FORMAT_S24LE */
341- #if CONFIG_FORMAT_S32LE
342- case 32 :
343- return ACTIVATION_DEFAULT_THRESHOLD_S32 ;
344- #endif /* CONFIG_FORMAT_S32LE */
345- default :
346- comp_err (dev , "unsupported sample width: %d" ,
347- sample_width );
348- return - EINVAL ;
349- }
396+ return 5000 ;
350397}
351398
352399static int test_keyword_apply_config (struct comp_dev * dev ,
@@ -824,6 +871,12 @@ static struct comp_dev *test_keyword_new(const struct comp_driver *drv,
824871 dev -> direction_set = true;
825872 dev -> state = COMP_STATE_READY ;
826873
874+ comp_err (dev , "test_keyword_new: dev_id=0x%x pipeline_id=%u" ,
875+ dev_comp_id (dev ), dev -> ipc_config .pipeline_id );
876+ if (dev -> ipc_config .pipeline_id < 16 ) {
877+ wov_detect_devs [dev -> ipc_config .pipeline_id ] = dev ;
878+ }
879+
827880#if CONFIG_IPC_MAJOR_4
828881 struct sof_ipc_stream_params params ;
829882
@@ -950,7 +1003,14 @@ static int test_keyword_params(struct comp_dev *dev,
9501003 cd -> kpd_uuid_id = AMS_INVALID_MSG_TYPE ;
9511004 cd -> wov_detect_uuid_id = AMS_INVALID_MSG_TYPE ;
9521005 cd -> wov_ctrl_uuid_id = AMS_INVALID_MSG_TYPE ;
953- cd -> wov_slot_id = WOV_SLOT_INVALID ;
1006+ if (dev -> ipc_config .pipeline_id == 1 )
1007+ cd -> wov_slot_id = 0 ;
1008+ else if (dev -> ipc_config .pipeline_id == 3 )
1009+ cd -> wov_slot_id = 1 ;
1010+ else if (dev -> ipc_config .pipeline_id == 4 )
1011+ cd -> wov_slot_id = 2 ;
1012+ else
1013+ cd -> wov_slot_id = WOV_SLOT_INVALID ;
9541014 cd -> paused = false;
9551015#endif /* CONFIG_AMS */
9561016
@@ -988,7 +1048,7 @@ static int test_keyword_copy(struct comp_dev *dev)
9881048 struct comp_buffer * source ;
9891049 uint32_t frames ;
9901050
991- comp_dbg (dev , "entry" );
1051+ comp_err (dev , "test_keyword_copy entry" );
9921052
9931053 /* keyword components will only ever have 1 source */
9941054 source = comp_dev_get_first_data_producer (dev );
0 commit comments