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 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 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 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 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 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 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 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 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