1 /*---------------------------------------------------------------------------*
2 * RecognizerResultImpl.c *
3 * *
4 * Copyright 2007, 2008 Nuance Communciations, Inc. *
5 * *
6 * Licensed under the Apache License, Version 2.0 (the 'License'); *
7 * you may not use this file except in compliance with the License. *
8 * *
9 * You may obtain a copy of the License at *
10 * http://www.apache.org/licenses/LICENSE-2.0 *
11 * *
12 * Unless required by applicable law or agreed to in writing, software *
13 * distributed under the License is distributed on an 'AS IS' BASIS, *
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15 * See the License for the specific language governing permissions and *
16 * limitations under the License. *
17 * *
18 *---------------------------------------------------------------------------*/
19
20 #include "SR_RecognizerResult.h"
21 #include "SR_RecognizerResultImpl.h"
22 #include "SR_SemanticResult.h"
23 #include "SR_SemanticResultImpl.h"
24 #include "SR_SemprocDefinitions.h"
25 #include "plog.h"
26 #include "pmemory.h"
27 #include "ESR_Locale.h"
28
29 #define MTAG NULL
30
SR_RecognizerResult_Create(SR_RecognizerResult ** self,SR_RecognizerImpl * recogImpl)31 ESR_ReturnCode SR_RecognizerResult_Create(SR_RecognizerResult** self, SR_RecognizerImpl* recogImpl)
32 {
33 SR_RecognizerResultImpl* impl;
34
35 if (self == NULL || recogImpl == NULL)
36 {
37 PLogError(L("ESR_INVALID_ARGUMENT"));
38 return ESR_INVALID_ARGUMENT;
39 }
40 impl = NEW(SR_RecognizerResultImpl, MTAG);
41 if (impl == NULL)
42 {
43 PLogError(L("ESR_OUT_OF_MEMORY"));
44 return ESR_OUT_OF_MEMORY;
45 }
46 impl->Interface.getWaveform = &SR_RecognizerResult_GetWaveform;
47 impl->Interface.getSize = &SR_RecognizerResult_GetSize;
48 impl->Interface.getKeyCount = &SR_RecognizerResult_GetKeyCount;
49 impl->Interface.getKeyList = &SR_RecognizerResult_GetKeyList;
50 impl->Interface.getValue = &SR_RecognizerResult_GetValue;
51 impl->Interface.getLocale = &SR_RecognizerResult_GetLocale;
52
53 impl->nbestList = NULL;
54 impl->nbestListSize = 0;
55 impl->results = NULL;
56 impl->recogImpl = recogImpl;
57 *self = (SR_RecognizerResult*) impl;
58 return ESR_SUCCESS;
59 }
60
SR_RecognizerResult_GetWaveform(const SR_RecognizerResult * self,const asr_int16_t ** waveform,size_t * size)61 ESR_ReturnCode SR_RecognizerResult_GetWaveform(const SR_RecognizerResult* self,
62 const asr_int16_t** waveform, size_t* size)
63 {
64 SR_RecognizerResultImpl* impl = (SR_RecognizerResultImpl*) self;
65
66 if (waveform == NULL)
67 {
68 PLogError(L("ESR_INVALID_ARGUMENT"));
69 return ESR_INVALID_ARGUMENT;
70 }
71
72 // just point to the circular buffer read start point
73 if (impl->recogImpl->waveformBuffer->overflow_count == 0)
74 {
75 *waveform = (asr_int16_t*)(((unsigned char *) impl->recogImpl->waveformBuffer->cbuffer) +
76 sizeof(CircularBuffer) + impl->recogImpl->waveformBuffer->cbuffer->readIdx);
77
78 *size = impl->recogImpl->waveformBuffer->read_size;
79 return ESR_SUCCESS;
80 }
81 else
82 {
83 PLogMessage(L("Warning: Voice Enrollment audio buffer overflow (spoke too much, over by %d bytes)\n"),
84 impl->recogImpl->waveformBuffer->overflow_count);
85
86 *waveform = (asr_int16_t*)(((unsigned char *) impl->recogImpl->waveformBuffer->cbuffer) + sizeof(CircularBuffer) + impl->recogImpl->waveformBuffer->cbuffer->readIdx);
87 *size = impl->recogImpl->waveformBuffer->read_size;
88 return ESR_SUCCESS;
89 }
90 }
91
SR_RecognizerResult_GetSize(const SR_RecognizerResult * self,size_t * count)92 ESR_ReturnCode SR_RecognizerResult_GetSize(const SR_RecognizerResult* self, size_t* count)
93 {
94 SR_RecognizerResultImpl* impl = (SR_RecognizerResultImpl*) self;
95 ESR_ReturnCode rc;
96
97 CHKLOG(rc, ArrayListGetSize(impl->results, count));
98 return ESR_SUCCESS;
99 CLEANUP:
100 return rc;
101 }
102
SR_RecognizerResult_GetKeyCount(const SR_RecognizerResult * self,const size_t nbest,size_t * count)103 ESR_ReturnCode SR_RecognizerResult_GetKeyCount(const SR_RecognizerResult* self,
104 const size_t nbest, size_t* count)
105 {
106 SR_RecognizerResultImpl* impl = (SR_RecognizerResultImpl*) self;
107 ESR_ReturnCode rc;
108 ArrayList* results;
109 SR_SemanticResult* result;
110
111 /* Choose nbest-list entry */
112 CHKLOG(rc, impl->results->get(impl->results, nbest, (void **)&results));
113 /*
114 * Currently we only support one semantic result per nbestlist entry,
115 * so we grab the first available one.
116 */
117 CHKLOG(rc, results->get(results, 0, (void **)&result));
118 CHKLOG(rc, result->getKeyCount(result , count));
119 return ESR_SUCCESS;
120 CLEANUP:
121 return rc;
122 }
123
SR_RecognizerResult_GetKeyList(const SR_RecognizerResult * self,const size_t nbest,LCHAR ** list,size_t * listSize)124 ESR_ReturnCode SR_RecognizerResult_GetKeyList(const SR_RecognizerResult* self,
125 const size_t nbest, LCHAR** list, size_t* listSize)
126 {
127 SR_RecognizerResultImpl* impl = (SR_RecognizerResultImpl*) self;
128 ArrayList* results;
129 SR_SemanticResult* result;
130 ESR_ReturnCode rc;
131
132 /* Choose nbest-list entry */
133 CHKLOG(rc, impl->results->get(impl->results, nbest, (void **)&results));
134
135 /*
136 * Currently we only support one semantic result per nbestlist entry,
137 * so we grab the first available one.
138 */
139 CHKLOG(rc, results->get(results, 0, (void **)&result));
140 CHKLOG(rc, result->getKeyList(result, list, listSize));
141
142 return ESR_SUCCESS;
143 CLEANUP:
144 return rc;
145 }
146
SR_RecognizerResult_GetValue(const SR_RecognizerResult * self,const size_t nbest,const LCHAR * key,LCHAR * value,size_t * len)147 ESR_ReturnCode SR_RecognizerResult_GetValue(const SR_RecognizerResult* self, const size_t nbest,
148 const LCHAR* key, LCHAR* value, size_t* len)
149 {
150 SR_RecognizerResultImpl* impl = (SR_RecognizerResultImpl*) self;
151 ArrayList* results;
152 SR_SemanticResult* result;
153 SR_SemanticResultImpl* resultImpl;
154 LCHAR* lValue;
155 size_t actualLen = 0, i, resultCount;
156 ESR_ReturnCode rc;
157 ESR_BOOL noMatch = ESR_TRUE;
158
159 /* Choose nbest-list entry */
160 CHKLOG(rc, impl->results->get(impl->results, nbest, (void **)&results));
161 /* Get the number of semantic results for the entry */
162 CHKLOG(rc, results->getSize(results, &resultCount));
163
164 for (i = 0; i < resultCount; ++i)
165 {
166 /* Choose semantic result */
167 CHKLOG(rc, results->get(results, i, (void **)&result));
168 resultImpl = (SR_SemanticResultImpl*) result;
169 rc = resultImpl->results->get(resultImpl->results, key, (void**) & lValue);
170 if (rc == ESR_SUCCESS)
171 {
172 noMatch = ESR_FALSE;
173 actualLen += LSTRLEN(lValue);
174 }
175 else if (rc != ESR_NO_MATCH_ERROR)
176 return rc;
177 }
178 if (noMatch)
179 return ESR_NO_MATCH_ERROR;
180 ++actualLen;
181
182 /* Check for overflow */
183 if (actualLen + 1 > *len)
184 {
185 /* Unfortunately some people are using get value functions to get the size of the value by
186 * passing a zero length buffer which causes errors to be logged. I am adding code so
187 * that the error is not logged when the length is zero, thus preventing lots of logs from
188 * flooding the system. SteveR
189 */
190 if ( ( *len ) != 0 )
191 PLogError(L("Buffer Overflow while fetching value for %s of choice %d Len %d"),
192 key, nbest, *len );
193 *len = actualLen + 1;
194 return ESR_BUFFER_OVERFLOW;
195 }
196 *len = actualLen;
197
198 LSTRCPY(value, L(""));
199 for (i = 0; i < resultCount; ++i)
200 {
201 /* Choose semantic result */
202 CHKLOG(rc, results->get(results, i, (void **)&result));
203 resultImpl = (SR_SemanticResultImpl*) result;
204 rc = resultImpl->results->get(resultImpl->results, key, (void **) & lValue);
205 if (rc == ESR_SUCCESS)
206 LSTRCAT(value, lValue);
207 else if (rc != ESR_NO_MATCH_ERROR)
208 return rc;
209
210 /* Separate semantic results with '#' token */
211 if (i < resultCount - 1) {
212 int len = LSTRLEN(value);
213 value[len] = MULTIPLE_MEANING_JOIN_CHAR;
214 value[len+1] = 0;
215 }
216 }
217 return ESR_SUCCESS;
218 CLEANUP:
219 return rc;
220 }
221
SR_RecognizerResult_Destroy(SR_RecognizerResult * self)222 ESR_ReturnCode SR_RecognizerResult_Destroy(SR_RecognizerResult* self)
223 {
224 SR_RecognizerResultImpl* impl = (SR_RecognizerResultImpl*) self;
225 ArrayList* semanticList;
226 SR_SemanticResult* semanticResult;
227 size_t nbest, i, j, num_semanticResults;
228 ESR_ReturnCode rc;
229
230 /* each nbest list entry has an ArrayList of Semantic Results... need to destroy them too */
231 if (impl->results != NULL)
232 {
233 CHKLOG(rc, impl->results->getSize(impl->results, &nbest));
234 for (i = 0; i < nbest; ++i)
235 {
236 CHKLOG(rc, impl->results->get(impl->results, 0, (void **)&semanticList));
237 if (semanticList == NULL)
238 continue;
239
240 CHKLOG(rc, semanticList->getSize(semanticList, &num_semanticResults));
241 for (j = 0; j < num_semanticResults; ++j)
242 {
243 LCHAR literal[256];
244 size_t len;
245
246 CHKLOG(rc, semanticList->get(semanticList, 0, (void **)&semanticResult));
247 CHKLOG(rc, semanticList->remove(semanticList, semanticResult));
248 len = sizeof(literal) / sizeof(LCHAR);
249 CHKLOG(rc, semanticResult->getValue(semanticResult, "literal", (LCHAR*) &literal, &len));
250 CHKLOG(rc, semanticResult->destroy(semanticResult));
251 }
252 CHKLOG(rc, impl->results->remove(impl->results, semanticList));
253 CHKLOG(rc, semanticList->destroy(semanticList));
254 }
255 CHKLOG(rc, impl->results->destroy(impl->results));
256 impl->results = NULL;
257 }
258
259 if (impl->nbestList != NULL)
260 {
261 CA_DeleteNBestList(impl->nbestList);
262 impl->nbestList = NULL;
263 }
264 FREE(impl);
265 return ESR_SUCCESS;
266 CLEANUP:
267 passert(rc != ESR_BUFFER_OVERFLOW);
268 return rc;
269 }
270
SR_RecognizerResult_GetLocale(const SR_RecognizerResult * self,ESR_Locale * locale)271 ESR_ReturnCode SR_RecognizerResult_GetLocale(const SR_RecognizerResult* self, ESR_Locale* locale)
272 {
273 SR_RecognizerResultImpl* impl = (SR_RecognizerResultImpl*) self;
274 *locale = impl->locale;
275 return ESR_SUCCESS;
276 }
277