diff options
Diffstat (limited to 'lib/picoctrl.c')
-rw-r--r-- | lib/picoctrl.c | 840 |
1 files changed, 840 insertions, 0 deletions
diff --git a/lib/picoctrl.c b/lib/picoctrl.c new file mode 100644 index 0000000..5af70e3 --- /dev/null +++ b/lib/picoctrl.c @@ -0,0 +1,840 @@ +/* + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file picoctrl.c + * + * Control PU -- Implementation + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#include "picodefs.h" +#include "picoos.h" +#include "picodbg.h" +#include "picodata.h" +#include "picorsrc.h" + +/* processing unit definitions */ +#include "picotok.h" +#include "picopr.h" +#include "picowa.h" +#include "picosa.h" +#include "picoacph.h" +#include "picospho.h" +#include "picopam.h" +#include "picocep.h" +#include "picosig.h" +#if defined(PICO_DEVEL_MODE) +#include "../history/picosink.h" +#endif + +#include "picoctrl.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/** + * @addtogroup picoctrl + * @b Control + * The "control" is a processing unit (PU) that contains and governs a sequence of sub-PUs + * (TTS processing chain). + * At each step (ctrlStep) it passes control to one of the sub-PUs (currrent PU). It may re-assign + * the role of "current PU" to another sub-PU, according to the status information returned from each PU. + */ + +/*---------------------------------------------------------- + * object : Control + * shortcut : ctrl + * derived from : picodata_ProcessingUnit + * implements a ProcessingUnit by creating and controlling + * a sequence of Processing Units (of possibly different + * implementations) exchanging data via CharBuffers + * ---------------------------------------------------------*/ +/* control sub-object */ +typedef struct ctrl_subobj { + picoos_uint8 numProcUnits; + picoos_uint8 curPU; + picoos_uint8 lastItemTypeProduced; + picodata_ProcessingUnit procUnit [PICOCTRL_MAX_PROC_UNITS]; + picodata_step_result_t procStatus [PICOCTRL_MAX_PROC_UNITS]; + picodata_CharBuffer procCbOut [PICOCTRL_MAX_PROC_UNITS]; +} ctrl_subobj_t; + +/** + * performs Control PU initialization + * @param this : pointer to Control PU + * @return PICO_OK : processing done + * @return PICO_ERR_OTHER : init error + * @callgraph + * @callergraph + */ +static pico_status_t ctrlInitialize(register picodata_ProcessingUnit this) { + register ctrl_subobj_t * ctrl; + pico_status_t status= PICO_OK; + picoos_int8 i; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + ctrl = (ctrl_subobj_t *) this->subObj; + ctrl->curPU = 0; + ctrl->lastItemTypeProduced=0; /*no item produced by default*/ + status = PICO_OK; + for (i = 0; i < ctrl->numProcUnits; i++) { + if (PICO_OK == status) { + status = ctrl->procUnit[i]->initialize(ctrl->procUnit[i]); + PICODBG_DEBUG(("(re-)initializing procUnit[%i] returned status %i",i, status)); + } + if (PICO_OK == status) { + status = picodata_cbReset(ctrl->procCbOut[i]); + PICODBG_DEBUG(("(re-)initializing procCbOut[%i] returned status %i",i, status)); + } + } + if (PICO_OK != status) { + picoos_emRaiseException(this->common->em,status,NULL,(picoos_char*)"problem (re-)initializing the engine"); + } + return status; +}/*ctrlInitialize*/ + + +/** + * performs one processing step + * @param this : pointer to Control PU + * @param mode : activation mode (unused) + * @param bytesOutput : number of bytes produced during this step (output) + * @return PICO_OK : processing done + * @return PICO_EXC_OUT_OF_MEM : no more memory available + * @return PICO_ERR_OTHER : other error + * @callgraph + * @callergraph + */ +static picodata_step_result_t ctrlStep(register picodata_ProcessingUnit this, + picoos_int16 mode, picoos_uint16 * bytesOutput) { + /* rules/invariants: + * - all pu's above current have status idle except possibly pu+1, which may be busy. + * (The latter is set if any pu->step produced output) + * - a pu returns idle iff its cbIn is empty and it has no more data ready for output */ + + register ctrl_subobj_t * ctrl = (ctrl_subobj_t *) this->subObj; + picodata_step_result_t status; + picoos_uint16 puBytesOutput; +#if defined(PICO_DEVEL_MODE) + picoos_uint8 btype; +#endif + + *bytesOutput = 0; + ctrl->lastItemTypeProduced=0; /*no item produced by default*/ + + /* --------------------- */ + /* do step of current pu */ + /* --------------------- */ + status = ctrl->procStatus[ctrl->curPU] = ctrl->procUnit[ctrl->curPU]->step( + ctrl->procUnit[ctrl->curPU], mode, &puBytesOutput); + + if (puBytesOutput) { + +#if defined(PICO_DEVEL_MODE) + /*store the type of item produced*/ + btype = picodata_cbGetFrontItemType(ctrl->procUnit[ctrl->curPU]->cbOut); + ctrl->lastItemTypeProduced=(picoos_uint8)btype; +#endif + + if (ctrl->curPU < ctrl->numProcUnits-1) { + /* data was output to internal PU buffers : set following pu to busy */ + ctrl->procStatus[ctrl->curPU + 1] = PICODATA_PU_BUSY; + } else { + /* data was output to caller output buffer */ + *bytesOutput = puBytesOutput; + } + } + /* recalculate state depending on pu status returned from curPU */ + switch (status) { + case PICODATA_PU_ATOMIC: + PICODBG_DEBUG(("got PICODATA_PU_ATOMIC")); + return status; + break; + + case PICODATA_PU_BUSY: + PICODBG_DEBUG(("got PICODATA_PU_BUSY")); + if ( (ctrl->curPU+1 < ctrl->numProcUnits) && (PICODATA_PU_BUSY + == ctrl->procStatus[ctrl->curPU+1])) { + ctrl->curPU++; + } + return status; + break; + + case PICODATA_PU_IDLE: + PICODBG_DEBUG(("got PICODATA_PU_IDLE")); + if ( (ctrl->curPU+1 < ctrl->numProcUnits) && (PICODATA_PU_BUSY + == ctrl->procStatus[ctrl->curPU+1])) { + /* still data to process below */ + ctrl->curPU++; + } else if (0 == ctrl->curPU) { /* all pu's are idle */ + /* nothing to do */ + } else { /* find non-idle pu above */ + PICODBG_DEBUG(( + "find non-idle pu above from pu %d with status %d", + ctrl->curPU, ctrl->procStatus[ctrl->curPU])); + while ((ctrl->curPU > 0) && (PICODATA_PU_IDLE + == ctrl->procStatus[ctrl->curPU])) { + ctrl->curPU--; + } + ctrl->procStatus[ctrl->curPU] = PICODATA_PU_BUSY; + } + PICODBG_DEBUG(("going to pu %d with status %d", + ctrl->curPU, ctrl->procStatus[ctrl->curPU])); + /*update last scheduled PU*/ + return ctrl->procStatus[ctrl->curPU]; + break; + + case PICODATA_PU_OUT_FULL: + PICODBG_DEBUG(("got PICODATA_PU_OUT_FULL")); + if (ctrl->curPU+1 < ctrl->numProcUnits) { /* let pu below empty buffer */ + ctrl->curPU++; + ctrl->procStatus[ctrl->curPU] = PICODATA_PU_BUSY; + } else { + /* nothing more to do, out_full will be returned to caller */ + } + return ctrl->procStatus[ctrl->curPU]; + break; + default: + return PICODATA_PU_ERROR; + break; + } +}/*ctrlStep*/ + +/** + * terminates Control PU + * @param this : pointer to Control PU + * @return PICO_OK : processing done + * @return PICO_ERR_OTHER : other error + * @callgraph + * @callergraph + */ +static pico_status_t ctrlTerminate(register picodata_ProcessingUnit this) { + pico_status_t status = PICO_OK; + picoos_int16 i; + register ctrl_subobj_t * ctrl; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + ctrl = (ctrl_subobj_t *) this->subObj; + for (i = 0; i < ctrl->numProcUnits; i++) { + status = ctrl->procUnit[i]->terminate(ctrl->procUnit[i]); + PICODBG_DEBUG(("terminating procUnit[%i] returned status %i",i, status)); + if (PICO_OK != status) { + return status; + } + } + return status; +}/*ctrlTerminate*/ + +/** + * deallocates Control PU's subobject + * @param this : pointer to Control PU + * @return PICO_OK : processing done + * @return PICO_ERR_OTHER : other error + * @callgraph + * @callergraph + */ +static pico_status_t ctrlSubObjDeallocate(register picodata_ProcessingUnit this, + picoos_MemoryManager mm) { + register ctrl_subobj_t * ctrl; + picoos_int16 i; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + ctrl = (ctrl_subobj_t *) this->subObj; + mm = mm; /* fix warning "var not used in this function"*/ + /* deallocate members (procCbOut and procUnit) */ + for (i = ctrl->numProcUnits-1; i >= 0; i--) { + picodata_disposeProcessingUnit(this->common->mm,&ctrl->procUnit[i]); + picodata_disposeCharBuffer(this->common->mm, &ctrl->procCbOut[i]); + } + /* deallocate object itself */ + picoos_deallocate(this->common->mm, (void *) &this->subObj); + + return PICO_OK; +}/*ctrlSubObjDeallocate*/ + +/** + * inserts a new PU in the TTS processing chain + * @param this : pointer to Control PU + * @param puType : type of the PU to be inserted + * @param last : if true, inserted PU is the last in the TTS processing chain + * @return PICO_OK : processing done + * @return PICO_EXC_OUT_OF_MEM : no more memory available + * @return PICO_ERR_OTHER : other error + * @remarks Calls the PU object creation method + * @callgraph + * @callergraph + */ +static pico_status_t ctrlAddPU(register picodata_ProcessingUnit this, + picodata_putype_t puType, + picoos_bool levelAwareCbOut, + picoos_bool last) +{ + picoos_uint16 bufSize; + register ctrl_subobj_t * ctrl; + picodata_CharBuffer cbIn; + picoos_uint8 newPU; + if (this == NULL) { + return PICO_ERR_OTHER; + } + ctrl = (ctrl_subobj_t *) this->subObj; + if (ctrl == NULL) { + return PICO_ERR_OTHER; + } + newPU = ctrl->numProcUnits; + if (0 == newPU) { + PICODBG_DEBUG(("taking cbIn of this because adding first pu")); + cbIn = this->cbIn; + } else { + PICODBG_DEBUG(("taking cbIn of previous pu")); + cbIn = ctrl->procCbOut[newPU-1]; + } + if (last) { + PICODBG_DEBUG(("taking cbOut of this because adding last pu")); + ctrl->procCbOut[newPU] = this->cbOut; + } else { + PICODBG_DEBUG(("creating intermediate cbOut of pu[%i]", newPU)); + bufSize = picodata_get_default_buf_size(puType); + ctrl->procCbOut[newPU] = picodata_newCharBuffer(this->common->mm, + this->common,bufSize); + + PICODBG_DEBUG(("intermediate cbOut of pu[%i] (address %i)", newPU, + (picoos_uint32) ctrl->procCbOut[newPU])); + if (NULL == ctrl->procCbOut[newPU]) { + return PICO_EXC_OUT_OF_MEM; + } + } + ctrl->procStatus[newPU] = PICODATA_PU_IDLE; + /*...............*/ + switch (puType) { + case PICODATA_PUTYPE_TOK: + PICODBG_DEBUG(("creating TokenizeUnit for pu %i", newPU)); + ctrl->procUnit[newPU] = picotok_newTokenizeUnit(this->common->mm, + this->common, cbIn, ctrl->procCbOut[newPU], this->voice); + break; + case PICODATA_PUTYPE_PR: + PICODBG_DEBUG(("creating PreprocUnit for pu %i", newPU)); + ctrl->procUnit[newPU] = picopr_newPreprocUnit(this->common->mm, + this->common, cbIn, ctrl->procCbOut[newPU], this->voice); + break; + case PICODATA_PUTYPE_WA: + PICODBG_DEBUG(("creating WordAnaUnit for pu %i", newPU)); + ctrl->procUnit[newPU] = picowa_newWordAnaUnit(this->common->mm, + this->common, cbIn, ctrl->procCbOut[newPU], this->voice); + break; + case PICODATA_PUTYPE_SA: + PICODBG_DEBUG(("creating SentAnaUnit for pu %i", newPU)); + ctrl->procUnit[newPU] = picosa_newSentAnaUnit(this->common->mm, + this->common, cbIn, ctrl->procCbOut[newPU], this->voice); + break; + case PICODATA_PUTYPE_ACPH: + PICODBG_DEBUG(("creating AccPhrUnit for pu %i", newPU)); + ctrl->procUnit[newPU] = picoacph_newAccPhrUnit(this->common->mm, + this->common, cbIn, ctrl->procCbOut[newPU], this->voice); + break; + case PICODATA_PUTYPE_SPHO: + PICODBG_DEBUG(("creating SentPhoUnit for pu %i", newPU)); + ctrl->procUnit[newPU] = picospho_newSentPhoUnit(this->common->mm, + this->common, cbIn, ctrl->procCbOut[newPU], this->voice); + break; + case PICODATA_PUTYPE_PAM: + PICODBG_DEBUG(("creating PAMUnit for pu %i", newPU)); + ctrl->procUnit[newPU] = picopam_newPamUnit(this->common->mm, + this->common, cbIn, ctrl->procCbOut[newPU], this->voice); + break; + case PICODATA_PUTYPE_CEP: + PICODBG_DEBUG(("creating CepUnit for pu %i", newPU)); + ctrl->procUnit[newPU] = picocep_newCepUnit(this->common->mm, + this->common, cbIn, ctrl->procCbOut[newPU], this->voice); + break; +#if defined(PICO_DEVEL_MODE) + case PICODATA_PUTYPE_SINK: + PICODBG_DEBUG(("creating SigUnit for pu %i", newPU)); + ctrl->procUnit[newPU] = picosink_newSinkUnit(this->common->mm, + this->common, cbIn, ctrl->procCbOut[newPU], this->voice); + break; +#endif + case PICODATA_PUTYPE_SIG: + PICODBG_DEBUG(("creating SigUnit for pu %i", newPU)); + ctrl->procUnit[newPU] = picosig_newSigUnit(this->common->mm, + this->common, cbIn, ctrl->procCbOut[newPU], this->voice); + break; + default: + ctrl->procUnit[newPU] = picodata_newProcessingUnit( + this->common->mm, this->common, cbIn, + ctrl->procCbOut[newPU], this->voice); + break; + } + if (NULL == ctrl->procUnit[newPU]) { + picodata_disposeCharBuffer(this->common->mm,&ctrl->procCbOut[newPU]); + return PICO_EXC_OUT_OF_MEM; + } + ctrl->numProcUnits++; + return PICO_OK; +}/*ctrlAddPU*/ + +/*forward declaration : see below for full function body*/ +void picoctrl_disposeControl(picoos_MemoryManager mm, + picodata_ProcessingUnit * this); + +/** + * initializes a control PU object + * @param mm : memory manager + * @param common : the common object + * @param cbIn : the input char buffer + * @param cbOut : the output char buffer + * @param voice : the voice object + * @return the pointer to the PU object created if OK + * @return PICO_EXC_OUT_OF_MEM : no more memory available + * @return NULL otherwise + * @callgraph + * @callergraph + */ +picodata_ProcessingUnit picoctrl_newControl(picoos_MemoryManager mm, + picoos_Common common, picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, picorsrc_Voice voice) { + picoos_int16 i; + register ctrl_subobj_t * ctrl; + picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, + cbOut,voice); + if (this == NULL) { + return NULL; + } + + this->initialize = ctrlInitialize; + this->step = ctrlStep; + this->terminate = ctrlTerminate; + this->subDeallocate = ctrlSubObjDeallocate; + + this->subObj = picoos_allocate(mm, sizeof(ctrl_subobj_t)); + if (this->subObj == NULL) { + picoos_deallocate(mm, (void **)(void*)&this); + return NULL; + } + + ctrl = (ctrl_subobj_t *) this->subObj; + + for (i=0; i < PICOCTRL_MAX_PROC_UNITS; i++) { + ctrl->procUnit[i] = NULL; + ctrl->procStatus[i] = PICODATA_PU_IDLE; + ctrl->procCbOut[i] = NULL; + } + ctrl->numProcUnits = 0; + + if ( + (PICO_OK == ctrlAddPU(this,PICODATA_PUTYPE_TOK, FALSE, /*last*/FALSE)) && + (PICO_OK == ctrlAddPU(this,PICODATA_PUTYPE_PR, FALSE, FALSE)) && + (PICO_OK == ctrlAddPU(this,PICODATA_PUTYPE_WA, FALSE, FALSE)) && + (PICO_OK == ctrlAddPU(this,PICODATA_PUTYPE_SA, FALSE, FALSE)) && + (PICO_OK == ctrlAddPU(this,PICODATA_PUTYPE_ACPH, FALSE, FALSE)) && + (PICO_OK == ctrlAddPU(this,PICODATA_PUTYPE_SPHO, FALSE, FALSE)) && + (PICO_OK == ctrlAddPU(this,PICODATA_PUTYPE_PAM, FALSE, FALSE)) && + (PICO_OK == ctrlAddPU(this,PICODATA_PUTYPE_CEP, FALSE, FALSE)) && + (PICO_OK == ctrlAddPU(this,PICODATA_PUTYPE_SIG, FALSE, TRUE)) + ) { + + /* we don't call ctrlInitialize here because ctrlAddPU does initialize the PUs allready and the only thing + * remaining to initialize is: + */ + ctrl->curPU = 0; + return this; + } else { + picoctrl_disposeControl(this->common->mm,&this); + return NULL; + } + +}/*picoctrl_newControl*/ + +/** + * disposes a Control PU + * @param mm : memory manager + * @param this : pointer to Control PU + * + * @return void + * @callgraph + * @callergraph + */ +void picoctrl_disposeControl(picoos_MemoryManager mm, + picodata_ProcessingUnit * this) +{ + picodata_disposeProcessingUnit(mm, this); +}/*picoctrl_disposeControl*/ + +/* ************************************************************************** + * + * Engine + * + ****************************************************************************/ +/** object : Engine + * shortcut : eng + */ +typedef struct picoctrl_engine { + picoos_uint32 magic; /* magic number used to validate handles */ + void *raw_mem; + picoos_Common common; + picorsrc_Voice voice; + picodata_ProcessingUnit control; + picodata_CharBuffer cbIn, cbOut; +} picoctrl_engine_t; + + +#define MAGIC_MASK 0x5069436F /* PiCo */ + +#define SET_MAGIC_NUMBER(eng) \ + (eng)->magic = ((picoos_uint32) (eng)) ^ MAGIC_MASK + +#define CHECK_MAGIC_NUMBER(eng) \ + ((eng)->magic == (((picoos_uint32) (eng)) ^ MAGIC_MASK)) + +/** + * performs an engine reset + * @param this : the engine object + * @return PICO_OK : reset performed + * @return otherwise error code + * @callgraph + * @callergraph + */ +pico_status_t picoctrl_engReset(picoctrl_Engine this) +{ + pico_status_t status; + + if (NULL == this) { + return PICO_ERR_NULLPTR_ACCESS; + } + picoos_emReset(this->common->em); + + status = this->control->terminate(this->control); + if (PICO_OK == status) { + status = this->control->initialize(this->control); + } + if (PICO_OK == status) { + status = picodata_cbReset(this->cbIn); + } + if (PICO_OK == status) { + status = picodata_cbReset(this->cbOut); + } + if (PICO_OK != status) { + picoos_emRaiseException(this->common->em,status,NULL,(picoos_char*) "problem resetting engine"); + } + return status; +} + +/** + * checks an engine handle + * @param this : the engine object + * @return PICO_OK : reset performed + * @return non-zero if 'this' is a valid engine handle + * @return zero otherwise + * @callgraph + * @callergraph + */ +picoos_int16 picoctrl_isValidEngineHandle(picoctrl_Engine this) +{ + return (this != NULL) && CHECK_MAGIC_NUMBER(this); +}/*picoctrl_isValidEngineHandle*/ + +/** + * creates a new engine object + * @param mm : memory manager to be used for this engine + * @param rm : resource manager to be used for this engine + * @param voiceName : voice definition to be used for this engine + * @return PICO_OK : reset performed + * @return new engine handle + * @return NULL otherwise + * @callgraph + * @callergraph + */ +picoctrl_Engine picoctrl_newEngine(picoos_MemoryManager mm, + picorsrc_ResourceManager rm, const picoos_char * voiceName) { + picoos_uint8 done= TRUE; + + picoos_uint16 bSize; + + picoos_MemoryManager engMM; + picoos_ExceptionManager engEM; + + picoctrl_Engine this = (picoctrl_Engine) picoos_allocate(mm, sizeof(*this)); + + PICODBG_DEBUG(("creating engine for voice '%s'",voiceName)); + + done = (NULL != this); + + if (done) { + this->magic = 0; + this->common = NULL; + this->voice = NULL; + this->control = NULL; + this->cbIn = NULL; + this->cbOut = NULL; + + this->raw_mem = picoos_allocate(mm, PICOCTRL_DEFAULT_ENGINE_SIZE); + if (NULL == this->raw_mem) { + done = FALSE; + } + } + + if (done) { + engMM = picoos_newMemoryManager(this->raw_mem, PICOCTRL_DEFAULT_ENGINE_SIZE, + /*enableMemProt*/ FALSE); + done = (NULL != engMM); + } + if (done) { + this->common = picoos_newCommon(engMM); + engEM = picoos_newExceptionManager(engMM); + done = (NULL != this->common) && (NULL != engEM); + } + if (done) { + this->common->mm = engMM; + this->common->em = engEM; + + done = (PICO_OK == picorsrc_createVoice(rm,voiceName,&(this->voice))); + } + if (done) { + bSize = picodata_get_default_buf_size(PICODATA_PUTYPE_TEXT); + + this->cbIn = picodata_newCharBuffer(this->common->mm, + this->common, bSize); + bSize = picodata_get_default_buf_size(PICODATA_PUTYPE_SIG); + + this->cbOut = picodata_newCharBuffer(this->common->mm, + this->common, bSize); + + PICODBG_DEBUG(("cbOut has address %i", (picoos_uint32) this->cbOut)); + + + this->control = picoctrl_newControl(this->common->mm, this->common, + this->cbIn, this->cbOut, this->voice); + done = (NULL != this->cbIn) && (NULL != this->cbOut) + && (NULL != this->control); + } + if (done) { + SET_MAGIC_NUMBER(this); + } else { + if (NULL != this) { + if (NULL != this->voice) { + picorsrc_releaseVoice(rm,&(this->voice)); + } + if(NULL != this->raw_mem) { + picoos_deallocate(mm,&(this->raw_mem)); + } + picoos_deallocate(mm,(void *)&this); + } + } + return this; +}/*picoctrl_newEngine*/ + +/** + * disposes an engine object + * @param mm : memory manager associated to the engine + * @param rm : resource manager associated to the engine + * @param this : handle of the engine to dispose + * @return PICO_OK : reset performed + * @return void + * @callgraph + * @callergraph + */ +void picoctrl_disposeEngine(picoos_MemoryManager mm, picorsrc_ResourceManager rm, + picoctrl_Engine * this) +{ + if (NULL != (*this)) { + if (NULL != (*this)->voice) { + picorsrc_releaseVoice(rm,&((*this)->voice)); + } + if(NULL != (*this)->control) { + picoctrl_disposeControl((*this)->common->mm,&((*this)->control)); + } + if(NULL != (*this)->raw_mem) { + picoos_deallocate(mm,&((*this)->raw_mem)); + } + (*this)->magic ^= 0xFFFEFDFC; + picoos_deallocate(mm,(void **)this); + } +}/*picoctrl_disposeEngine*/ + +/** + * resets the exception manager of an engine + * @param this : handle of the engine + * @return void + * @callgraph + * @callergraph + */ +void picoctrl_engResetExceptionManager( + picoctrl_Engine this + ) +{ + picoos_emReset(this->common->em); +}/*picoctrl_engResetExceptionManager*/ + +/** + * returns the engine common pointer + * @param this : handle of the engine + * @return PICO_OK : reset performed + * @return the engine common pointer + * @return NULL if error + * @callgraph + * @callergraph + */ +picoos_Common picoctrl_engGetCommon(picoctrl_Engine this) { + if (NULL == this) { + return NULL; + } else { + return this->common; + } +}/*picoctrl_engGetCommon*/ + +/** + * feed raw 'text' into 'engine'. text may contain '\\0'. + * @param this : handle of the engine + * @param text : the input text + * @param textSize : size of the input text + * @param *bytesPut : the number of bytes effectively consumed from 'text'. + * @return PICO_OK : feeding succeded + * @return PICO_ERR_OTHER : if error + * @callgraph + * @callergraph + */ +pico_status_t picoctrl_engFeedText(picoctrl_Engine this, + picoos_char * text, + picoos_int16 textSize, picoos_int16 * bytesPut) { + if (NULL == this) { + return PICO_ERR_OTHER; + } + PICODBG_DEBUG(("get \"%.100s\"", text)); + *bytesPut = 0; + while ((*bytesPut < textSize) && (PICO_OK == picodata_cbPutCh(this->cbIn, text[*bytesPut]))) { + (*bytesPut)++; + } + + return PICO_OK; +}/*picoctrl_engFeedText*/ + +/** + * gets engine output bytes + * @param this : handle of the engine + * @param buffer : the destination buffer + * @param bufferSize : max size of the destinatioon buffer + * @param *bytesReceived : the number of bytes effectively returned + * @return PICO_OK : feeding succeded + * @return PICO_ERR_OTHER : if error + * @callgraph + * @callergraph + */ +picodata_step_result_t picoctrl_engFetchOutputItemBytes( + picoctrl_Engine this, + picoos_char *buffer, + picoos_int16 bufferSize, + picoos_int16 *bytesReceived) { + picoos_uint16 ui; + picodata_step_result_t stepResult; + pico_status_t rv; + + if (NULL == this) { + return (picodata_step_result_t)PICO_STEP_ERROR; + } + PICODBG_DEBUG(("doing one step")); + stepResult = this->control->step(this->control,/* mode */0,&ui); + if (PICODATA_PU_ERROR != stepResult) { + PICODBG_TRACE(("filling output buffer")); + rv = picodata_cbGetSpeechData(this->cbOut, (picoos_uint8 *)buffer, + bufferSize, &ui); + + if (ui > 255) { /* because picoapi uses signed int16 */ + return (picodata_step_result_t)PICO_STEP_ERROR; + } else { + *bytesReceived = ui; + } + if ((rv == PICO_EXC_BUF_UNDERFLOW) || (rv == PICO_EXC_BUF_OVERFLOW)) { + PICODBG_ERROR(("problem getting speech data")); + return (picodata_step_result_t)PICO_STEP_ERROR; + } + /* rv must now be PICO_OK or PICO_EOF */ + PICODBG_ASSERT(((PICO_EOF == rv) || (PICO_OK == rv))); + if ((PICODATA_PU_IDLE == stepResult) && (PICO_EOF == rv)) { + PICODBG_DEBUG(("IDLE")); + return (picodata_step_result_t)PICO_STEP_IDLE; + } else if (PICODATA_PU_ERROR == stepResult) { + PICODBG_DEBUG(("ERROR")); + return (picodata_step_result_t)PICO_STEP_ERROR; + } else { + PICODBG_DEBUG(("BUSY")); + return (picodata_step_result_t)PICO_STEP_BUSY; + } + } else { + return (picodata_step_result_t)PICO_STEP_ERROR; + } +}/*picoctrl_engFetchOutputItemBytes*/ + +/** + * returns the last scheduled PU + * @param this : handle of the engine + * @return a value >= 0 : last scheduled PU index + * @remarks designed to be used for performance evaluation + * @callgraph + * @callergraph + */ +picodata_step_result_t picoctrl_getLastScheduledPU( + picoctrl_Engine this + ) +{ + ctrl_subobj_t * ctrl; + if (NULL == this || NULL == this->control->subObj) { + return PICO_ERR_OTHER; + } + ctrl = (ctrl_subobj_t *) ((*this).control->subObj); + return (picodata_step_result_t) ctrl->curPU; +}/*picoctrl_getLastScheduledPU*/ + +/** + * returns the last item type produced by the last scheduled PU + * @param this : handle of the engine + * @return a value >= 0 : item type (see picodata.h for item types) + * @return a value = 0 : no item produced + * @remarks designed to be used for performance evaluation + * @callgraph + * @callergraph + */ +picodata_step_result_t picoctrl_getLastProducedItemType( + picoctrl_Engine this + ) +{ + ctrl_subobj_t * ctrl; + if (NULL == this || NULL == this->control->subObj) { + return PICO_ERR_OTHER; + } + ctrl = (ctrl_subobj_t *) ((*this).control->subObj); + return (picodata_step_result_t) ctrl->lastItemTypeProduced; +}/*picoctrl_getLastProducedItemType*/ + + +#ifdef __cplusplus +} +#endif + +/* Picoctrl.c end */ |