summaryrefslogtreecommitdiffstats
path: root/lib/picoctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/picoctrl.c')
-rw-r--r--lib/picoctrl.c840
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 */