1 /*
2 * Copyright 2008-2014 Arsen Chaloyan
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * $Id: apt_nlsml_doc.c 2177 2014-09-12 05:36:20Z achaloyan@gmail.com $
17 */
18
19 #include <stdlib.h>
20 #ifdef WIN32
21 #pragma warning(disable: 4127)
22 #endif
23 #include <apr_ring.h>
24
25 #include "apt_nlsml_doc.h"
26 #include "apt_log.h"
27
28 /** NLSML result */
29 struct nlsml_result_t
30 {
31 /** List of interpretations */
32 APR_RING_HEAD(apt_ir_head_t, nlsml_interpretation_t) interpretations;
33 /** List of enrollment results */
34 APR_RING_HEAD(apt_er_head_t, nlsml_enrollment_result_t) enrollment_results;
35 /** List of verification results */
36 APR_RING_HEAD(apt_vr_head_t, nlsml_verification_result_t) verification_results;
37
38 /** Optional grammar attribute */
39 const char *grammar;
40 };
41
42 /** NLSML instance */
43 struct nlsml_instance_t
44 {
45 /** Ring entry */
46 APR_RING_ENTRY(nlsml_instance_t) link;
47
48 /** Instance element */
49 apr_xml_elem *elem;
50 };
51
52 /** NLSML input */
53 struct nlsml_input_t
54 {
55 /** Input element */
56 apr_xml_elem *elem;
57 /** Input mode attribute [default: "speech"] */
58 const char *mode;
59 /** Confidence attribute [default: 1.0] */
60 float confidence;
61 /** Timestamp-start attribute */
62 const char *timestamp_start;
63 /** Timestamp-end attribute */
64 const char *timestamp_end;
65 };
66
67 /** NLSML interpretation */
68 struct nlsml_interpretation_t
69 {
70 /** Ring entry */
71 APR_RING_ENTRY(nlsml_interpretation_t) link;
72
73 /** List of instances */
74 APR_RING_HEAD(apt_head_t, nlsml_instance_t) instances;
75 /** Input [0..1] */
76 nlsml_input_t *input;
77
78 /** Confidence attribute [default: 1.0] */
79 float confidence;
80 /** Optional grammar attribute */
81 const char *grammar;
82 };
83
84 struct nlsml_enrollment_result_t
85 {
86 /** Ring entry */
87 APR_RING_ENTRY(nlsml_enrollment_result_t) link;
88 };
89
90 struct nlsml_verification_result_t
91 {
92 /** Ring entry */
93 APR_RING_ENTRY(nlsml_verification_result_t) link;
94 };
95
96 /** Load NLSML document */
nlsml_doc_load(const char * data,apr_size_t length,apr_pool_t * pool)97 static apr_xml_doc* nlsml_doc_load(const char *data, apr_size_t length, apr_pool_t *pool)
98 {
99 apr_xml_parser *parser;
100 apr_xml_doc *doc = NULL;
101 const apr_xml_elem *root;
102
103 if(!data || !length) {
104 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No NLSML data available");
105 return NULL;
106 }
107
108 /* create XML parser */
109 parser = apr_xml_parser_create(pool);
110 if(apr_xml_parser_feed(parser,data,length) != APR_SUCCESS) {
111 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to feed NLSML input to the parser");
112 return NULL;
113 }
114
115 /* done with XML tree creation */
116 if(apr_xml_parser_done(parser,&doc) != APR_SUCCESS) {
117 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to terminate NLSML parsing");
118 return NULL;
119 }
120
121 if(!doc || !doc->root) {
122 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No NLSML root element");
123 return NULL;
124 }
125 root = doc->root;
126
127 /* NLSML validity check: root element must be <result> */
128 if(strcmp(root->name,"result") != 0) {
129 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unexpected NLSML root element <%s>",root->name);
130 return NULL;
131 }
132
133 return doc;
134 }
135
136 /** Parse confidence value */
nlsml_confidence_parse(const char * str)137 static float nlsml_confidence_parse(const char *str)
138 {
139 float confidence = (float) atof(str);
140 if(confidence > 1.0)
141 confidence /= 100;
142
143 return confidence;
144 }
145
146 /** Parse <instance> element */
nlsml_instance_parse(apr_xml_elem * elem,apr_pool_t * pool)147 static nlsml_instance_t* nlsml_instance_parse(apr_xml_elem *elem, apr_pool_t *pool)
148 {
149 /* Initialize instance */
150 nlsml_instance_t *instance = apr_palloc(pool, sizeof(*instance));
151 APR_RING_ELEM_INIT(instance,link);
152 instance->elem = elem;
153
154 return instance;
155 }
156
157 /** Parse <input> element */
nlsml_input_parse(apr_xml_elem * elem,apr_pool_t * pool)158 static nlsml_input_t* nlsml_input_parse(apr_xml_elem *elem, apr_pool_t *pool)
159 {
160 const apr_xml_attr *xml_attr;
161 /* Initialize input */
162 nlsml_input_t *input = apr_palloc(pool, sizeof(*input));
163 input->elem = elem;
164 input->mode = "speech";
165 input->confidence = 1.0;
166 input->timestamp_start = NULL;
167 input->timestamp_end = NULL;
168
169 /* Find input attributes */
170 for(xml_attr = elem->attr; xml_attr; xml_attr = xml_attr->next) {
171 if(strcasecmp(xml_attr->name, "mode") == 0) {
172 input->mode = xml_attr->value;
173 }
174 else if(strcasecmp(xml_attr->name, "confidence") == 0) {
175 input->confidence = nlsml_confidence_parse(xml_attr->value);
176 }
177 else if(strcasecmp(xml_attr->name, "timestamp-start") == 0) {
178 input->timestamp_start = xml_attr->value;
179 }
180 else if(strcasecmp(xml_attr->name, "timestamp-end") == 0) {
181 input->timestamp_end = xml_attr->value;
182 }
183 else {
184 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown attribute '%s' for <%s>", xml_attr->name, elem->name);
185 }
186 }
187
188 return input;
189 }
190
191 /** Parse <interpretation> element */
nlsml_interpretation_parse(apr_xml_elem * elem,apr_pool_t * pool)192 static nlsml_interpretation_t* nlsml_interpretation_parse(apr_xml_elem *elem, apr_pool_t *pool)
193 {
194 apr_xml_elem *child_elem;
195 const apr_xml_attr *xml_attr;
196 nlsml_instance_t *instance;
197 nlsml_input_t *input;
198
199 /* Initialize interpretation */
200 nlsml_interpretation_t *interpretation = apr_palloc(pool, sizeof(*interpretation));
201 APR_RING_ELEM_INIT(interpretation,link);
202 interpretation->grammar = NULL;
203 interpretation->confidence = 1.0;
204 interpretation->input = NULL;
205 APR_RING_INIT(&interpretation->instances, nlsml_instance_t, link);
206
207 /* Find optional grammar and confidence attributes */
208 for(xml_attr = elem->attr; xml_attr; xml_attr = xml_attr->next) {
209 if(strcasecmp(xml_attr->name, "grammar") == 0) {
210 interpretation->grammar = xml_attr->value;
211 }
212 else if(strcasecmp(xml_attr->name, "confidence") == 0) {
213 interpretation->confidence = nlsml_confidence_parse(xml_attr->value);
214 }
215 else {
216 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown attribute '%s' for <%s>", xml_attr->name, elem->name);
217 }
218 }
219
220 /* Find input and instance elements */
221 for(child_elem = elem->first_child; child_elem; child_elem = child_elem->next) {
222 if(strcasecmp(child_elem->name, "input") == 0) {
223 input = nlsml_input_parse(child_elem, pool);
224 if(input) {
225 interpretation->input = input;
226 }
227 }
228 else if(strcasecmp(child_elem->name, "instance") == 0) {
229 instance = nlsml_instance_parse(child_elem, pool);
230 if(instance) {
231 APR_RING_INSERT_TAIL(&interpretation->instances, instance, nlsml_instance_t, link);
232 }
233 }
234 else {
235 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown child element <%s> for <%s>", child_elem->name, elem->name);
236 }
237 }
238
239 return interpretation;
240 }
241
242 /** Parse <enrollment-result> element */
nlsml_enrollment_result_parse(const apr_xml_elem * elem,apr_pool_t * pool)243 static nlsml_enrollment_result_t* nlsml_enrollment_result_parse(const apr_xml_elem *elem, apr_pool_t *pool)
244 {
245 /* To be done */
246 return NULL;
247 }
248
249 /** Parse <verification-result> element */
nlsml_verification_result_parse(const apr_xml_elem * elem,apr_pool_t * pool)250 static nlsml_verification_result_t* nlsml_verification_result_parse(const apr_xml_elem *elem, apr_pool_t *pool)
251 {
252 /* To be done */
253 return NULL;
254 }
255
256 /** Parse NLSML result */
nlsml_result_parse(const char * data,apr_size_t length,apr_pool_t * pool)257 APT_DECLARE(nlsml_result_t*) nlsml_result_parse(const char *data, apr_size_t length, apr_pool_t *pool)
258 {
259 nlsml_result_t *result;
260 apr_xml_elem *root;
261 apr_xml_elem *child_elem;
262 const apr_xml_attr *xml_attr;
263 nlsml_interpretation_t *interpretation;
264 nlsml_enrollment_result_t *enrollment_result;
265 nlsml_verification_result_t *verification_result;
266 apr_xml_doc *doc;
267 /* Load XML document */
268 doc = nlsml_doc_load(data, length, pool);
269 if(!doc)
270 return NULL;
271
272 root = doc->root;
273
274 /* Initialize result */
275 result = apr_palloc(pool, sizeof(*result));
276 APR_RING_INIT(&result->interpretations, nlsml_interpretation_t, link);
277 APR_RING_INIT(&result->enrollment_results, nlsml_enrollment_result_t, link);
278 APR_RING_INIT(&result->verification_results, nlsml_verification_result_t, link);
279 result->grammar = NULL;
280
281 /* Find optional grammar attribute */
282 for(xml_attr = root->attr; xml_attr; xml_attr = xml_attr->next) {
283 if(strcasecmp(xml_attr->name, "grammar") == 0) {
284 result->grammar = xml_attr->value;
285 }
286 else {
287 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown attribute '%s' for <%s>", xml_attr->name, root->name);
288 }
289 }
290
291 /* Find interpretation, enrollment-result, or verification-result elements */
292 for(child_elem = root->first_child; child_elem; child_elem = child_elem->next) {
293 if(strcasecmp(child_elem->name, "interpretation") == 0) {
294 interpretation = nlsml_interpretation_parse(child_elem, pool);
295 if(interpretation) {
296 APR_RING_INSERT_TAIL(&result->interpretations, interpretation, nlsml_interpretation_t, link);
297 }
298 }
299 else if(strcasecmp(child_elem->name, "enrollment-result") == 0) {
300 enrollment_result = nlsml_enrollment_result_parse(child_elem, pool);
301 if(enrollment_result) {
302 APR_RING_INSERT_TAIL(&result->enrollment_results, enrollment_result, nlsml_enrollment_result_t, link);
303 }
304 }
305 else if(strcasecmp(child_elem->name, "verification-result") == 0) {
306 verification_result = nlsml_verification_result_parse(child_elem, pool);
307 if(verification_result) {
308 APR_RING_INSERT_TAIL(&result->verification_results, verification_result, nlsml_verification_result_t, link);
309 }
310 }
311 else {
312 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown child element <%s> for <%s>", child_elem->name, root->name);
313 }
314 }
315
316 if(APR_RING_EMPTY(&result->interpretations, nlsml_interpretation_t, link) &&
317 APR_RING_EMPTY(&result->enrollment_results, nlsml_enrollment_result_t, link) &&
318 APR_RING_EMPTY(&result->verification_results, nlsml_verification_result_t, link)) {
319 /* at least one of <interpretation>, <enrollment-result>, <verification-result> MUST be specified */
320 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Invalid NLSML document: at least one child element MUST be specified for <%s>", root->name);
321 }
322
323 return result;
324 }
325
326 /** Trace NLSML result (for debug purposes only) */
nlsml_result_trace(const nlsml_result_t * result,apr_pool_t * pool)327 APT_DECLARE(void) nlsml_result_trace(const nlsml_result_t *result, apr_pool_t *pool)
328 {
329 int interpretation_count;
330 nlsml_interpretation_t *interpretation;
331 int instance_count;
332 nlsml_instance_t *instance;
333 nlsml_input_t *input;
334 const char *instance_data;
335 const char *input_data;
336 const char *timestamp_start;
337 const char *timestamp_end;
338
339 if(result->grammar)
340 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Result.grammar: %s", result->grammar);
341
342 interpretation_count = 0;
343 interpretation = nlsml_first_interpretation_get(result);
344 while(interpretation) {
345 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Interpretation[%d].confidence: %.2f", interpretation_count, nlsml_interpretation_confidence_get(interpretation));
346 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Interpretation[%d].grammar: %s", interpretation_count, nlsml_interpretation_grammar_get(interpretation));
347
348 instance_count = 0;
349 instance = nlsml_interpretation_first_instance_get(interpretation);
350 while(instance) {
351 nlsml_instance_swi_suppress(instance);
352 instance_data = nlsml_instance_content_generate(instance,pool);
353 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Interpretation[%d].instance[%d]: %s", interpretation_count, instance_count, instance_data);
354
355 instance_count++;
356 instance = nlsml_interpretation_next_instance_get(interpretation, instance);
357 }
358
359 input = nlsml_interpretation_input_get(interpretation);
360 if(input) {
361 input_data = nlsml_input_content_generate(input,pool);
362 timestamp_start = nlsml_input_timestamp_start_get(input);
363 timestamp_end = nlsml_input_timestamp_end_get(input);
364 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Interpretation[%d].input: %s", interpretation_count, input_data);
365 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Interpretation[%d].input.mode: %s", interpretation_count, nlsml_input_mode_get(input));
366 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Interpretation[%d].input.confidence: %.2f", interpretation_count, nlsml_input_confidence_get(input));
367 if(timestamp_start)
368 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Interpretation[%d].input.timestamp-start: %s", interpretation_count, timestamp_start);
369 if(timestamp_end)
370 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Interpretation[%d].input.timestamp-end: %s", interpretation_count, timestamp_end);
371 }
372
373 interpretation_count++;
374 interpretation = nlsml_next_interpretation_get(result, interpretation);
375 }
376 }
377
378 /** Get first interpretation */
nlsml_first_interpretation_get(const nlsml_result_t * result)379 APT_DECLARE(nlsml_interpretation_t*) nlsml_first_interpretation_get(const nlsml_result_t *result)
380 {
381 nlsml_interpretation_t *first_interpretation = APR_RING_FIRST(&result->interpretations);
382 if(first_interpretation == APR_RING_SENTINEL(&result->interpretations, nlsml_interpretation_t, link))
383 return NULL;
384 return first_interpretation;
385 }
386
387 /** Get next interpretation */
nlsml_next_interpretation_get(const nlsml_result_t * result,const nlsml_interpretation_t * interpretation)388 APT_DECLARE(nlsml_interpretation_t*) nlsml_next_interpretation_get(const nlsml_result_t *result, const nlsml_interpretation_t *interpretation)
389 {
390 nlsml_interpretation_t *next_interpretation = APR_RING_NEXT(interpretation, link);
391 if(next_interpretation == APR_RING_SENTINEL(&result->interpretations, nlsml_interpretation_t, link))
392 return NULL;
393 return next_interpretation;
394 }
395
396 /** Get first enrollment result */
nlsml_first_enrollment_result_get(const nlsml_result_t * result)397 APT_DECLARE(nlsml_enrollment_result_t*) nlsml_first_enrollment_result_get(const nlsml_result_t *result)
398 {
399 nlsml_enrollment_result_t *first_enrollment_result = APR_RING_FIRST(&result->enrollment_results);
400 if(first_enrollment_result == APR_RING_SENTINEL(&result->enrollment_results, nlsml_enrollment_result_t, link))
401 return NULL;
402 return first_enrollment_result;
403 }
404
405 /** Get next enrollment result */
nlsml_next_enrollment_result_get(const nlsml_result_t * result,const nlsml_enrollment_result_t * enrollment_result)406 APT_DECLARE(nlsml_enrollment_result_t*) nlsml_next_enrollment_result_get(const nlsml_result_t *result, const nlsml_enrollment_result_t *enrollment_result)
407 {
408 nlsml_enrollment_result_t *next_enrollment_result = APR_RING_NEXT(enrollment_result, link);
409 if(next_enrollment_result == APR_RING_SENTINEL(&result->enrollment_results, nlsml_enrollment_result_t, link))
410 return NULL;
411 return next_enrollment_result;
412 }
413
414 /** Get first verification result */
nlsml_first_verification_result_get(const nlsml_result_t * result)415 APT_DECLARE(nlsml_verification_result_t*) nlsml_first_verification_result_get(const nlsml_result_t *result)
416 {
417 nlsml_verification_result_t *first_verification_result = APR_RING_FIRST(&result->verification_results);
418 if(first_verification_result == APR_RING_SENTINEL(&result->verification_results, nlsml_verification_result_t, link))
419 return NULL;
420 return first_verification_result;
421 }
422
423 /** Get next verification result */
nlsml_next_verification_result_get(const nlsml_result_t * result,const nlsml_verification_result_t * verification_result)424 APT_DECLARE(nlsml_verification_result_t*) nlsml_next_verification_result_get(const nlsml_result_t *result, const nlsml_verification_result_t *verification_result)
425 {
426 nlsml_verification_result_t *next_verification_result = APR_RING_NEXT(verification_result, link);
427 if(next_verification_result == APR_RING_SENTINEL(&result->verification_results, nlsml_verification_result_t, link))
428 return NULL;
429 return next_verification_result;
430 }
431
432 /** Get grammar attribute of NLSML result */
nlsml_result_grammar_get(const nlsml_result_t * result)433 APT_DECLARE(const char*) nlsml_result_grammar_get(const nlsml_result_t *result)
434 {
435 return result->grammar;
436 }
437
438 /** Get first instance */
nlsml_interpretation_first_instance_get(const nlsml_interpretation_t * interpretation)439 APT_DECLARE(nlsml_instance_t*) nlsml_interpretation_first_instance_get(const nlsml_interpretation_t *interpretation)
440 {
441 nlsml_instance_t *first_instance = APR_RING_FIRST(&interpretation->instances);
442 if(first_instance == APR_RING_SENTINEL(&interpretation->instances, nlsml_instance_t, link))
443 return NULL;
444 return first_instance;
445 }
446
447 /** Get next instance */
nlsml_interpretation_next_instance_get(const nlsml_interpretation_t * interpretation,const nlsml_instance_t * instance)448 APT_DECLARE(nlsml_instance_t*) nlsml_interpretation_next_instance_get(const nlsml_interpretation_t *interpretation, const nlsml_instance_t *instance)
449 {
450 nlsml_instance_t *next_instance = APR_RING_NEXT(instance, link);
451 if(next_instance == APR_RING_SENTINEL(&interpretation->instances, nlsml_instance_t, link))
452 return NULL;
453 return next_instance;
454 }
455
456 /** Get input */
nlsml_interpretation_input_get(const nlsml_interpretation_t * interpretation)457 APT_DECLARE(nlsml_input_t*) nlsml_interpretation_input_get(const nlsml_interpretation_t *interpretation)
458 {
459 return interpretation->input;
460 }
461
462 /** Get interpretation confidence */
nlsml_interpretation_confidence_get(const nlsml_interpretation_t * interpretation)463 APT_DECLARE(float) nlsml_interpretation_confidence_get(const nlsml_interpretation_t *interpretation)
464 {
465 return interpretation->confidence;
466 }
467
468 /** Get interpretation grammar */
nlsml_interpretation_grammar_get(const nlsml_interpretation_t * interpretation)469 APT_DECLARE(const char*) nlsml_interpretation_grammar_get(const nlsml_interpretation_t *interpretation)
470 {
471 return interpretation->grammar;
472 }
473
474 /** Get instance element */
nlsml_instance_elem_get(const nlsml_instance_t * instance)475 APT_DECLARE(const apr_xml_elem*) nlsml_instance_elem_get(const nlsml_instance_t *instance)
476 {
477 return instance->elem;
478 }
479
480 /** Suppress SWI elements (normalize instance) */
nlsml_instance_swi_suppress(nlsml_instance_t * instance)481 APT_DECLARE(apt_bool_t) nlsml_instance_swi_suppress(nlsml_instance_t *instance)
482 {
483 apr_xml_elem *child_elem;
484 apr_xml_elem *prev_elem = NULL;
485 apr_xml_elem *swi_literal = NULL;
486 apt_bool_t remove;
487 if(!instance->elem)
488 return FALSE;
489
490 for(child_elem = instance->elem->first_child; child_elem; child_elem = child_elem->next) {
491 remove = FALSE;
492 if(strcasecmp(child_elem->name,"SWI_literal") == 0) {
493 swi_literal = child_elem;
494 remove = TRUE;
495 }
496 else if(strcasecmp(child_elem->name,"SWI_meaning") == 0) {
497 remove = TRUE;
498 }
499
500 if(remove == TRUE) {
501 if(child_elem == instance->elem->first_child) {
502 instance->elem->first_child = child_elem->next;
503 }
504 else if(prev_elem) {
505 prev_elem->next = child_elem->next;
506 }
507 }
508
509 prev_elem = child_elem;
510 }
511
512 if(APR_XML_ELEM_IS_EMPTY(instance->elem) && swi_literal) {
513 instance->elem->first_cdata = swi_literal->first_cdata;
514 }
515
516 return TRUE;
517 }
518
519 /** Generate a plain text content of the instance element */
nlsml_instance_content_generate(const nlsml_instance_t * instance,apr_pool_t * pool)520 APT_DECLARE(const char*) nlsml_instance_content_generate(const nlsml_instance_t *instance, apr_pool_t *pool)
521 {
522 const char *buf = NULL;
523 if(instance->elem) {
524 apr_size_t size;
525 apr_xml_to_text(pool, instance->elem, APR_XML_X2T_INNER, NULL, NULL, &buf, &size);
526 }
527 return buf;
528 }
529
530 /** Get input element */
nlsml_input_elem_get(const nlsml_input_t * input)531 APT_DECLARE(const apr_xml_elem*) nlsml_input_elem_get(const nlsml_input_t *input)
532 {
533 return input->elem;
534 }
535
536 /** Generate a plain text content of the input element */
nlsml_input_content_generate(const nlsml_input_t * input,apr_pool_t * pool)537 APT_DECLARE(const char*) nlsml_input_content_generate(const nlsml_input_t *input, apr_pool_t *pool)
538 {
539 const char *buf = NULL;
540 if(input->elem) {
541 apr_size_t size;
542 apr_xml_to_text(pool, input->elem, APR_XML_X2T_INNER, NULL, NULL, &buf, &size);
543 }
544 return buf;
545 }
546
547 /** Get input mode */
nlsml_input_mode_get(const nlsml_input_t * input)548 APT_DECLARE(const char*) nlsml_input_mode_get(const nlsml_input_t *input)
549 {
550 return input->mode;
551 }
552
553 /** Get input confidence */
nlsml_input_confidence_get(const nlsml_input_t * input)554 APT_DECLARE(float) nlsml_input_confidence_get(const nlsml_input_t *input)
555 {
556 return input->confidence;
557 }
558
559 /** Get start of input timestamp */
nlsml_input_timestamp_start_get(const nlsml_input_t * input)560 APT_DECLARE(const char*) nlsml_input_timestamp_start_get(const nlsml_input_t *input)
561 {
562 return input->timestamp_start;
563 }
564
565 /** Get end of input timestamp */
nlsml_input_timestamp_end_get(const nlsml_input_t * input)566 APT_DECLARE(const char*) nlsml_input_timestamp_end_get(const nlsml_input_t *input)
567 {
568 return input->timestamp_end;
569 }
570