📄 vxirec.cpp
字号:
logger.logDiag(DIAG_TAG_RECOGNITION, L"%s%s", L"DTMFInput: ",
VXIStringCStr((const VXIString*)val));
}
}
VXIString* vect = (VXIString*) val;
if (vect != NULL) input = (VXIchar*) VXIStringCStr(vect);
if (input && wcscmp(input, L"-") == 0) {
unsigned int i;
VXIchar* cp = console;
char lbuf[512];
printf("Console: ");
fgets(lbuf, 511, stdin);
// copy to VXIchar
for(i = 0; i < strlen(lbuf); ++i) {
if (lbuf[i] == '\r' || lbuf[i] == '\n') continue;
*cp++ = lbuf[i] & 0x7f;
}
*cp++ = 0;
input = console;
logger.logDiag(DIAG_TAG_RECOGNITION, L"%s%s", L"Input: ",
(input ? input : L"NULL"));
}
}
// Create a new results structure.
const unsigned int CHARSIZE = sizeof(VXIchar) / sizeof(VXIbyte);
VXIContent * xmlresult = NULL;
// Looking for matched phrase, if not act appropriately
vxistring nlsmlresult;
bool found = tp->ConstructNLSMLForInput(input, nlsmlresult);
if( !found ) {
if( !input || input[0] == L'\0' ) {
// No input case
haveUtterance = false;
logger.logDiag(DIAG_TAG_RECOGNITION, L"%s", L"-- NO_INPUT RESULT --");
xmlresult = VXIContentCreate(VXIREC_MIMETYPE_XMLRESULT,
(VXIbyte *) NLSML_NOINPUT,
NLSML_NOINPUT_SIZE * CHARSIZE,
DestroyNLSMLBuffer, NULL);
} else {
// No match case
logger.logDiag(DIAG_TAG_RECOGNITION, L"%s", L"-- NO_MATCH RESULT --");
xmlresult = VXIContentCreate(VXIREC_MIMETYPE_XMLRESULT,
(VXIbyte *) NLSML_NOMATCH,
NLSML_NOMATCH_SIZE * CHARSIZE,
DestroyNLSMLBuffer, NULL);
}
}
else {
// Found matched grammar
logger.logDiag(DIAG_TAG_RECOGNITION, L"%s%s", L"NLSML_RESULT: ",
nlsmlresult.c_str());
unsigned int BUFFERSIZE = (nlsmlresult.length() + 1) * CHARSIZE;
VXIbyte * buffer = new VXIbyte[BUFFERSIZE];
if (buffer == NULL) return VXIrec_RESULT_OUT_OF_MEMORY;
memcpy(buffer, nlsmlresult.c_str(), BUFFERSIZE);
xmlresult = VXIContentCreate(VXIREC_MIMETYPE_XMLRESULT,
buffer, BUFFERSIZE,
DestroyNLSMLBuffer, buffer);
if (xmlresult == NULL) {
delete [] buffer;
return VXIrec_RESULT_OUT_OF_MEMORY;
}
}
VXIrecRecognitionResult * result = new VXIrecRecognitionResult();
if (result == NULL) {
VXIContentDestroy(&xmlresult);
return VXIrec_RESULT_OUT_OF_MEMORY;
}
result->Destroy = RecognitionResultDestroy;
result->markname = NULL;
result->marktime = 0;
result->xmlresult = xmlresult;
if (!haveUtterance ||!recordUtterance) {
result->utterance = NULL;
result->utteranceDuration = 0;
}
else {
result->utteranceDuration = 5000; // 5sec
unsigned int waveformSizeBytes = (result->utteranceDuration / 1000 ) * 8000 * sizeof(unsigned char);
unsigned char * c_waveform = new unsigned char[waveformSizeBytes];
if (c_waveform == NULL) {
result->utterance = NULL;
result->utteranceDuration = 0;
}
else {
for (unsigned int i = 0; i < waveformSizeBytes; ++i)
c_waveform[i] = i & 0x00ff;
result->utterance = VXIContentCreate(VXIREC_MIMETYPE_ULAW,
c_waveform, waveformSizeBytes,
ResultContentDestroy, NULL);
}
}
*recogResult = result;
return VXIrec_RESULT_SUCCESS;
}
static VXIrecResult VXIrecGetMatchedGrammar(VXIrecInterface *pThis,
const VXIchar *grammarID,
const VXIrecGrammar **gram)
{
const wchar_t* fnname = L"VXIrecGetMatchedGrammar";
VXIrecData* tp = GetRecData(pThis);
if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT;
LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE);
if (grammarID == NULL || gram == NULL)
return VXIrec_RESULT_INVALID_ARGUMENT;
VXIrecGrammar * mgram = NULL;
SWIswscanf(grammarID, L"%p", &mgram);
*gram = mgram;
logger.logDiag(DIAG_TAG_RECOGNITION, L"%s%p", L"Got Matched grammar: ", mgram);
return VXIrec_RESULT_SUCCESS;
}
static void RecordResultDestroy(VXIrecRecordResult **Result)
{
if (Result == NULL || *Result == NULL) return;
VXIrecRecordResult * result = *Result;
if (result->waveform != NULL)
VXIContentDestroy(&result->waveform);
if (result->xmlresult != NULL)
VXIContentDestroy(&result->xmlresult);
delete result;
*Result = NULL;
}
static VXIrecResult VXIrecRecord(VXIrecInterface *pThis,
const VXIMap *props,
VXIrecRecordResult **recordResult)
{
const wchar_t* fnname = L"VXIrecRecord";
VXIrecData* tp = GetRecData(pThis);
if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT;
LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE);
if (recordResult == NULL) {
logger = VXIrec_RESULT_INVALID_ARGUMENT;
return VXIrec_RESULT_INVALID_ARGUMENT;
}
// (1) Create record structure
VXIrecRecordResult *result = new VXIrecRecordResult();
if (result == NULL) {
logger = VXIrec_RESULT_OUT_OF_MEMORY;
return VXIrec_RESULT_OUT_OF_MEMORY;
}
result->Destroy = RecordResultDestroy;
result->waveform = NULL;
result->xmlresult = NULL;
result->duration = 0;
result->termchar = 0;
result->maxtime = FALSE;
result->markname = NULL;
result->marktime = 0;
*recordResult = result;
VXIlong duration = -1;
VXIlong maxtime = 0;
VXIlong finalsilence = 0;
// (2) Get maxtime
const VXIValue* val = VXIMapGetProperty(props, REC_MAX_RECORDING_TIME);
if (val != NULL && VXIValueGetType(val) == VALUE_INTEGER )
maxtime = VXIIntegerValue(reinterpret_cast<const VXIInteger *>(val));
else
maxtime = 1000 * 20; // in milliseconds (default to 20 secs)
// (2.1) adjust duration for simulator
if( duration < 0 ) duration = maxtime;
(*recordResult)->duration = duration;
if( duration == maxtime ) (*recordResult)->maxtime = TRUE;
// TODO: this should use the media type. For now just construct
// raw ulaw audio with silence
unsigned int waveformSizeBytes = (duration / 1000 ) * 8000 * sizeof(unsigned char);
unsigned char * c_waveform = new unsigned char[waveformSizeBytes];
if (c_waveform == NULL) {
(*recordResult)->Destroy(recordResult);
tp->LogError(400, L"%s%s", L"Error", L"out of memory");
return VXIrec_RESULT_OUT_OF_MEMORY;
}
for (unsigned int i = 0; i < waveformSizeBytes; ++i)
c_waveform[i] = i & 0x00ff;
(*recordResult)->waveform = VXIContentCreate(VXIREC_MIMETYPE_ULAW,
c_waveform, waveformSizeBytes,
ResultContentDestroy, NULL);
if( (*recordResult)->waveform == NULL ) {
(*recordResult)->Destroy(recordResult);
tp->LogError(400, L"%s%s", L"Error", L"out of memory");
return VXIrec_RESULT_OUT_OF_MEMORY;
}
return VXIrec_RESULT_SUCCESS;
}
static VXIbool VXIrecSupportsHotwordTransfer(
struct VXIrecInterface * pThis,
const VXIMap * properties,
const VXIchar * transferDest)
{
VXIbool result = FALSE;
// this is really just to demonstrate how the platform could
// support hotword for some type of transfers, but not others.
// this could just as easily been based on other properties of
// the transfer. i.e., destination type, required line type, etc...
const VXIValue* dval = VXIMapGetProperty(properties, TEL_TRANSFER_TYPE);
if( dval && VXIValueGetType(dval) == VALUE_STRING ){
const wchar_t* hid = VXIStringCStr(reinterpret_cast<const VXIString *>(dval));
if (wcscmp(hid, L"consultation") == 0)
return FALSE;
}
dval = VXIMapGetProperty(properties, L"SupportsHotwordTransfer");
if( dval && VXIValueGetType(dval) == VALUE_STRING ){
const wchar_t* hid = VXIStringCStr(reinterpret_cast<const VXIString *>(dval));
result = (wcscmp(hid, L"true") == 0) ? TRUE : FALSE;
}
return result;
}
static VXIrecResult VXIrecHotwordTransfer
(
struct VXIrecInterface * pThis,
struct VXItelInterface * tel,
const VXIMap *properties,
const VXIchar* transferDest,
VXIrecTransferResult ** transferResult
)
{
const wchar_t* fnname = L"VXIrecHotwordTransfer";
VXIrecData* tp = GetRecData(pThis);
if (tp == NULL) return VXIrec_RESULT_INVALID_ARGUMENT;
LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE);
VXIrecResult res = VXIrec_RESULT_SUCCESS;
// this is probably not how it would be done in real life...but for this
// sample app it will suffice:
// Do the transfer
int activeGrammars = tp->GetActiveCount();
VXIMap *xferResp = NULL;
VXItelResult xferResult = tel->TransferBridge(tel, properties, transferDest, &xferResp);
if (xferResult != VXItel_RESULT_SUCCESS) {
res = VXIrec_RESULT_FAILURE;
}
else if (activeGrammars == 0) {
*transferResult = new VXIrecTransferResult();
(*transferResult)->Destroy = TransferResultDestroy;
(*transferResult)->utterance = NULL;
(*transferResult)->markname = NULL;
(*transferResult)->marktime = 0;
(*transferResult)->xmlresult = NULL;
const VXIValue * v = VXIMapGetProperty(xferResp, TEL_TRANSFER_DURATION);
if (v != NULL && VXIValueGetType(v) == VALUE_INTEGER)
(*transferResult)->duration = VXIIntegerValue(reinterpret_cast<const VXIInteger*>(v));
v = VXIMapGetProperty(xferResp, TEL_TRANSFER_STATUS);
if (v != NULL && VXIValueGetType(v) == VALUE_INTEGER) {
long temp = VXIIntegerValue(reinterpret_cast<const VXIInteger *>(v));
(*transferResult)->status = VXItelTransferStatus(temp);
}
VXIMapDestroy(&xferResp);
}
else {
// get input from the user.
VXIrecRecognitionResult *recResult = NULL;
VXIrecResult localRes = pThis->Recognize(pThis, properties, &recResult);
if (localRes == VXIrec_RESULT_SUCCESS){
*transferResult = new VXIrecTransferResult();
if ((*transferResult) == NULL) {
recResult->Destroy(&recResult);
VXIMapDestroy(&xferResp);
return VXIrec_RESULT_OUT_OF_MEMORY;
}
// setup the transfer result by first copying the
// RecResult.
(*transferResult)->Destroy = TransferResultDestroy;
(*transferResult)->utterance = recResult->utterance;
(*transferResult)->markname = recResult->markname;
(*transferResult)->marktime = recResult->marktime;
(*transferResult)->xmlresult = recResult->xmlresult;
(*transferResult)->duration = 0;
(*transferResult)->status = VXItel_TRANSFER_FAR_END_DISCONNECT;
// we no long need the rec result (but we don't want the VXIContent
// fields destroyed).
recResult->utterance = NULL;
recResult->xmlresult = NULL;
recResult->Destroy(&recResult);
// translate the status and duration to the transfer result fields.
// since this code is simply so that Hotword transfers work, any
// valid recognition (ignoring noinput and nomatch) will set the
// transfer to "near_end_disconnect". Otherwise, we pretend that
// the other end terminated the transfer.
if((*transferResult)->xmlresult){
// we're going to ignore noinput and nomatch results.
const VXIchar * contentType;
const VXIbyte * content;
VXIulong contentSize = 0;
VXIContentValue((*transferResult)->xmlresult, &contentType, &content, &contentSize);
// we're going to ignore noinput and nomatch results.
if ( !wcsstr((VXIchar*)content, L"<noinput/>")
&& !wcsstr((VXIchar*)content, L"<nomatch/>")){
(*transferResult)->status = VXItel_TRANSFER_NEAR_END_DISCONNECT;
}
}
const VXIValue * v = VXIMapGetProperty(xferResp, TEL_TRANSFER_DURATION);
if (v != NULL && VXIValueGetType(v) == VALUE_INTEGER)
(*transferResult)->duration = VXIIntegerValue(reinterpret_cast<const VXIInteger*>(v));
VXIMapDestroy(&xferResp);
}
}
return res;
}
/*******************************************************
* Init and factory routines
*******************************************************/
static inline VXIrecImpl * ToVXIrecImpl(VXIrecInterface * i)
{ return reinterpret_cast<VXIrecImpl *>(i); }
// Global init - Don't need to do much here
//
VXIREC_API VXIrecResult VXIrecInit(VXIlogInterface *log,
VXIunsigned diagLogBase,
VXIMap *args)
{
if (!log) return VXIrec_RESULT_INVALID_ARGUMENT;
gblDiagLogBase = diagLogBase;
const wchar_t* fnname = L"VXIrecInit";
LogBlock logger(log, gblDiagLogBase, fnname, VXIREC_MODULE);
logger = VXIrecData::Initialize(log, diagLogBase);
return VXIrec_RESULT_SUCCESS;
}
// Global shutdown
//
VXIREC_API VXIrecResult VXIrecShutDown(VXIlogInterface *log)
{
if (!log) return VXIrec_RESULT_INVALID_ARGUMENT;
const wchar_t* fnname = L"VXIrecShutDown";
LogBlock logger(log, gblDiagLogBase, fnname, VXIREC_MODULE);
logger = VXIrecData::ShutDown();
return VXIrec_RESULT_SUCCESS;
}
// Create an VXIrecInterface object and return.
//
VXIREC_API VXIrecResult VXIrecCreateResource(VXIlogInterface *log,
VXIinetInterface *inet,
VXIcacheInterface *cache,
VXIpromptInterface *prompt,
VXItelInterface *tel,
VXIrecInterface **rec)
{
if (!log) return VXIrec_RESULT_INVALID_ARGUMENT;
const wchar_t* fnname = L"VXIrecCreateResource";
LogBlock logger(log, gblDiagLogBase, fnname, VXIREC_MODULE);
VXIrecImpl* pp = new VXIrecImpl();
if (pp == NULL) {
logger = VXIrec_RESULT_OUT_OF_MEMORY;
return VXIrec_RESULT_OUT_OF_MEMORY;
}
VXIrecData* tp = new VXIrecData(log, inet);
if (tp == NULL) {
logger = VXIrec_RESULT_OUT_OF_MEMORY;
return VXIrec_RESULT_OUT_OF_MEMORY;
}
pp->recData = tp;
pp->intf.GetVersion = VXIrecGetVersion;
pp->intf.GetImplementationName = VXIrecGetImplementationName;
pp->intf.BeginSession = VXIrecBeginSession;
pp->intf.EndSession = VXIrecEndSession;
pp->intf.LoadGrammarURI = VXIrecLoadGrammarFromURI;
pp->intf.LoadGrammarString = VXIrecLoadGrammarFromString;
pp->intf.LoadGrammarOption = VXIrecLoadGrammarOption;
pp->intf.ActivateGrammar = VXIrecActivateGrammar;
pp->intf.DeactivateGrammar = VXIrecDeactivateGrammar;
pp->intf.FreeGrammar = VXIrecFreeGrammar;
pp->intf.Recognize = VXIrecRecognize;
pp->intf.Record = VXIrecRecord;
pp->intf.HotwordTransfer = VXIrecHotwordTransfer;
pp->intf.SupportsHotwordTransfer = VXIrecSupportsHotwordTransfer;
pp->intf.GetMatchedGrammar = VXIrecGetMatchedGrammar;
*rec = &pp->intf;
return VXIrec_RESULT_SUCCESS;
}
// Free VXIrec structure allocated in VXIrecCreateResource.
//
VXIREC_API VXIrecResult VXIrecDestroyResource(VXIrecInterface **rec)
{
if (rec == NULL || *rec == NULL) return VXIrec_RESULT_INVALID_ARGUMENT;
VXIrecImpl* recImpl = reinterpret_cast<VXIrecImpl*>(*rec);
VXIrecData * tp = recImpl->recData;
if ( tp ) {
const wchar_t* fnname = L"VXIrecDestroyResource";
LogBlock logger(tp->GetLog(), gblDiagLogBase, fnname, VXIREC_MODULE);
delete tp;
}
delete recImpl;
*rec = NULL;
return VXIrec_RESULT_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -