• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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