From 1284d937084a20b457c280259fff59391129509a Mon Sep 17 00:00:00 2001 From: Charles Chen Date: Mon, 22 Jun 2009 16:25:25 -0700 Subject: Moving PicoTts plugin under the pico directory of external/svox --- Android.mk | 95 +- AndroidManifest.xml | 52 - lib/picoacph.c | 1430 -------- lib/picoacph.h | 205 -- lib/picoapi.c | 801 ----- lib/picoapi.h | 469 --- lib/picoapid.h | 70 - lib/picobase.c | 1243 ------- lib/picobase.h | 171 - lib/picocep.c | 1965 ---------- lib/picocep.h | 54 - lib/picoctrl.c | 840 ----- lib/picoctrl.h | 101 - lib/picodata.c | 1152 ------ lib/picodata.h | 643 ---- lib/picodbg.c | 438 --- lib/picodbg.h | 311 -- lib/picodefs.h | 173 - lib/picodsp.h | 112 - lib/picoextapi.c | 228 -- lib/picoextapi.h | 163 - lib/picofftsg.c | 3274 ----------------- lib/picofftsg.h | 54 - lib/picokdbg.c | 173 - lib/picokdbg.h | 82 - lib/picokdt.c | 2642 -------------- lib/picokdt.h | 465 --- lib/picokfst.c | 438 --- lib/picokfst.h | 169 - lib/picoklex.c | 572 --- lib/picoklex.h | 129 - lib/picoknow.c | 81 - lib/picoknow.h | 190 - lib/picokpdf.c | 381 -- lib/picokpdf.h | 160 - lib/picokpr.c | 652 ---- lib/picokpr.h | 147 - lib/picoktab.c | 1118 ------ lib/picoktab.h | 224 -- lib/picoos.c | 2309 ------------ lib/picoos.h | 550 --- lib/picopal.c | 554 --- lib/picopal.h | 288 -- lib/picopam.c | 4803 ------------------------- lib/picopam.h | 79 - lib/picopltf.h | 73 - lib/picopr.c | 3550 ------------------ lib/picopr.h | 63 - lib/picorsrc.c | 1028 ------ lib/picorsrc.h | 185 - lib/picosa.c | 1738 --------- lib/picosa.h | 216 -- lib/picosig.c | 1280 ------- lib/picosig.h | 64 - lib/picosig2.c | 4090 --------------------- lib/picosig2.h | 229 -- lib/picospho.c | 1694 --------- lib/picospho.h | 175 - lib/picotok.c | 1563 -------- lib/picotok.h | 115 - lib/picotrns.c | 745 ---- lib/picotrns.h | 191 - lib/picowa.c | 578 --- lib/picowa.h | 135 - pico/Android.mk | 92 + pico/AndroidManifest.xml | 52 + pico/lib/picoacph.c | 1430 ++++++++ pico/lib/picoacph.h | 205 ++ pico/lib/picoapi.c | 801 +++++ pico/lib/picoapi.h | 469 +++ pico/lib/picoapid.h | 70 + pico/lib/picobase.c | 1243 +++++++ pico/lib/picobase.h | 171 + pico/lib/picocep.c | 1965 ++++++++++ pico/lib/picocep.h | 54 + pico/lib/picoctrl.c | 840 +++++ pico/lib/picoctrl.h | 101 + pico/lib/picodata.c | 1152 ++++++ pico/lib/picodata.h | 643 ++++ pico/lib/picodbg.c | 438 +++ pico/lib/picodbg.h | 311 ++ pico/lib/picodefs.h | 173 + pico/lib/picodsp.h | 112 + pico/lib/picoextapi.c | 228 ++ pico/lib/picoextapi.h | 163 + pico/lib/picofftsg.c | 3274 +++++++++++++++++ pico/lib/picofftsg.h | 54 + pico/lib/picokdbg.c | 173 + pico/lib/picokdbg.h | 82 + pico/lib/picokdt.c | 2642 ++++++++++++++ pico/lib/picokdt.h | 465 +++ pico/lib/picokfst.c | 438 +++ pico/lib/picokfst.h | 169 + pico/lib/picoklex.c | 572 +++ pico/lib/picoklex.h | 129 + pico/lib/picoknow.c | 81 + pico/lib/picoknow.h | 190 + pico/lib/picokpdf.c | 381 ++ pico/lib/picokpdf.h | 160 + pico/lib/picokpr.c | 652 ++++ pico/lib/picokpr.h | 147 + pico/lib/picoktab.c | 1118 ++++++ pico/lib/picoktab.h | 224 ++ pico/lib/picoos.c | 2309 ++++++++++++ pico/lib/picoos.h | 550 +++ pico/lib/picopal.c | 554 +++ pico/lib/picopal.h | 288 ++ pico/lib/picopam.c | 4803 +++++++++++++++++++++++++ pico/lib/picopam.h | 79 + pico/lib/picopltf.h | 73 + pico/lib/picopr.c | 3550 ++++++++++++++++++ pico/lib/picopr.h | 63 + pico/lib/picorsrc.c | 1028 ++++++ pico/lib/picorsrc.h | 185 + pico/lib/picosa.c | 1738 +++++++++ pico/lib/picosa.h | 216 ++ pico/lib/picosig.c | 1280 +++++++ pico/lib/picosig.h | 64 + pico/lib/picosig2.c | 4090 +++++++++++++++++++++ pico/lib/picosig2.h | 229 ++ pico/lib/picospho.c | 1694 +++++++++ pico/lib/picospho.h | 175 + pico/lib/picotok.c | 1563 ++++++++ pico/lib/picotok.h | 115 + pico/lib/picotrns.c | 745 ++++ pico/lib/picotrns.h | 191 + pico/lib/picowa.c | 578 +++ pico/lib/picowa.h | 135 + pico/res/layout/main.xml | 30 + pico/res/values/strings.xml | 22 + pico/src/com/svox/pico/CheckVoiceData.java | 60 + pico/src/com/svox/pico/DownloadVoiceData.java | 37 + pico/src/com/svox/pico/Pico.java | 42 + pico/tts/com_svox_picottsengine.cpp | 1039 ++++++ res/layout/main.xml | 30 - res/values/strings.xml | 22 - src/com/svox/pico/CheckVoiceData.java | 60 - src/com/svox/pico/DownloadVoiceData.java | 37 - src/com/svox/pico/Pico.java | 42 - tts/com_svox_picottsengine.cpp | 1039 ------ 140 files changed, 49190 insertions(+), 49191 deletions(-) delete mode 100755 AndroidManifest.xml delete mode 100644 lib/picoacph.c delete mode 100644 lib/picoacph.h delete mode 100644 lib/picoapi.c delete mode 100644 lib/picoapi.h delete mode 100644 lib/picoapid.h delete mode 100644 lib/picobase.c delete mode 100644 lib/picobase.h delete mode 100644 lib/picocep.c delete mode 100644 lib/picocep.h delete mode 100644 lib/picoctrl.c delete mode 100644 lib/picoctrl.h delete mode 100644 lib/picodata.c delete mode 100644 lib/picodata.h delete mode 100644 lib/picodbg.c delete mode 100644 lib/picodbg.h delete mode 100644 lib/picodefs.h delete mode 100644 lib/picodsp.h delete mode 100644 lib/picoextapi.c delete mode 100644 lib/picoextapi.h delete mode 100644 lib/picofftsg.c delete mode 100644 lib/picofftsg.h delete mode 100644 lib/picokdbg.c delete mode 100644 lib/picokdbg.h delete mode 100644 lib/picokdt.c delete mode 100644 lib/picokdt.h delete mode 100644 lib/picokfst.c delete mode 100644 lib/picokfst.h delete mode 100644 lib/picoklex.c delete mode 100644 lib/picoklex.h delete mode 100644 lib/picoknow.c delete mode 100644 lib/picoknow.h delete mode 100644 lib/picokpdf.c delete mode 100644 lib/picokpdf.h delete mode 100644 lib/picokpr.c delete mode 100644 lib/picokpr.h delete mode 100644 lib/picoktab.c delete mode 100644 lib/picoktab.h delete mode 100644 lib/picoos.c delete mode 100644 lib/picoos.h delete mode 100644 lib/picopal.c delete mode 100644 lib/picopal.h delete mode 100644 lib/picopam.c delete mode 100644 lib/picopam.h delete mode 100644 lib/picopltf.h delete mode 100644 lib/picopr.c delete mode 100644 lib/picopr.h delete mode 100644 lib/picorsrc.c delete mode 100644 lib/picorsrc.h delete mode 100644 lib/picosa.c delete mode 100644 lib/picosa.h delete mode 100644 lib/picosig.c delete mode 100644 lib/picosig.h delete mode 100644 lib/picosig2.c delete mode 100644 lib/picosig2.h delete mode 100644 lib/picospho.c delete mode 100644 lib/picospho.h delete mode 100644 lib/picotok.c delete mode 100644 lib/picotok.h delete mode 100644 lib/picotrns.c delete mode 100644 lib/picotrns.h delete mode 100644 lib/picowa.c delete mode 100644 lib/picowa.h create mode 100755 pico/Android.mk create mode 100755 pico/AndroidManifest.xml create mode 100644 pico/lib/picoacph.c create mode 100644 pico/lib/picoacph.h create mode 100644 pico/lib/picoapi.c create mode 100644 pico/lib/picoapi.h create mode 100644 pico/lib/picoapid.h create mode 100644 pico/lib/picobase.c create mode 100644 pico/lib/picobase.h create mode 100644 pico/lib/picocep.c create mode 100644 pico/lib/picocep.h create mode 100644 pico/lib/picoctrl.c create mode 100644 pico/lib/picoctrl.h create mode 100644 pico/lib/picodata.c create mode 100644 pico/lib/picodata.h create mode 100644 pico/lib/picodbg.c create mode 100644 pico/lib/picodbg.h create mode 100644 pico/lib/picodefs.h create mode 100644 pico/lib/picodsp.h create mode 100644 pico/lib/picoextapi.c create mode 100644 pico/lib/picoextapi.h create mode 100644 pico/lib/picofftsg.c create mode 100644 pico/lib/picofftsg.h create mode 100644 pico/lib/picokdbg.c create mode 100644 pico/lib/picokdbg.h create mode 100644 pico/lib/picokdt.c create mode 100644 pico/lib/picokdt.h create mode 100644 pico/lib/picokfst.c create mode 100644 pico/lib/picokfst.h create mode 100644 pico/lib/picoklex.c create mode 100644 pico/lib/picoklex.h create mode 100644 pico/lib/picoknow.c create mode 100644 pico/lib/picoknow.h create mode 100644 pico/lib/picokpdf.c create mode 100644 pico/lib/picokpdf.h create mode 100644 pico/lib/picokpr.c create mode 100644 pico/lib/picokpr.h create mode 100644 pico/lib/picoktab.c create mode 100644 pico/lib/picoktab.h create mode 100644 pico/lib/picoos.c create mode 100644 pico/lib/picoos.h create mode 100644 pico/lib/picopal.c create mode 100644 pico/lib/picopal.h create mode 100644 pico/lib/picopam.c create mode 100644 pico/lib/picopam.h create mode 100644 pico/lib/picopltf.h create mode 100644 pico/lib/picopr.c create mode 100644 pico/lib/picopr.h create mode 100644 pico/lib/picorsrc.c create mode 100644 pico/lib/picorsrc.h create mode 100644 pico/lib/picosa.c create mode 100644 pico/lib/picosa.h create mode 100644 pico/lib/picosig.c create mode 100644 pico/lib/picosig.h create mode 100644 pico/lib/picosig2.c create mode 100644 pico/lib/picosig2.h create mode 100644 pico/lib/picospho.c create mode 100644 pico/lib/picospho.h create mode 100644 pico/lib/picotok.c create mode 100644 pico/lib/picotok.h create mode 100644 pico/lib/picotrns.c create mode 100644 pico/lib/picotrns.h create mode 100644 pico/lib/picowa.c create mode 100644 pico/lib/picowa.h create mode 100755 pico/res/layout/main.xml create mode 100755 pico/res/values/strings.xml create mode 100755 pico/src/com/svox/pico/CheckVoiceData.java create mode 100755 pico/src/com/svox/pico/DownloadVoiceData.java create mode 100755 pico/src/com/svox/pico/Pico.java create mode 100644 pico/tts/com_svox_picottsengine.cpp delete mode 100755 res/layout/main.xml delete mode 100755 res/values/strings.xml delete mode 100755 src/com/svox/pico/CheckVoiceData.java delete mode 100755 src/com/svox/pico/DownloadVoiceData.java delete mode 100755 src/com/svox/pico/Pico.java delete mode 100644 tts/com_svox_picottsengine.cpp diff --git a/Android.mk b/Android.mk index 4232ad0..6571161 100755 --- a/Android.mk +++ b/Android.mk @@ -1,94 +1 @@ -#include $(all-subdir-makefiles) - -# SVOX Pico TTS Engine -# This makefile builds both an activity and a shared library. - -ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean - -TOP_LOCAL_PATH:= $(call my-dir) - -# Build Pico activity - -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := user - -LOCAL_SRC_FILES := $(call all-subdir-java-files) - -LOCAL_PACKAGE_NAME := PicoTts - -LOCAL_JNI_SHARED_LIBRARIES := libttspico - -include $(BUILD_PACKAGE) - -# Build Pico Shared Library - -LOCAL_PATH:= $(TOP_LOCAL_PATH)/tts -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= com_svox_picottsengine.cpp - -LOCAL_C_INCLUDES += \ - external/svox/lib \ - frameworks - -LOCAL_STATIC_LIBRARIES:= libsvoxpico - -LOCAL_SHARED_LIBRARIES:= libcutils - -LOCAL_MODULE:= libttspico - -LOCAL_ARM_MODE:= arm - -LOCAL_PRELINK_MODULE:= false - -include $(BUILD_SHARED_LIBRARY) - - -# Build Base Generic SVOX Pico Library -LOCAL_PATH:= $(TOP_LOCAL_PATH)/lib -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - picoacph.c \ - picoapi.c \ - picobase.c \ - picocep.c \ - picoctrl.c \ - picodata.c \ - picodbg.c \ - picoextapi.c \ - picofftsg.c \ - picokdbg.c \ - picokdt.c \ - picokfst.c \ - picoklex.c \ - picoknow.c \ - picokpdf.c \ - picokpr.c \ - picoktab.c \ - picoos.c \ - picopal.c \ - picopam.c \ - picopr.c \ - picorsrc.c \ - picosa.c \ - picosig.c \ - picosig2.c \ - picospho.c \ - picotok.c \ - picotrns.c \ - picowa.c - -LOCAL_PRELINK_MODULE:= false - -LOCAL_MODULE:= libsvoxpico - -LOCAL_CFLAGS+= $(TOOL_CFLAGS) - -LOCAL_LDFLAGS+= $(TOOL_LDFLAGS) - -include $(BUILD_STATIC_LIBRARY) - -endif # TARGET_SIMULATOR +include $(all-subdir-makefiles) diff --git a/AndroidManifest.xml b/AndroidManifest.xml deleted file mode 100755 index 7188e70..0000000 --- a/AndroidManifest.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/picoacph.c b/lib/picoacph.c deleted file mode 100644 index 98feb6e..0000000 --- a/lib/picoacph.c +++ /dev/null @@ -1,1430 +0,0 @@ -/* - * 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 picoacph.c - * - * accentuation and phrasing - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#include "picoos.h" -#include "picodbg.h" -#include "picobase.h" -#include "picodata.h" -#include "picoacph.h" -#include "picokdt.h" -#include "picoklex.h" -#include "picoktab.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -/* PU acphStep states */ -#define SA_STEPSTATE_COLLECT 0 -#define SA_STEPSTATE_PROCESS_PHR 12 -#define SA_STEPSTATE_PROCESS_ACC 13 -#define SA_STEPSTATE_FEED 2 - - -/* boundary strength state */ -#define SA_BOUNDSTRENGTH_SSEP 0 /* sentence separator */ -#define SA_BOUNDSTRENGTH_PPHR 1 /* primary phrase separator */ - - -/* subobject : AccPhrUnit - * shortcut : acph - * context size : one phrase, max. 30 non-PUNC items, for non-processed items - * one item if internal input empty - */ - -/** - * @addtogroup picoacph - * - * Pico Accentuation and Phrasing \n - * - internal buffers: - - - headx : array for extended item heads of fixed size (head plus - index for content, plus two fields for boundary strength/type) - - cbuf : buffer for item contents (referenced by index in - headx). - - 0. bottom up filling of items in headx and cbuf - - 1. phrasing (right-to-left): - - e.g. from WP WP WP WP WP PUNC WP WP PUNC WP WP WP PUNC FLUSH \n - e.g. to BSBEG WP WP WP BPHR3 WP WP BPHR1 WP WP BSEND BSBEG WP WP WP BSEND BTERM \n - |1 |2 |3 |4 \n - - 2-level bound state: The internal buffer contains one primary phrase (sometimes forced, if buffer - allmost full), with the trailing PUNCT item included (last item).\n - If the trailing PUNC is a a primary phrase separator, the - item is not output, but instead, the bound state is set to PPHR, so that the correct BOUND can - be output at the start of the next primary phrase.\n - Otherwise, - the item is converted to the corresponding BOUND and output. the bound state is set to SSEP, - so that a BOUND of type SBEG is output at the start of the next primary phrase. - - trailing PUNC item bound states \n - SSEP PPHR \n - PUNC(SENTEND, X) B(B,X)>SSEP B(P1,X)>SSEP (X = T | Q | E) \n - PUNC(FLUSH, T) B(B,T)>SSEP* B(P1,T)>SSEP \n - PUNC(PHRASEEND, P) B(B,P)>PPHR B(P1,P)>PPHR \n - PUNC(PHRASEEND, FORC) B(B,P)>PPHR B(P1,P)>PPHR \n - - If more than one sentence separators follow each other (e.g. SEND-FLUSH, SEND-SEND) then - all but the first will be treated as an (empty) phrase containing just this item. - If this (single) item is a flush, creation of SBEG is suppressed. - - - - dtphr phrasing tree ("subphrasing") - determines - - BOUND_PHR2 - - BOUND_PHR3 - - boundary strenghts are determined for every word (except the - first one) from right-to-left. The boundary types mark the phrase - type of the phrase following the boundary. - - number of items actually changed (new BOUND items added): because - of fixed size without content, two fields are contained in headx - to indicate if a BOUND needs to be added to the LEFT of the item. - -> headx further extended with boundary strength and type info to - indicate that to the left of the headx ele a BOUND needs to be - inserted when outputting. - - 2. accentuation: - - number of items unchanged, content unchanged, only head info changes - -> changed in place in headx -*/ - - -typedef struct { - picodata_itemhead_t head; - picoos_uint16 cind; - picoos_uint8 boundstrength; /* bstrength to the left, 0 if not set */ - picoos_uint8 boundtype; /* btype for following phrase, 0 if not set */ -} picoacph_headx_t; - - -typedef struct acph_subobj { - picoos_uint8 procState; /* for next processing step decision */ - picoos_uint8 boundStrengthState; /* boundary strength state */ - - picoos_uint8 inspaceok; /* flag: headx/cbuf has space for an item */ - picoos_uint8 needsmoreitems; /* flag: need more items */ - - picoos_uint8 tmpbuf[PICODATA_MAX_ITEMSIZE]; /* tmp. location for an item */ - - picoacph_headx_t headx[PICOACPH_MAXNR_HEADX]; - picoos_uint16 headxBottom; /* bottom */ - picoos_uint16 headxLen; /* length, 0 if empty */ - - picoos_uint8 cbuf[PICOACPH_MAXSIZE_CBUF]; - picoos_uint16 cbufBufSize; /* actually allocated size */ - picoos_uint16 cbufLen; /* length, 0 if empty */ - - /* tab knowledge base */ - picoktab_Phones tabphones; - - /* dtphr knowledge base */ - picokdt_DtPHR dtphr; - - /* dtacc knowledge base */ - picokdt_DtACC dtacc; -} acph_subobj_t; - - -static pico_status_t acphInitialize(register picodata_ProcessingUnit this) { - acph_subobj_t * acph; - picoos_uint16 i; - - PICODBG_DEBUG(("calling")); - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(this->common->em, - PICO_ERR_NULLPTR_ACCESS, NULL, NULL); - } - acph = (acph_subobj_t *) this->subObj; - acph->procState = SA_STEPSTATE_COLLECT; - acph->boundStrengthState = SA_BOUNDSTRENGTH_SSEP; - - acph->inspaceok = TRUE; - acph->needsmoreitems = TRUE; - - acph->headxBottom = 0; - acph->headxLen = 0; - acph->cbufBufSize = PICOACPH_MAXSIZE_CBUF; - acph->cbufLen = 0; - - /* init headx, cbuf */ - for (i = 0; i < PICOACPH_MAXNR_HEADX; i++){ - acph->headx[i].head.type = 0; - acph->headx[i].head.info1 = 0; - acph->headx[i].head.info2 = 0; - acph->headx[i].head.len = 0; - acph->headx[i].cind = 0; - acph->headx[i].boundstrength = 0; - acph->headx[i].boundtype = 0; - } - for (i = 0; i < PICOACPH_MAXSIZE_CBUF; i++) { - acph->cbuf[i] = 0; - } - - /* kb tabphones */ - acph->tabphones = - picoktab_getPhones(this->voice->kbArray[PICOKNOW_KBID_TAB_PHONES]); - if (acph->tabphones == NULL) { - return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - PICODBG_DEBUG(("got tabphones")); - -#ifdef PICO_DEBUG_1 - { - picoos_uint16 itmp; - for (itmp = 0; itmp < 256; itmp++) { - if (picoktab_hasVowelProp(acph->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones hasVowel: %d", itmp)); - } - if (picoktab_hasDiphthProp(acph->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones hasDiphth: %d", itmp)); - } - if (picoktab_hasGlottProp(acph->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones hasGlott: %d", itmp)); - } - if (picoktab_hasNonsyllvowelProp(acph->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones hasNonsyllvowel: %d", itmp)); - } - if (picoktab_hasSyllconsProp(acph->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones hasSyllcons: %d", itmp)); - } - - if (picoktab_isPrimstress(acph->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones isPrimstress: %d", itmp)); - } - if (picoktab_isSecstress(acph->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones isSecstress: %d", itmp)); - } - if (picoktab_isSyllbound(acph->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones isSyllbound: %d", itmp)); - } - if (picoktab_isPause(acph->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones isPause: %d", itmp)); - } - } - - PICODBG_DEBUG(("tabphones primstressID: %d", - picoktab_getPrimstressID(acph->tabphones))); - PICODBG_DEBUG(("tabphones secstressID: %d", - picoktab_getSecstressID(acph->tabphones))); - PICODBG_DEBUG(("tabphones syllboundID: %d", - picoktab_getSyllboundID(acph->tabphones))); - PICODBG_DEBUG(("tabphones pauseID: %d", - picoktab_getPauseID(acph->tabphones))); - } -#endif - - - /* kb dtphr */ - acph->dtphr = picokdt_getDtPHR(this->voice->kbArray[PICOKNOW_KBID_DT_PHR]); - if (acph->dtphr == NULL) { - return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - PICODBG_DEBUG(("got dtphr")); - - /* kb dtacc */ - acph->dtacc = picokdt_getDtACC(this->voice->kbArray[PICOKNOW_KBID_DT_ACC]); - if (acph->dtacc == NULL) { - return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - PICODBG_DEBUG(("got dtacc")); - - return PICO_OK; -} - -static picodata_step_result_t acphStep(register picodata_ProcessingUnit this, - picoos_int16 mode, - picoos_uint16 *numBytesOutput); - -static pico_status_t acphTerminate(register picodata_ProcessingUnit this) -{ - return PICO_OK; -} - -static pico_status_t acphSubObjDeallocate(register picodata_ProcessingUnit this, - picoos_MemoryManager mm) { - mm = mm; /* avoid warning "var not used in this function"*/ - if (NULL != this) { - picoos_deallocate(this->common->mm, (void *) &this->subObj); - } - return PICO_OK; -} - - -picodata_ProcessingUnit picoacph_newAccPhrUnit(picoos_MemoryManager mm, - picoos_Common common, - picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, - picorsrc_Voice voice) { - picodata_ProcessingUnit this; - - this = picodata_newProcessingUnit(mm, common, cbIn, cbOut, voice); - if (this == NULL) { - return NULL; - } - - this->initialize = acphInitialize; - PICODBG_DEBUG(("set this->step to acphStep")); - this->step = acphStep; - this->terminate = acphTerminate; - this->subDeallocate = acphSubObjDeallocate; - this->subObj = picoos_allocate(mm, sizeof(acph_subobj_t)); - if (this->subObj == NULL) { - picoos_deallocate(mm, (void *)&this); - picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); - return NULL; - } - - acphInitialize(this); - return this; -} - - -/* ***********************************************************************/ -/* PROCESS_PHR/ACC support functions */ -/* ***********************************************************************/ - - -static picoos_uint8 acphGetNrSylls(register picodata_ProcessingUnit this, - register acph_subobj_t *acph, - const picoos_uint16 ind) { - picoos_uint8 i; - picoos_uint8 ch; - picoos_uint8 count; - - count = 1; - for (i = 0; i < acph->headx[ind].head.len; i++) { - ch = acph->cbuf[acph->headx[ind].cind + i]; - if (picoktab_isSyllbound(acph->tabphones, ch)) { - count++; - } - } - return count; -} - - -/* ***********************************************************************/ -/* PROCESS_PHR functions */ -/* ***********************************************************************/ - - -/* find next POS to the left of 'ind' and return its POS and index */ -static picoos_uint8 acphPhrItemSeqGetPosLeft(register picodata_ProcessingUnit this, - register acph_subobj_t *acph, - const picoos_uint16 ind, - picoos_uint16 *leftind) { - picoos_uint8 val; - picoos_int32 i; - - val = PICOKDT_EPSILON; - for (i = ind - 1; ((val == PICOKDT_EPSILON) && (i >= 0)); i--) { - if ((acph->headx[i].head.type == PICODATA_ITEM_WORDPHON)) { - val = acph->headx[i].head.info1; - } - } - *leftind = i + 1; - return val; -} - - -/* right-to-left, for each WORDPHON do phr */ -static pico_status_t acphSubPhrasing(register picodata_ProcessingUnit this, - register acph_subobj_t *acph) { - picokdt_classify_result_t dtres; - picoos_uint8 valbuf[5]; - picoos_uint16 nrwordspre; - picoos_uint16 nrwordsfol; - picoos_uint16 nrsyllsfol; - picoos_uint16 lastprev2; /* last index of POS(es) found to the left */ - picoos_uint8 curpos; /* POS(es) of current word */ - picoos_uint16 upbound; /* index of last WORDPHON item (with POS) */ - picoos_uint8 okay; - picoos_uint8 nosubphrases; - picoos_int32 i; - - /* set initial values */ - okay = TRUE; - nosubphrases = TRUE; - curpos = PICOKDT_EPSILON; /* needs to be in 2^8 */ - - /* set upbound to last WORDPHON, don't worry about first one */ - upbound = acph->headxLen - 1; - while ((upbound > 0) && - (acph->headx[upbound].head.type != PICODATA_ITEM_WORDPHON)) { - upbound--; - } - - /* zero or one WORDPHON, no subphrasing needed, but handling of - BOUND strength state is needed */ - if (upbound <= 0) { - /* phrase not containing more than one WORDPHON */ - PICODBG_DEBUG(("less than two WORDPHON in phrase -> no subphrasing")); - } - - lastprev2 = upbound; - - /* set initial nr pre/fol words/sylls, upbound is ind of last WORDPHON */ - nrwordsfol = 0; - nrsyllsfol = 0; - nrwordspre = 0; - for (i = 0; i < upbound; i++) { - if (acph->headx[i].head.type == PICODATA_ITEM_WORDPHON) { - nrwordspre++; - } - } - - nrwordspre++; /* because we later have a decrement before being used */ - - - /* set POS of current word in valbuf[1], will be shifted right afterwards */ - valbuf[1] = acph->headx[upbound].head.info1; - /* find first POS to the left and set valbuf[0] */ - valbuf[0] = acphPhrItemSeqGetPosLeft(this, acph, lastprev2, &lastprev2); - for (i = 2; i < 5; i++) { - valbuf[i] = PICOKDT_EPSILON; - } - - PICODBG_TRACE(("headxLen: %d", acph->headxLen)); - - /* at least two WORDPHON items */ - /* process from right-to-left all items in headx, except for 1st WORDPHON */ - for (i = upbound; (i > 0) && (nrwordspre > 1); i--) { - okay = TRUE; - - PICODBG_TRACE(("iter: %d, type: %c", i, acph->headx[i].head.type)); - - /* if not (WORDPHON) */ - if ((acph->headx[i].head.type != PICODATA_ITEM_WORDPHON)) { - continue; - } - - PICODBG_TRACE(("iter: %d, curpos: %d", i, acph->headx[i].head.info1)); - - /* get and set POS of current item, must be WORDPHON */ - curpos = acph->headx[i].head.info1; - - /* no continue so far => at [i] we have a WORDPHON item */ - /* shift all POS elements one position to the right */ - valbuf[4] = valbuf[3]; - valbuf[3] = valbuf[2]; - valbuf[2] = valbuf[1]; - valbuf[1] = valbuf[0]; - /* find next POS to the left and set valbuf[0] */ - valbuf[0] = acphPhrItemSeqGetPosLeft(this, acph, lastprev2, &lastprev2); - - /* better check double than never */ - if (curpos != valbuf[2]) { - PICODBG_WARN(("syncing POS")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, - NULL, NULL); - valbuf[2] = curpos; - } - - nrwordsfol++; - nrsyllsfol += acphGetNrSylls(this, acph, i); - nrwordspre--; - - PICODBG_TRACE(("%d: [%d,%d|%d|%d,%d|%d,%d,%d]", - i, valbuf[0], valbuf[1], valbuf[2], valbuf[3], - valbuf[4], nrwordspre, nrwordsfol, nrsyllsfol)); - - /* no continue so far => subphrasing needed */ - /* construct input vector, which is set in dtphr */ - if (!picokdt_dtPHRconstructInVec(acph->dtphr, valbuf[0], valbuf[1], - valbuf[2], valbuf[3], valbuf[4], - nrwordspre, nrwordsfol, nrsyllsfol)) { - /* error constructing invec */ - PICODBG_WARN(("problem with invec")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, - NULL, NULL); - okay = FALSE; - } - /* classify */ - if (okay && (!picokdt_dtPHRclassify(acph->dtphr))) { - /* error doing classification */ - PICODBG_WARN(("problem classifying")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, - NULL, NULL); - okay = FALSE; - } - /* decompose */ - if (okay && (!picokdt_dtPHRdecomposeOutClass(acph->dtphr, &dtres))) { - /* error decomposing */ - PICODBG_WARN(("problem decomposing")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_OUTVECTOR, - NULL, NULL); - okay = FALSE; - } - - if (okay && dtres.set) { - PICODBG_DEBUG(("%d - inpos: %d, out: %d", i,valbuf[2],dtres.class)); - } else { - PICODBG_WARN(("problem determining subphrase boundary strength")); - dtres.class = PICODATA_ITEMINFO1_ERR; - } - - if (dtres.class > 255) { - PICODBG_WARN(("dt class outside valid range, setting to PHR0")); - dtres.class = PICODATA_ITEMINFO1_BOUND_PHR0; - } - acph->headx[i].boundstrength = (picoos_uint8)dtres.class; - if ((dtres.class == PICODATA_ITEMINFO1_BOUND_PHR2) || - (dtres.class == PICODATA_ITEMINFO1_BOUND_PHR3)) { - if (nosubphrases) { - /* it's the last secondary phrase in the primary phrase */ - /* add type info */ - switch (acph->headx[acph->headxLen - 1].head.info2) { - case PICODATA_ITEMINFO2_PUNC_SENT_T: - acph->headx[i].boundtype = - PICODATA_ITEMINFO2_BOUNDTYPE_T; - break; - case PICODATA_ITEMINFO2_PUNC_SENT_Q: - acph->headx[i].boundtype = - PICODATA_ITEMINFO2_BOUNDTYPE_Q; - break; - case PICODATA_ITEMINFO2_PUNC_SENT_E: - acph->headx[i].boundtype = - PICODATA_ITEMINFO2_BOUNDTYPE_E; - break; - case PICODATA_ITEMINFO2_PUNC_PHRASE: - case PICODATA_ITEMINFO2_PUNC_PHRASE_FORCED: - acph->headx[i].boundtype = - PICODATA_ITEMINFO2_BOUNDTYPE_P; - break; - default: - PICODBG_WARN(("invalid boundary type, not set")); - break; - } - nosubphrases = FALSE; - - } else { - acph->headx[i].boundtype = - PICODATA_ITEMINFO2_BOUNDTYPE_P; - } - /* reset nr following words and sylls counters */ - nrwordsfol = 0; - nrsyllsfol = 0; - } - } - - /* process first item, add bound-info */ - switch (acph->boundStrengthState) { - case SA_BOUNDSTRENGTH_SSEP: - acph->headx[0].boundstrength = - PICODATA_ITEMINFO1_BOUND_SBEG; - break; - case SA_BOUNDSTRENGTH_PPHR: - acph->headx[0].boundstrength = - PICODATA_ITEMINFO1_BOUND_PHR1; - break; - default: - PICODBG_WARN(("invalid boundary strength, not set")); - break; - } - - /* set boundary strength state */ - switch (acph->headx[acph->headxLen - 1].head.info1) { - case PICODATA_ITEMINFO1_PUNC_SENTEND: - case PICODATA_ITEMINFO1_PUNC_FLUSH: - acph->boundStrengthState = SA_BOUNDSTRENGTH_SSEP; - break; - case PICODATA_ITEMINFO1_PUNC_PHRASEEND: - acph->boundStrengthState = SA_BOUNDSTRENGTH_PPHR; - break; - default: - PICODBG_WARN(("invalid boundary strength state, not changed")); - break; - } - - if (nosubphrases) { - /* process first item, add type info */ - switch (acph->headx[acph->headxLen - 1].head.info2) { - case PICODATA_ITEMINFO2_PUNC_SENT_T: - acph->headx[0].boundtype = - PICODATA_ITEMINFO2_BOUNDTYPE_T; - break; - case PICODATA_ITEMINFO2_PUNC_SENT_Q: - acph->headx[0].boundtype = - PICODATA_ITEMINFO2_BOUNDTYPE_Q; - break; - case PICODATA_ITEMINFO2_PUNC_SENT_E: - acph->headx[0].boundtype = - PICODATA_ITEMINFO2_BOUNDTYPE_E; - break; - case PICODATA_ITEMINFO2_PUNC_PHRASE: - case PICODATA_ITEMINFO2_PUNC_PHRASE_FORCED: - acph->headx[0].boundtype = - PICODATA_ITEMINFO2_BOUNDTYPE_P; - break; - default: - PICODBG_WARN(("invalid boundary type, not set")); - break; - } - } else { - acph->headx[0].boundtype = - PICODATA_ITEMINFO2_BOUNDTYPE_P; - } - - return PICO_OK; -} - - -/* ***********************************************************************/ -/* PROCESS_ACC functions */ -/* ***********************************************************************/ - -/* find next POS to the left of 'ind' and return its POS and index */ -static picoos_uint8 acphAccItemSeqGetPosLeft(register picodata_ProcessingUnit this, - register acph_subobj_t *acph, - const picoos_uint16 ind, - picoos_uint16 *leftind) { - picoos_uint8 val; - picoos_int32 i; - - val = PICOKDT_EPSILON; - for (i = ind - 1; ((val == PICOKDT_EPSILON) && (i >= 0)); i--) { - if ((acph->headx[i].head.type == PICODATA_ITEM_WORDPHON)) { - val = acph->headx[i].head.info1; - } - } - *leftind = i + 1; - return val; -} - - -/* s1: nr sylls in word before the first primary stressed syll, - s2: nr sylls in word after (but excluding) the first primary stressed syll */ -static picoos_uint8 acphAccNrSyllParts(register picodata_ProcessingUnit this, - register acph_subobj_t *acph, - const picoos_uint16 ind, - picoos_uint8 *s1, - picoos_uint8 *s2) { - picoos_uint16 pind; - picoos_uint16 pend; /* phone string start+len */ - picoos_uint8 afterprim; - - /* check ind is in valid range */ - if (ind >= acph->headxLen) { - return FALSE; - } - - *s1 = 0; - *s2 = 0; - afterprim = FALSE; - pend = acph->headx[ind].cind + acph->headx[ind].head.len; - for (pind = acph->headx[ind].cind; pind < pend; pind++) { - if (picoktab_isPrimstress(acph->tabphones, acph->cbuf[pind])) { - afterprim = TRUE; - } else if (picoktab_isSyllbound(acph->tabphones, acph->cbuf[pind])) { - if (afterprim) { - (*s2)++; - } else { - (*s1)++; - } - } - } - if (afterprim) { - (*s2)++; - } else { - (*s1)++; - } - - /* exclude the stressed syllable */ - if ((*s2) > 0) { - (*s2)--; - } - /* handle the case when there is no primstress */ - if (!afterprim) { - (*s2) = (*s1); - } - return TRUE; -} - - -static picoos_uint8 acphAccGetNrsRight(register picodata_ProcessingUnit this, - register acph_subobj_t *acph, - const picoos_uint16 ind, - picoos_uint16 *nrwordsfol, - picoos_uint16 *nrsyllsfol, - picoos_uint16 *footwordsfol, - picoos_uint16 *footsyllsfol) { - picoos_uint16 i; - picoos_uint8 s1; - picoos_uint8 s2; - - if (!acphAccNrSyllParts(this, acph, ind, &s1, &s2)) { - return FALSE; - } - - *nrwordsfol = 0; - *nrsyllsfol = s2; - i = ind + 1; - while ((i < acph->headxLen) && - (acph->headx[i].boundstrength == PICODATA_ITEMINFO1_BOUND_PHR0)) { - if (acph->headx[i].head.type == PICODATA_ITEM_WORDPHON) { - (*nrwordsfol)++; - *nrsyllsfol += acphGetNrSylls(this, acph, i); - } - i++; - } - - *footwordsfol = 0; - *footsyllsfol = s2; - i = ind + 1; - while ((i < acph->headxLen) && - (acph->headx[i].head.info2 != PICODATA_ACC1)) { - if (acph->headx[i].head.type == PICODATA_ITEM_WORDPHON) { - (*footwordsfol)++; - *footsyllsfol += acphGetNrSylls(this, acph, i); - } - i++; - } - if ((i < acph->headxLen) && (acph->headx[i].head.info2 == PICODATA_ACC1)) { - if (!acphAccNrSyllParts(this, acph, i, &s1, &s2)) { - return FALSE; - } - *footsyllsfol += s1; - } - return TRUE; -} - - -static picoos_uint8 acphAccGetNrsLeft(register picodata_ProcessingUnit this, - register acph_subobj_t *acph, - const picoos_uint16 ind, - picoos_uint16 *nrwordspre, - picoos_uint16 *nrsyllspre) { - picoos_int32 i; - picoos_uint8 s1; - picoos_uint8 s2; - - if (!acphAccNrSyllParts(this, acph, ind, &s1, &s2)) { - return FALSE; - } - - *nrwordspre = 0; - *nrsyllspre = s1; - i = ind - 1; - while ((i >= 0) && - (acph->headx[i].boundstrength == PICODATA_ITEMINFO1_BOUND_PHR0)) { - if (acph->headx[i].head.type == PICODATA_ITEM_WORDPHON) { - (*nrwordspre)++; - *nrsyllspre += acphGetNrSylls(this, acph, i); - } - i--; - } - - if ((acph->headx[i].boundstrength != PICODATA_ITEMINFO1_BOUND_PHR0) && - (acph->headx[i].head.type == PICODATA_ITEM_WORDPHON)) { - (*nrwordspre)++; - *nrsyllspre += acphGetNrSylls(this, acph, i); - } - return TRUE; -} - - -/* return TRUE if wordphon contains no stress, FALSE otherwise */ -static picoos_uint8 acphIsWordWithoutStress(register picodata_ProcessingUnit this, - register acph_subobj_t *acph, - const picoos_uint16 ind) { - picoos_uint8 i; - picoos_uint16 pos; - - pos = acph->headx[ind].cind; - for (i = 0; i < acph->headx[ind].head.len; i++) { - if (picoktab_isPrimstress(acph->tabphones, acph->cbuf[pos + i]) || - picoktab_isSecstress(acph->tabphones, acph->cbuf[pos + i])) { - return FALSE; - } - } - return TRUE; -} - - -/* right-to-left, for each WORDPHON do acc */ -static pico_status_t acphAccentuation(register picodata_ProcessingUnit this, - register acph_subobj_t *acph) { - picokdt_classify_result_t dtres; - picoos_uint8 valbuf[5]; - picoos_uint16 hist1; - picoos_uint16 hist2; - picoos_uint16 nrwordspre; - picoos_uint16 nrsyllspre; - picoos_uint16 nrwordsfol; - picoos_uint16 nrsyllsfol; - picoos_uint16 footwordsfol; - picoos_uint16 footsyllsfol; - picoos_uint16 lastprev2; /* last index of POS(es) found to the left */ - picoos_uint8 curpos; /* POS(es) of current word */ - picoos_uint16 prevout; - picoos_uint8 okay; - picoos_int32 upbound; /* index of last WORDPHON item (with POS) */ - picoos_uint16 i; - - /* set initial values */ - okay = TRUE; - curpos = PICOKDT_EPSILON; /* needs to be < 2^8 */ - - /* set upbound to last WORDPHON */ - upbound = acph->headxLen - 1; - while ((upbound >= 0) && - (acph->headx[upbound].head.type != PICODATA_ITEM_WORDPHON)) { - upbound--; - } - - if (upbound < 0) { - /* phrase containing zero WORDPHON */ - PICODBG_DEBUG(("no WORDPHON in phrase -> no accentuation")); - return PICO_OK; - } - - lastprev2 = upbound; - - /* set initial history values */ - prevout = PICOKDT_HISTORY_ZERO; - hist1 = PICOKDT_HISTORY_ZERO; - hist2 = PICOKDT_HISTORY_ZERO; - - /* set initial nr pre/fol words/sylls, upbound is ind of last WORDPHON */ - nrwordsfol = 0; - nrsyllsfol = 0; - footwordsfol = 0; - footsyllsfol = 0; - nrwordspre = 0; - nrsyllspre = 0; - - /* set POS of current word in valbuf[1], will be shifted right afterwards */ - valbuf[1] = acph->headx[upbound].head.info1; - /* find first POS to the left and set valbuf[0] */ - valbuf[0] = acphAccItemSeqGetPosLeft(this, acph, lastprev2, &lastprev2); - for (i = 2; i < 5; i++) { - valbuf[i] = PICOKDT_EPSILON; - } - - PICODBG_TRACE(("headxLen: %d", acph->headxLen)); - - /* process from right-to-left all items in headx */ - for (i = upbound+1; i > 0; ) { - i--; - - okay = TRUE; - - PICODBG_TRACE(("iter: %d, type: %c", i, acph->headx[i].head.type)); - - /* if not (WORDPHON) */ - if ((acph->headx[i].head.type != PICODATA_ITEM_WORDPHON)) { - continue; - } - - PICODBG_TRACE(("iter: %d, curpos: %d", i, acph->headx[i].head.info1)); - - /* get and set POS of current item, must be WORDPHON */ - curpos = acph->headx[i].head.info1; - - /* no continue so far => at [i] we have a WORDPHON item */ - /* shift all POS elements one position to the right */ - valbuf[4] = valbuf[3]; - valbuf[3] = valbuf[2]; - valbuf[2] = valbuf[1]; - valbuf[1] = valbuf[0]; - /* find next POS to the left and set valbuf[0] */ - valbuf[0] = acphAccItemSeqGetPosLeft(this, acph, lastprev2, &lastprev2); - - /* better check double than never */ - if (curpos != valbuf[2]) { - PICODBG_WARN(("syncing POS")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, - NULL, NULL); - valbuf[2] = curpos; - } - - /* set history values */ - hist2 = hist1; - hist1 = prevout; - - /* ************************************************************ */ - /* many speedups possible by avoiding double calc of attribtues */ - /* ************************************************************ */ - - /* get distances */ - if ((!acphAccGetNrsRight(this, acph, i, &nrwordsfol, &nrsyllsfol, - &footwordsfol, &footsyllsfol)) || - (!acphAccGetNrsLeft(this, acph, i, &nrwordspre, &nrsyllspre))) { - PICODBG_WARN(("problem setting distances in invec")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, - NULL, NULL); - okay = FALSE; - } - - PICODBG_TRACE(("%d: [%d,%d,%d,%d,%d|%d,%d|%d,%d,%d,%d|%d,%d]", i, - valbuf[0], valbuf[1], valbuf[2], valbuf[3], valbuf[4], - hist1, hist2, nrwordspre, nrsyllspre, - nrwordsfol, nrsyllsfol, footwordsfol, footsyllsfol)); - - /* no continue so far => accentuation needed */ - /* construct input vector, which is set in dtacc */ - if (!picokdt_dtACCconstructInVec(acph->dtacc, valbuf[0], valbuf[1], - valbuf[2], valbuf[3], valbuf[4], - hist1, hist2, nrwordspre, nrsyllspre, - nrwordsfol, nrsyllsfol, footwordsfol, - footsyllsfol)) { - /* error constructing invec */ - PICODBG_WARN(("problem with invec")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, - NULL, NULL); - okay = FALSE; - } - /* classify */ - if (okay && (!picokdt_dtACCclassify(acph->dtacc, &prevout))) { - /* error doing classification */ - PICODBG_WARN(("problem classifying")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, - NULL, NULL); - okay = FALSE; - } - /* decompose */ - if (okay && (!picokdt_dtACCdecomposeOutClass(acph->dtacc, &dtres))) { - /* error decomposing */ - PICODBG_WARN(("problem decomposing")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_OUTVECTOR, - NULL, NULL); - okay = FALSE; - } - - if (dtres.class > 255) { - PICODBG_WARN(("dt class outside valid range, setting to ACC0")); - dtres.class = PICODATA_ACC0; - } - - if (okay && dtres.set) { - PICODBG_DEBUG(("%d - inpos: %d, out: %d", i,valbuf[2],dtres.class)); - if (acphIsWordWithoutStress(this, acph, i)) { - if (dtres.class != PICODATA_ACC0) { - acph->headx[i].head.info2 = PICODATA_ACC3; - } else { - acph->headx[i].head.info2 = (picoos_uint8)dtres.class; - } - } else { - acph->headx[i].head.info2 = (picoos_uint8)dtres.class; - } - PICODBG_DEBUG(("%d - after-nostress-corr: %d", - i, acph->headx[i].head.info2)); - } else { - PICODBG_WARN(("problem determining accentuation level")); - dtres.class = PICODATA_ITEMINFO1_ERR; - } - } - return PICO_OK; -} - - - -/* ***********************************************************************/ -/* acphStep support functions */ -/* ***********************************************************************/ - -static picoos_uint8 acphPutBoundItem(register picodata_ProcessingUnit this, - register acph_subobj_t *acph, - const picoos_uint8 strength, - const picoos_uint8 type, - picoos_uint8 *dopuoutfull, - picoos_uint16 *numBytesOutput) { - pico_status_t rv = PICO_OK; - picoos_uint16 blen = 0; - picodata_itemhead_t tmphead; - - *dopuoutfull = FALSE; - - /* construct BOUND item in tmpbuf and put item */ - tmphead.type = PICODATA_ITEM_BOUND; - tmphead.info1 = strength; - tmphead.info2 = type; - tmphead.len = 0; - rv = picodata_put_itemparts(&tmphead, NULL, 0, acph->tmpbuf, - PICODATA_MAX_ITEMSIZE, &blen); - if (rv != PICO_OK) { - PICODBG_ERROR(("problem creating BOUND item")); - picoos_emRaiseException(this->common->em, rv, NULL, NULL); - return FALSE; - } - /* put constructed item to ext. charbuf */ - rv = picodata_cbPutItem(this->cbOut, acph->tmpbuf, blen, &blen); - - *numBytesOutput += blen; - if (rv == PICO_EXC_BUF_OVERFLOW) { - PICODBG_DEBUG(("overflow in cb output buffer")); - *dopuoutfull = TRUE; /* ie. do PU_OUT_FULL later */ - return FALSE; - } else if (rv != PICO_OK) { - PICODBG_ERROR(("problem putting BOUND item")); - picoos_emRaiseException(this->common->em, rv, NULL, NULL); - return FALSE; - } - - PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], - (picoos_uint8 *)"acph: ", acph->tmpbuf, blen); - - return TRUE; -} - - - -/* ***********************************************************************/ -/* acphStep function */ -/* ***********************************************************************/ - -/* -complete phrase processed in one step, if not fast enough -> rework - -init, collect into internal buffer, process, and then feed to -output buffer - -init state: INIT ext ext -state trans: in hc1 hc2 out - -INIT | putItem = 0 0 +1 | BUSY -> COLL (put B-SBEG item, - set do-init to false) - - inspace-ok-hc1 - needs-more-items-(phrase-or-flush) -COLL1 |getItems -n +n 0 1 | ATOMIC -> PPOSD (got items, - if flush set do-init) -COLL2 |getItems -n +n 1 0 | ATOMIC -> PPOSD (got items, forced) -COLL3 |getItems -n +n 1 1 | IDLE (got items, need more) -COLL4 |getItems = = 1 1 | IDLE (got no items) - -PPOSD | posd = ~n~n | BUSY -> PWP (posd done) -PWP | lex/g2p = ~n-n 0+n | BUSY -> PPHR (lex/g2p done) -PPHR | phr = -n 0 +m=n | BUSY -> PACC (phr done, m>=n) -PACC | acc = 0 0 ~m=n | BUSY -> FEED (acc done) - - doinit-flag -FEED | putItems 0 0 0 -m-n +m 0 | BUSY -> COLL (put items) -FEED | putItems 0 0 0 -m-n +m 1 | BUSY -> INIT (put items) -FEED | putItems 0 0 0 -d-d +d | OUT_FULL (put some items) -*/ - -static picodata_step_result_t acphStep(register picodata_ProcessingUnit this, - picoos_int16 mode, - picoos_uint16 *numBytesOutput) { - register acph_subobj_t *acph; - pico_status_t rv = PICO_OK; - pico_status_t rvP = PICO_OK; - picoos_uint16 blen = 0; - picoos_uint16 clen = 0; - picoos_uint16 i; - - - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - acph = (acph_subobj_t *) this->subObj; - mode = mode; /* avoid warning "var not used in this function"*/ - *numBytesOutput = 0; - while (1) { /* exit via return */ - PICODBG_DEBUG(("doing state %i, hLen|c1Len: %d|%d", - acph->procState, acph->headxLen, acph->cbufLen)); - - switch (acph->procState) { - - /* *********************************************************/ - /* collect state: get item(s) from charBuf and store in - * internal buffers, need a complete punctuation-phrase - */ - case SA_STEPSTATE_COLLECT: - - while (acph->inspaceok && acph->needsmoreitems && (PICO_OK == - (rv = picodata_cbGetItem(this->cbIn, acph->tmpbuf, - PICODATA_MAX_ITEMSIZE, &blen)))) { - rvP = picodata_get_itemparts(acph->tmpbuf, - PICODATA_MAX_ITEMSIZE, &(acph->headx[acph->headxLen].head), - &(acph->cbuf[acph->cbufLen]), acph->cbufBufSize - - acph->cbufLen, &clen); - if (rvP != PICO_OK) { - PICODBG_ERROR(("problem getting item parts")); - picoos_emRaiseException(this->common->em, rvP, - NULL, NULL); - return PICODATA_PU_ERROR; - } - - /* if CMD(...FLUSH...) -> PUNC(...FLUSH...), - construct PUNC-FLUSH item in headx */ - if ((acph->headx[acph->headxLen].head.type - == PICODATA_ITEM_CMD) - && (acph->headx[acph->headxLen].head.info1 - == PICODATA_ITEMINFO1_CMD_FLUSH)) { - acph->headx[acph->headxLen].head.type - = PICODATA_ITEM_PUNC; - acph->headx[acph->headxLen].head.info1 - = PICODATA_ITEMINFO1_PUNC_FLUSH; - acph->headx[acph->headxLen].head.info2 - = PICODATA_ITEMINFO2_PUNC_SENT_T; - acph->headx[acph->headxLen].head.len = 0; - } - - /* check/set needsmoreitems */ - if (acph->headx[acph->headxLen].head.type - == PICODATA_ITEM_PUNC) { - acph->needsmoreitems = FALSE; - } - - /* check/set inspaceok, keep spare slot for forcing */ - if ((acph->headxLen >= (PICOACPH_MAXNR_HEADX - 2)) - || ((acph->cbufBufSize - acph->cbufLen) - < PICODATA_MAX_ITEMSIZE)) { - acph->inspaceok = FALSE; - } - - if (clen > 0) { - acph->headx[acph->headxLen].cind = acph->cbufLen; - acph->cbufLen += clen; - } else { - acph->headx[acph->headxLen].cind = 0; - } - acph->headxLen++; - } - - if (!acph->needsmoreitems) { - /* 1, phrase buffered */ - acph->procState = SA_STEPSTATE_PROCESS_PHR; - return PICODATA_PU_ATOMIC; - } else if (!acph->inspaceok) { - /* 2, forced phrase end */ - /* at least one slot is still free, use it to - force a trailing PUNC item */ - acph->headx[acph->headxLen].head.type = PICODATA_ITEM_PUNC; - acph->headx[acph->headxLen].head.info1 = - PICODATA_ITEMINFO1_PUNC_PHRASEEND; - acph->headx[acph->headxLen].head.info2 = - PICODATA_ITEMINFO2_PUNC_PHRASE_FORCED; - acph->headx[acph->headxLen].head.len = 0; - acph->needsmoreitems = FALSE; /* not really needed for now */ - acph->headxLen++; - PICODBG_WARN(("forcing phrase end, added PUNC_PHRASEEND")); - picoos_emRaiseWarning(this->common->em, - PICO_WARN_FALLBACK, NULL, - (picoos_char *)"forced phrase end"); - acph->procState = SA_STEPSTATE_PROCESS_PHR; - return PICODATA_PU_ATOMIC; - } else if (rv == PICO_EOF) { - /* 3, 4 */ - return PICODATA_PU_IDLE; - } else if ((rv == PICO_EXC_BUF_UNDERFLOW) || - (rv == PICO_EXC_BUF_OVERFLOW)) { - /* error, no valid item in cb (UNDER) */ - /* or tmpbuf not large enough, not possible (OVER) */ - /* no exception raised, left for ctrl to handle */ - PICODBG_ERROR(("buffer under/overflow, rv: %d", rv)); - return PICODATA_PU_ERROR; - } else { - /* error, only possible if cbGetItem implementation - changes without this function being adapted*/ - PICODBG_ERROR(("untreated return value, rv: %d", rv)); - return PICODATA_PU_ERROR; - } - break; - - - - - /* *********************************************************/ - /* process phr state: process items in headx and modify - * headx in place - */ - case SA_STEPSTATE_PROCESS_PHR: - /* ensure there is an item in inBuf */ - if (acph->headxLen > 0) { - /* we have a phrase in headx, cbuf1 (can be - single PUNC item), do phrasing and modify headx */ - - if (PICO_OK != acphSubPhrasing(this, acph)) { - picoos_emRaiseException(this->common->em, - PICO_ERR_OTHER, NULL, NULL); - return PICODATA_PU_ERROR; - } - acph->procState = SA_STEPSTATE_PROCESS_ACC; - } else if (acph->headxLen == 0) { /* no items in inBuf */ - PICODBG_WARN(("no items in inBuf")); - acph->procState = SA_STEPSTATE_COLLECT; - return PICODATA_PU_BUSY; - } - -#if defined (PICO_DEBUG_NOTNEEDED) - if (1) { - picoos_uint8 i, j, ittype; - for (i = 0; i < acph->headxLen; i++) { - if ((acph->headx[i].boundstrength != 0) && - (acph->headx[i].boundstrength != - PICODATA_ITEMINFO1_BOUND_PHR0)) { - PICODBG_INFO(("acph-p: boundstrength '%c', " - "boundtype '%c'", - acph->headx[i].boundstrength, - acph->headx[i].boundtype)); - } - - ittype = acph->headx[i].head.type; - PICODBG_INFO_CTX(); - PICODBG_INFO_MSG(("acph-p: (")); - PICODBG_INFO_MSG(("'%c',", ittype)); - if ((32 <= acph->headx[i].head.info1) && - (acph->headx[i].head.info1 < 127) && - (ittype != PICODATA_ITEM_WORDPHON)) { - PICODBG_INFO_MSG(("'%c',",acph->headx[i].head.info1)); - } else { - PICODBG_INFO_MSG(("%3d,", acph->headx[i].head.info1)); - } - if ((32 <= acph->headx[i].head.info2) && - (acph->headx[i].head.info2 < 127)) { - PICODBG_INFO_MSG(("'%c',",acph->headx[i].head.info2)); - } else { - PICODBG_INFO_MSG(("%3d,", acph->headx[i].head.info2)); - } - PICODBG_INFO_MSG(("%3d)", acph->headx[i].head.len)); - - for (j = 0; j < acph->headx[i].head.len; j++) { - if ((ittype == PICODATA_ITEM_CMD)) { - PICODBG_INFO_MSG(("%c", - acph->cbuf[acph->headx[i].cind+j])); - } else { - PICODBG_INFO_MSG(("%4d", - acph->cbuf[acph->headx[i].cind+j])); - } - } - PICODBG_INFO_MSG(("\n")); - } - } -#endif - - break; - - - /* *********************************************************/ - /* process acc state: process items in headx and modify - * headx in place - */ - case SA_STEPSTATE_PROCESS_ACC: - /* ensure there is an item in inBuf */ - if (acph->headxLen > 0) { - /* we have a phrase in headx, cbuf (can be - single PUNC item), do accentuation and modify headx */ - if (PICO_OK != acphAccentuation(this, acph)) { - picoos_emRaiseException(this->common->em, - PICO_ERR_OTHER, NULL, NULL); - return PICODATA_PU_ERROR; - } - acph->procState = SA_STEPSTATE_FEED; - } else if (acph->headxLen == 0) { /* no items in inBuf */ - PICODBG_WARN(("no items in inBuf")); - acph->procState = SA_STEPSTATE_COLLECT; - return PICODATA_PU_BUSY; - } - break; - - - /* *********************************************************/ - /* feed state: copy item in internal outBuf to output charBuf */ - case SA_STEPSTATE_FEED: { - picoos_uint16 indupbound; - picoos_uint8 dopuoutfull; - - PICODBG_DEBUG(("put out items (bot, len): (%d, %d)", - acph->headxBottom, acph->headxLen)); - - indupbound = acph->headxBottom + acph->headxLen; - dopuoutfull = FALSE; - - if (acph->headxBottom == 0) { - /* construct first BOUND item in tmpbuf and put item */ - /* produce BOUND unless it is followed by a term/flush) */ - if (acph->headx[0].head.info1 - != PICODATA_ITEMINFO1_PUNC_FLUSH) { - if (!acphPutBoundItem(this, acph, - acph->headx[0].boundstrength, - acph->headx[0].boundtype, &dopuoutfull, - numBytesOutput)) { - if (dopuoutfull) { - PICODBG_DEBUG(("feeding overflow")); - return PICODATA_PU_OUT_FULL; - } else { - /* ERR-msg and exception done in acphPutBoundItem */ - return PICODATA_PU_ERROR; - } - } - } - } - - /* for all items in headx, cbuf */ - for (i = acph->headxBottom; i < indupbound; i++) { - - switch (acph->headx[i].head.type) { - case PICODATA_ITEM_PUNC: - /* if sentence end, put SEND bound */ - if ((acph->headx[i].head.info1 == - PICODATA_ITEMINFO1_PUNC_SENTEND) && - (i == (indupbound - 1))) { - /* construct and put BOUND item */ - if (!acphPutBoundItem(this, acph, - PICODATA_ITEMINFO1_BOUND_SEND, - PICODATA_ITEMINFO2_NA, - &dopuoutfull, numBytesOutput)) { - if (dopuoutfull) { - PICODBG_DEBUG(("feeding overflow")); - return PICODATA_PU_OUT_FULL; - } else { - /* ERR-msg and exception done - in acphPutBoundItem */ - return PICODATA_PU_ERROR; - } - } - } else if ((acph->headx[i].head.info1 == - PICODATA_ITEMINFO1_PUNC_FLUSH) && - (i == (indupbound - 1))) { - /* construct and put BOUND item */ - if (!acphPutBoundItem(this, acph, - PICODATA_ITEMINFO1_BOUND_TERM, - PICODATA_ITEMINFO2_NA, - &dopuoutfull, numBytesOutput)) { - if (dopuoutfull) { - PICODBG_DEBUG(("feeding overflow")); - return PICODATA_PU_OUT_FULL; - } else { - /* ERR-msg and exception done - in acphPutBoundItem */ - return PICODATA_PU_ERROR; - } - } - } - /* else, good-bye PUNC, not needed anymore */ - break; - default: - - /* PHR2/3 maybe existing, check and add - BOUND item now, if needed */ - if ((acph->headx[i].boundstrength == - PICODATA_ITEMINFO1_BOUND_PHR2) || - (acph->headx[i].boundstrength == - PICODATA_ITEMINFO1_BOUND_PHR3)) { - if (!acphPutBoundItem(this, acph, - acph->headx[i].boundstrength, - acph->headx[i].boundtype, - &dopuoutfull, numBytesOutput)) { - if (dopuoutfull) { - PICODBG_DEBUG(("feeding overflow")); - return PICODATA_PU_OUT_FULL; - } else { - /* ERR-msg and exception done - in acphPutBoundItem */ - return PICODATA_PU_ERROR; - } - } - } - - /* copy item unmodified */ - rv = picodata_put_itemparts(&(acph->headx[i].head), - &(acph->cbuf[acph->headx[i].cind]), - acph->headx[i].head.len, - acph->tmpbuf, PICODATA_MAX_ITEMSIZE, - &blen); - - rvP = picodata_cbPutItem(this->cbOut, acph->tmpbuf, - PICODATA_MAX_ITEMSIZE, &clen); - - *numBytesOutput += clen; - - PICODBG_DEBUG(("put item, status: %d", rvP)); - - if (rvP == PICO_OK) { - acph->headxBottom++; - acph->headxLen--; - } else if (rvP == PICO_EXC_BUF_OVERFLOW) { - /* try again next time, but PHR2/3 - bound already added if existing, - ensure it's not output a 2nd - time */ - PICODBG_DEBUG(("feeding overflow")); - acph->headx[i].boundstrength = 0; - return PICODATA_PU_OUT_FULL; - } else { - /* error, should never happen */ - PICODBG_ERROR(("untreated return value, rvP: %d", rvP)); - return PICODATA_PU_ERROR; - } - - PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], - (picoos_uint8 *)"acph: ", - acph->tmpbuf, PICODATA_MAX_ITEMSIZE); - - break; - } /*switch*/ - } /*for*/ - - /* reset headx, cbuf */ - acph->headxBottom = 0; - acph->headxLen = 0; - acph->cbufLen = 0; - for (i = 0; i < PICOACPH_MAXNR_HEADX; i++) { - acph->headx[i].boundstrength = 0; - } - - /* reset collect state support variables */ - acph->inspaceok = TRUE; - acph->needsmoreitems = TRUE; - - acph->procState = SA_STEPSTATE_COLLECT; - return PICODATA_PU_BUSY; - break; - } - - default: - break; - } /* switch */ - - } /* while */ - - /* should be never reached */ - PICODBG_ERROR(("reached end of function")); - picoos_emRaiseException(this->common->em, PICO_ERR_OTHER, NULL, NULL); - return PICODATA_PU_ERROR; -} - -#ifdef __cplusplus -} -#endif - - -/* end */ diff --git a/lib/picoacph.h b/lib/picoacph.h deleted file mode 100644 index 266ab6e..0000000 --- a/lib/picoacph.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * 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 picoacph.h - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - - -/** - * @addtogroup picoacph - * -itemtype, iteminfo1, iteminfo2, content -> TYPE(INFO1,INFO2)content -in the following - -items input -=========== - -processed by sa (POS disambiguation): -- WORDGRAPH(POSes,NA)graph -- WORDINDEX(POSes,NA)POS|1ind1...POSN|indN -- CMD(PICODATA_ITEMINFO1_CMD_FLUSH,PICODATA_ITEMINFO2_NA) - -processed by sa (Phrasing, Accentuation): -- PUNC(PUNCtype,PUNCsubtype) - -unprocessed: -- all other item types are forwarded through the PU without modification: - CMD - - -minimal input size (before processing starts) -================== - -processing (POS disambiguation, g2p, lexind, phrasing, accentuation) -is possible with - -- one punctuation-phrase, consisting of a sequence (see below for - limits) of items terminated by a PUNC item. - -(possible but not implemented: as long as the internal buffer is -empty, non-processed item types can be processed immediately) - -Ensuring terminal PUNC item: -- when reading items from the external buffer a CMD(...FLUSH...) is - converted to a PUNC(...FLUSH...) item -- If needed, a PUNC(PHRASE) is artificially added to ensure a phrase - fits in the PUs memory and processing can start. - - -items processed and output -========================== - -precondition: -CMD(...FLUSH...) already converted to PUNC(...FLUSH...) and trailing -PUNC item enforced if necessary. - ----- --# PROCESS_POSD: processing input WORDGRAPH or WORDINDEX items, after -POS disambiguation (POSes -> POS), results in a sequence of: - - - - WORDGRAPH(POS,NA)graph - - WORDINDEX(POS,NA)POS|ind - - - . --# PROCESS_WPHO: then, after lex-index lookup and G2P in a -sequence of: - - WORDPHON(POS,NA)phon - -(phon containing primary and secondary word-level stress) - ----- -3. PROCESS_PHR: then, after processing these WORDPHON items, -together with the trailing PUNC item results in: - --> BOUND(BOUNDstrength,BOUNDtype) - -being added in the sequence of WORDPHON (respectively inserted instead -of the PUNC). All PUNC, incl PUNC(...FLUSH...) now gone. - ----- -4. PROCESS_ACC: then, after processing the WORDPHON and BOUND items -results in: - --> WORDPHON(POS,ACC)phon - -A postprocessing step of accentuation is hard-coded in the -accentuation module: In case the whole word does not have any stress -at all (primary or secondary or both) then do the following mapping: - - ACC0 nostress -> ACC0 - ACC1 nostress -> ACC3 - ACC2 nostress -> ACC3 - ACC3 nostress -> ACC3 - ----- -- POS - a single, unambiguous POS - -cf. picodata.h for -- ACC (sentence-level accent (aka prominence)) %d - - PICODATA_ACC0 - - PICODATA_ACC1 - - PICODATA_ACC2 (<- maybe mapped to ACC1, ie. no ACC2 in output) - - PICODATA_ACC3 - -- BOUNDstrength %d - - PICODATA_ITEMINFO1_BOUND_SBEG (at sentence start) - - PICODATA_ITEMINFO1_BOUND_SEND (at sentence end) - - PICODATA_ITEMINFO1_BOUND_TERM (replaces a flush) - - PICODATA_ITEMINFO1_BOUND_PHR1 (primary boundary) - - PICODATA_ITEMINFO1_BOUND_PHR2 (short break) - - PICODATA_ITEMINFO1_BOUND_PHR3 (secondary phrase boundary, no break) - - PICODATA_ITEMINFO1_BOUND_PHR0 (no break, not produced by sa, not existing - BOUND in item sequence equals PHR0 bound strength) - -- BOUNDtype (created in sa base on punctuation, indicates type of phrase - following the boundary) %d - - PICODATA_ITEMINFO2_BOUNDTYPE_P - - PICODATA_ITEMINFO2_BOUNDTYPE_T - - PICODATA_ITEMINFO2_BOUNDTYPE_Q - - PICODATA_ITEMINFO2_BOUNDTYPE_E - - -output sequence (without CMDs): - - = { BOUND(BOUND_SBEG,PHRASEtype) BOUND(BOUND_SEND,..)} BOUND(BOUND_TERM,..) - - = { BOUND(BOUND_PHR1|2|3,BOUNDtype) } - - = WORDPHON(POS,ACC)phon { WORDPHON(POS,ACC)phon } - -Done in later PU: mapping ACC & word-level stress to syllable accent value - - ACC0 prim -> 0 - - ACC1 prim -> 1 - - ACC2 prim -> 2 - - ACC3 prim -> 3 - - ACC0 sec -> 0 - - ACC1 sec -> 4 - - ACC2 sec -> 4 - - ACC3 sec -> 4 - -other limitations -================= - -- item size: header plus len=256 (valid for Pico in general) -- see defines below for max nr of items. Item heads plus ref. to contents - buffer are stored in array with fixed size elements. Two restrictions: - - MAXNR_HEADX (max nr elements==items in headx array) - - CONTENTSSIZE (max size of all contents together - */ - - -#ifndef PICOACPH_H_ -#define PICOACPH_H_ - -#include "picoos.h" -#include "picodata.h" -#include "picorsrc.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -/* nr item restriction: maximum number of extended item heads in headx */ -#define PICOACPH_MAXNR_HEADX 60 - -/* nr item restriction: maximum size of all item contents together in cont */ -#define PICOACPH_MAXSIZE_CBUF 7680 - - - -picodata_ProcessingUnit picoacph_newAccPhrUnit( - picoos_MemoryManager mm, - picoos_Common common, - picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, - picorsrc_Voice voice); - -#ifdef __cplusplus -} -#endif - -#endif /*PICOACPH_H_*/ diff --git a/lib/picoapi.c b/lib/picoapi.c deleted file mode 100644 index c4ef8bf..0000000 --- a/lib/picoapi.c +++ /dev/null @@ -1,801 +0,0 @@ -/* - * 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 picoapi.c - * - * 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 "picorsrc.h" -#include "picoctrl.h" -#include "picoapi.h" -#include "picoapid.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* ****************************************************************************/ -/* System-level API functions */ -/* ****************************************************************************/ - -#define MAGIC_MASK 0x5069636F /* Pico */ - -#define SET_MAGIC_NUMBER(sys) \ - (sys)->magic = ((picoos_uint32) (sys)) ^ MAGIC_MASK - -#define CHECK_MAGIC_NUMBER(sys) \ - ((sys)->magic == (((picoos_uint32) (sys)) ^ MAGIC_MASK)) - - - -/* *** Auxiliary routines (may also be called from picoextapi.c) **************/ - - -int is_valid_system_handle(pico_System system) -{ - return (system != NULL) && CHECK_MAGIC_NUMBER(system); -} - - -picoos_Common pico_sysGetCommon(pico_System this) -{ - if (this != NULL) { - return this->common; - } else { - return NULL; - } -} - - - -/* *** System initialization and termination functions ************************/ -pico_Status pico_initialize_priv( - void *memory, - const pico_Uint32 size, - pico_Int16 enableMemProt, - pico_System *system - ) -{ - pico_Status status = PICO_OK; - - PICODBG_INITIALIZE(PICODBG_LOG_LEVEL_INFO); - PICODBG_ENABLE_COLORS(0); - /*PICODBG_SET_OUTPUT_FORMAT((PICODBG_SHOW_LEVEL | PICODBG_SHOW_SRCNAME));*/ - - if (memory == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else if (size == 0) { - status = PICO_ERR_INVALID_ARGUMENT; - } else if (system == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else { - byte_ptr_t rest_mem; - picoos_uint32 rest_mem_size; - pico_System sys; - picoos_MemoryManager sysMM; - picoos_ExceptionManager sysEM; - - sys = (pico_System) picoos_raw_malloc(memory, size, sizeof(pico_system_t), - &rest_mem, &rest_mem_size); - if (sys != NULL) { - sysMM = picoos_newMemoryManager(rest_mem, rest_mem_size, enableMemProt ? TRUE : FALSE); - if (sysMM != NULL) { - sysEM = picoos_newExceptionManager(sysMM); - sys->common = picoos_newCommon(sysMM); - sys->rm = picorsrc_newResourceManager(sysMM, sys->common); - if ((sysEM != NULL) && (sys->common != NULL) && (sys->rm != NULL)) { - sys->common->em = sysEM; - sys->common->mm = sysMM; - sys->engine = NULL; - - picorsrc_createDefaultResource(sys->rm /*,&defaultResource */); - - SET_MAGIC_NUMBER(sys); - status = PICO_OK; - } else { - status = PICO_EXC_OUT_OF_MEM; - } - } else { - status = PICO_EXC_OUT_OF_MEM; - } - } else { - status = PICO_EXC_OUT_OF_MEM; - } - *system = sys; - } - - if (status != PICO_OK) { - if (system != NULL) { - *system = NULL; - } - PICODBG_TERMINATE(); - } - - return status; -} -/** - * pico_initialize : initializes the pico system private memory - * @param memory : pointer to a free and already allocated memory area - * @param size : size of the memory area - * @param system : pointer to a pico_System struct - * @return PICO_OK : successful init, !PICO_OK : error on allocating private memory - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_initialize( - void *memory, - const pico_Uint32 size, - pico_System *system - ) -{ - return pico_initialize_priv(memory, size, /*enableMemProt*/ FALSE, system); -} - -/** - * pico_terminate : deallocates the pico system private memory - * @param system : pointer to a pico_System struct - * @return PICO_OK : successful de-init, !PICO_OK : error on de-allocating private memory - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_terminate( - pico_System *system - ) -{ - pico_Status status = PICO_OK; - - if ((system == NULL) || !is_valid_system_handle(*system)) { - status = PICO_ERR_INVALID_HANDLE; - } else { - pico_System sys = *system; - - /* close engine(s) */ - picoctrl_disposeEngine(sys->common->mm, sys->rm, &sys->engine); - - /* close all resources */ - picorsrc_disposeResourceManager(sys->common->mm, &sys->rm); - - sys->magic ^= 0xFFFEFDFC; - *system = NULL; - } - - PICODBG_TERMINATE(); - - return status; -} - - - -/* *** System status and error/warning message retrieval function *************/ - -/** - * pico_getSystemStatusMessage : Returns a description of the system status or errors - * @param system : pointer to a pico_System struct - * @param errCode : pico_System error code - * @param outMessage : memory area where to return a string - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_getSystemStatusMessage( - pico_System system, - pico_Status errCode, - pico_Retstring outMessage - ) -{ - pico_Status status = PICO_OK; - - if (!is_valid_system_handle(system)) { - status = PICO_ERR_INVALID_HANDLE; - if (outMessage != NULL) { - picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "'system' not initialized", PICO_RETSTRINGSIZE); - } - } else if (outMessage == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else { - if (picoos_emGetExceptionCode(system->common->em) == PICO_OK) { - if (errCode == PICO_OK) { - picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "system ok", PICO_RETSTRINGSIZE); - } else { - /* exceptionManager was not informed yet; produce default message */ - picoos_setErrorMsg((picoos_char *) outMessage, PICO_RETSTRINGSIZE, errCode, NULL, NULL, NULL); - } - } else { - picoos_emGetExceptionMessage(system->common->em, (picoos_char *) outMessage, PICO_RETSTRINGSIZE); - } - } - - return status; -} - -/** - * pico_getSystemStatusMessage : Returns the number of warnings - * @param system : pointer to a pico_System struct - * @param *outNrOfWarnings : pointer to location to receive number of warnings - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_getNrSystemWarnings( - pico_System system, - pico_Int32 *outNrOfWarnings - ) -{ - pico_Status status = PICO_OK; - - if (!is_valid_system_handle(system)) { - status = PICO_ERR_INVALID_HANDLE; - if (outNrOfWarnings != NULL) { - *outNrOfWarnings = 0; - } - } else if (outNrOfWarnings == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else { - *outNrOfWarnings = picoos_emGetNumOfWarnings(system->common->em); - } - - return status; -} - -/** - * pico_getSystemWarning : Returns a description of a warning - * @param system : pointer to a pico_System struct - * @param warningIndex : warning index - * @param *outCode : pointer to receive the warning code - * @param outMessage : pointer to receive the output message - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_getSystemWarning( - pico_System system, - const pico_Int32 warningIndex, - pico_Status *outCode, - pico_Retstring outMessage - ) -{ - pico_Status status = PICO_OK; - - if (!is_valid_system_handle(system)) { - status = PICO_ERR_INVALID_HANDLE; - if (outMessage != NULL) { - picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "'system' not initialized", PICO_RETSTRINGSIZE); - } - } else if (warningIndex < 0) { - status = PICO_ERR_INDEX_OUT_OF_RANGE; - } else if ((outCode == NULL) || (outMessage == NULL)) { - status = PICO_ERR_NULLPTR_ACCESS; - } else { - *outCode = picoos_emGetWarningCode(system->common->em, warningIndex); - picoos_emGetWarningMessage(system->common->em, warningIndex, (picoos_char *) outMessage, (picoos_uint16) PICO_RETSTRINGSIZE); - } - - return status; -} - - - -/* *** Resource loading and unloading functions *******************************/ - -/** - * pico_loadResource : Loads a resource file into the Pico system - * @param system : pointer to a pico_System struct - * @param *lingwareFileName : lingware resource file name - * @param *outLingware : pointer to receive the loaded lingware resource memory area address - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_loadResource( - pico_System system, - const pico_Char *lingwareFileName, - pico_Resource *outLingware - ) -{ - pico_Status status = PICO_OK; - - if (!is_valid_system_handle(system)) { - status = PICO_ERR_INVALID_HANDLE; - } else if ((lingwareFileName == NULL) || (outLingware == NULL)) { - status = PICO_ERR_NULLPTR_ACCESS; - } else { - PICODBG_DEBUG(("memory usage before resource loading")); - picoos_showMemUsage(system->common->mm, FALSE, TRUE); - picoos_emReset(system->common->em); - status = picorsrc_loadResource(system->rm, (picoos_char *) lingwareFileName, (picorsrc_Resource *) outLingware); - PICODBG_DEBUG(("memory used to load resource %s", lingwareFileName)); - picoos_showMemUsage(system->common->mm, TRUE, FALSE); - } - - return status; -} - -/** - * pico_unloadResource : unLoads a resource file from the Pico system - * @param system : pointer to a pico_System struct - * @param *inoutLingware : pointer to the loaded lingware resource memory area address - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_unloadResource( - pico_System system, - pico_Resource *inoutLingware - ) -{ - pico_Status status = PICO_OK; - - if (!is_valid_system_handle(system)) { - status = PICO_ERR_INVALID_HANDLE; - } else if (inoutLingware == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else if (!picoctrl_isValidResourceHandle(*((picorsrc_Resource *) inoutLingware))) { - status = PICO_ERR_INVALID_HANDLE; - } else { - PICODBG_DEBUG(("memory usage before resource unloading")); - picoos_showMemUsage(system->common->mm, FALSE, TRUE); - picoos_emReset(system->common->em); - status = picorsrc_unloadResource(system->rm, (picorsrc_Resource *) inoutLingware); - PICODBG_DEBUG(("memory released by resource unloading")); - picoos_showMemUsage(system->common->mm, TRUE, FALSE); - } - - return status; -} - -/* *** Resource inspection functions *******************************/ -/** - * pico_getResourceName : Gets a resource name - * @param system : pointer to a pico_System struct - * @param resource : pointer to the loaded resource memory area address - * @param outName : pointer to the area to receuive the resource name - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_getResourceName( - pico_System system, - pico_Resource resource, - pico_Retstring outName) { - - if (!is_valid_system_handle(system)) { - return PICO_ERR_INVALID_HANDLE; - } else if (NULL == outName) { - return PICO_ERR_NULLPTR_ACCESS; - } - return picorsrc_rsrcGetName((picorsrc_Resource)resource, (picoos_char *) outName, PICO_RETSTRINGSIZE); -} - - -/* *** Voice definition functions *********************************************/ - -/** - * pico_createVoiceDefinition : Creates a voice definition - * @param system : pointer to a pico_System struct - * @param *voiceName : pointer to the area to receive the voice definition - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_createVoiceDefinition( - pico_System system, - const pico_Char *voiceName - ) -{ - pico_Status status = PICO_OK; - - if (!is_valid_system_handle(system)) { - status = PICO_ERR_INVALID_HANDLE; - } else if (voiceName == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else if (picoos_strlen((picoos_char *) voiceName) == 0) { - status = PICO_ERR_INVALID_ARGUMENT; - } else { - picoos_emReset(system->common->em); - status = picorsrc_createVoiceDefinition(system->rm, (picoos_char *) voiceName); - } - - return status; -} - -/** - * pico_addResourceToVoiceDefinition : Adds a mapping pair to a voice definition - * @param system : pointer to a pico_System struct - * @param *voiceName : pointer to the area containing the voice definition - * @param *resourceName : pointer to the area containing the resource name - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_addResourceToVoiceDefinition( - pico_System system, - const pico_Char *voiceName, - const pico_Char *resourceName - ) -{ - pico_Status status = PICO_OK; - - if (!is_valid_system_handle(system)) { - status = PICO_ERR_INVALID_HANDLE; - } else if (voiceName == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else if (picoos_strlen((picoos_char *) voiceName) == 0) { - status = PICO_ERR_INVALID_ARGUMENT; - } else if (resourceName == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else if (picoos_strlen((picoos_char *) resourceName) == 0) { - status = PICO_ERR_INVALID_ARGUMENT; - } else { - picoos_emReset(system->common->em); - status = picorsrc_addResourceToVoiceDefinition(system->rm, (picoos_char *) voiceName, (picoos_char *) resourceName); - } - - return status; -} - -/** - * pico_releaseVoiceDefinition : Releases a voice definition - * @param system : pointer to a pico_System struct - * @param *voiceName : pointer to the area containing the voice definition - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_releaseVoiceDefinition( - pico_System system, - const pico_Char *voiceName - ) -{ - pico_Status status = PICO_OK; - - if (!is_valid_system_handle(system)) { - status = PICO_ERR_INVALID_HANDLE; - } else if (voiceName == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else if (picoos_strlen((picoos_char *) voiceName) == 0) { - status = PICO_ERR_INVALID_ARGUMENT; - } else { - picoos_emReset(system->common->em); - status = picorsrc_releaseVoiceDefinition(system->rm, (picoos_char *) voiceName); - } - - return status; -} - - - -/* *** Engine creation and deletion functions *********************************/ - -/** - * pico_newEngine : Creates and initializes a new Pico engine - * @param system : pointer to a pico_System struct - * @param *voiceName : pointer to the area containing the voice definition - * @param *outEngine : pointer to the Pico engine handle - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_newEngine( - pico_System system, - const pico_Char *voiceName, - pico_Engine *outEngine - ) -{ - pico_Status status = PICO_OK; - - PICODBG_DEBUG(("creating engine for voice '%s'", (picoos_char *) voiceName)); - - if (!is_valid_system_handle(system)) { - status = PICO_ERR_INVALID_HANDLE; - } else if (voiceName == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else if (picoos_strlen((picoos_char *) voiceName) == 0) { - status = PICO_ERR_INVALID_ARGUMENT; - } else if (outEngine == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else { - picoos_emReset(system->common->em); - if (system->engine == NULL) { - *outEngine = (pico_Engine) picoctrl_newEngine(system->common->mm, system->rm, voiceName); - if (*outEngine != NULL) { - system->engine = (picoctrl_Engine) *outEngine; - } else { - status = picoos_emRaiseException(system->common->em, PICO_EXC_OUT_OF_MEM, - (picoos_char *) "out of memory creating new engine", NULL); - } - } else { - status = picoos_emRaiseException(system->common->em, PICO_EXC_MAX_NUM_EXCEED, - NULL, (picoos_char *) "no more than %i engines", 1); - } - } - - return status; -} - -/** - * pico_disposeEngine : Disposes a Pico engine - * @param system : pointer to a pico_System struct - * @param *inoutEngine : pointer to the Pico engine handle - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_disposeEngine( - pico_System system, - pico_Engine *inoutEngine - ) -{ - pico_Status status = PICO_OK; - - if (!is_valid_system_handle(system)) { - status = PICO_ERR_INVALID_HANDLE; - } else if (inoutEngine == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else if (!picoctrl_isValidEngineHandle(*((picoctrl_Engine *) inoutEngine))) { - status = PICO_ERR_INVALID_HANDLE; - } else { - picoos_emReset(system->common->em); - picoctrl_disposeEngine(system->common->mm, system->rm, (picoctrl_Engine *) inoutEngine); - system->engine = NULL; - status = picoos_emGetExceptionCode(system->common->em); - } - - return status; -} - - - -/* ****************************************************************************/ -/* Engine-level API functions */ -/* ****************************************************************************/ - -/** - * pico_putTextUtf8 : Puts UTF8 text into Pico text input buffer - * @param engine : pointer to a Pico engine handle - * @param *text : pointer to the text buffer - * @param textSize : text buffer size - * @param *bytesPut : pointer to variable to receive the number of bytes put - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph - */ -PICO_FUNC pico_putTextUtf8( - pico_Engine engine, - const pico_Char *text, - const pico_Int16 textSize, - pico_Int16 *bytesPut) -{ - pico_Status status = PICO_OK; - - if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) { - status = PICO_ERR_INVALID_HANDLE; - } else if (text == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else if (textSize < 0) { - status = PICO_ERR_INVALID_ARGUMENT; - } else if (bytesPut == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else { - picoctrl_engResetExceptionManager((picoctrl_Engine) engine); - status = picoctrl_engFeedText((picoctrl_Engine) engine, (picoos_char *)text, textSize, bytesPut); - } - - return status; -} - -/** - * pico_getData : Gets speech data from the engine. - * @param engine : pointer to a Pico engine handle - * @param *buffer : pointer to output buffer - * @param bufferSize : out buffer size - * @param *bytesReceived : pointer to a variable to receive the number of bytes received - * @param *outDataType : pointer to a variable to receive the type of buffer received - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_getData( - pico_Engine engine, - void *buffer, - const pico_Int16 bufferSize, - pico_Int16 *bytesReceived, - pico_Int16 *outDataType - ) -{ - pico_Status status = PICO_OK; - - if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) { - status = PICO_STEP_ERROR; - } else if (buffer == NULL) { - status = PICO_STEP_ERROR; - } else if (bufferSize < 0) { - status = PICO_STEP_ERROR; - } else if (bytesReceived == NULL) { - status = PICO_STEP_ERROR; - } else { - picoctrl_engResetExceptionManager((picoctrl_Engine) engine); - status = picoctrl_engFetchOutputItemBytes((picoctrl_Engine) engine, (picoos_char *)buffer, bufferSize, bytesReceived); - if ((status != PICO_STEP_IDLE) && (status != PICO_STEP_BUSY)) { - status = PICO_STEP_ERROR; - } - } - - *outDataType = PICO_DATA_PCM_16BIT; - return status; -} - -/** - * pico_resetEngine : Resets the engine - * @param engine : pointer to a Pico engine handle - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_resetEngine( - pico_Engine engine) -{ - pico_Status status = PICO_OK; - - if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) { - status = PICO_ERR_INVALID_HANDLE; - } else { - picoctrl_engResetExceptionManager((picoctrl_Engine) engine); - status = picoctrl_engReset((picoctrl_Engine) engine); - } - - return status; -} - -/** - * pico_getEngineStatusMessage : Returns the engine status or error description - * @param engine : pointer to a Pico engine handle - * @param errCode : error code - * @param outMessage : pointer to a memory area to receive the output message - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_getEngineStatusMessage( - pico_Engine engine, - pico_Status errCode, - pico_Retstring outMessage - ) -{ - pico_Status status = PICO_OK; - - PICODBG_DEBUG(("got error code %i", errCode)); - - if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) { - status = PICO_ERR_INVALID_HANDLE; - if (outMessage != NULL) { - picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "'engine' not initialized", PICO_RETSTRINGSIZE); - } - } else if (outMessage == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else { - picoos_Common common = picoctrl_engGetCommon((picoctrl_Engine) engine); - if (picoos_emGetExceptionCode(common->em) == PICO_OK) { - if (errCode == PICO_OK) { - picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "engine ok", PICO_RETSTRINGSIZE); - } else { - /* exceptionManager was not informed yet; produce default message */ - picoos_setErrorMsg((picoos_char *) outMessage, PICO_RETSTRINGSIZE, errCode, NULL, NULL, NULL); - } - } else { - picoos_emGetExceptionMessage(common->em, (picoos_char *) outMessage, PICO_RETSTRINGSIZE); - } - } - - return status; -} - -/** - * pico_getNrEngineWarnings : Returns the number of warnings - * @param engine : pointer to a Pico engine handle - * @param *outNrOfWarnings: pointer to a variable to receive the number of warnings - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_getNrEngineWarnings( - pico_Engine engine, - pico_Int32 *outNrOfWarnings - ) -{ - pico_Status status = PICO_OK; - - if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) { - status = PICO_ERR_INVALID_HANDLE; - if (outNrOfWarnings != NULL) { - *outNrOfWarnings = 0; - } - } else if (outNrOfWarnings == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else { - picoos_Common common = picoctrl_engGetCommon((picoctrl_Engine) engine); - *outNrOfWarnings = picoos_emGetNumOfWarnings(common->em); - } - - return status; -} - -/** - * pico_getEngineWarning : Returns a description of a warning - * @param engine : pointer to a Pico engine handle - * @param warningIndex : warning index - * @param *outCode: pointer to a variable to receive the warning code - * @param outMessage: pointer to a memory area to receive the warning description - * @return PICO_OK : successful - * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors - * @callgraph - * @callergraph -*/ -PICO_FUNC pico_getEngineWarning( - pico_Engine engine, - const pico_Int32 warningIndex, - pico_Status *outCode, - pico_Retstring outMessage - ) -{ - pico_Status status = PICO_OK; - - if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) { - status = PICO_ERR_INVALID_HANDLE; - if (outMessage != NULL) { - picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "'engine' not initialized", PICO_RETSTRINGSIZE); - } - } else if (warningIndex < 0) { - status = PICO_ERR_INDEX_OUT_OF_RANGE; - } else if ((outCode == NULL) || (outMessage == NULL)) { - status = PICO_ERR_NULLPTR_ACCESS; - } else { - picoos_Common common = picoctrl_engGetCommon((picoctrl_Engine) engine); - *outCode = picoos_emGetWarningCode(common->em, warningIndex); - picoos_emGetWarningMessage(common->em, warningIndex, (picoos_char *) outMessage, (picoos_uint16) PICO_RETSTRINGSIZE); - } - - return status; -} - -#ifdef __cplusplus -} -#endif - - -/* end */ diff --git a/lib/picoapi.h b/lib/picoapi.h deleted file mode 100644 index 0dad702..0000000 --- a/lib/picoapi.h +++ /dev/null @@ -1,469 +0,0 @@ -/* - * 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 picoapi.h - * - * SVOX Pico application programming interface - * (SVOX Pico version 1.0 and later) - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - */ - - -/** - * @addtogroup picoapi - * -@b Basic_Concepts - -@e SVOX_Pico_System - -The SVOX Pico 'system' is the entity that manages data common to all -SVOX Pico engines, e.g. linguistic data needed to do text-to-speech -(TTS) synthesis, license key, etc. All API functions on the Pico -system level take a 'pico_System' handle as the first parameter. - -@e SVOX_Pico_Engine - -A SVOX Pico 'engine' provides the functions needed to perform actual -synthesis. Currently there can be only one engine instance at a time -(concurrent engines will be possible in the future). All API functions -at the engine level take a 'pico_Engine' handle as the first -parameter. - -@e SVOX_Pico_Resource - -A SVOX Pico 'resource' denotes all the language- and speaker-dependent -data needed to do TTS synthesis. In the following, the term 'resource' -may be used interchangeably with the term 'lingware'. A resource file -contains a set of knowledge bases for an entire TTS voice or parts of -it. - - -@b Basic_Usage - -In its most basic form, an application must call the following -functions in order to perform TTS synthesis: - - - pico_initialize - - pico_loadResource - - pico_createVoiceDefinition - - pico_addResourceToVoiceDefinition - - pico_newEngine - - pico_putTextUtf8 - - pico_getData (several times) - - pico_disposeEngine - - pico_releaseVoiceDefinition - - pico_unloadResource - - pico_terminate - -It is possible to repeatedly run the above sequence, i.e., the SVOX -Pico system may be initialized and terminated multiple times. This may -be useful in applications that need TTS functionality only from time -to time. - - -@b Conventions - -@e Function_arguments - -All arguments that only return values are marked by a leading 'out...' -in their name. All arguments that are used as input and output values -are marked by a leading 'inout...'. All other arguments are read-only -(input) arguments. - -@e Error_handling - -All API functions return a status code which is one of the status -constants defined in picodefs.h. In case of an error, a more detailed -description of the status can be retrieved by calling function -'pico_getSystemStatusMessage' (or 'pico_getEngineStatusMessage' -if the error happened on the SVOX Pico engine level). - -Unlike errors, warnings do not prevent an API function from performing -its function, but output might not be as intended. Functions -'pico_getNrSystemWarnings' and 'pico_getNrEngineWarnings' respectively -can be used to determine whether an API function caused any -warnings. Details about warnings can be retrieved by calling -'pico_getSystemWarning' and 'pico_getEngineWarning' respectively. - -*/ - - - -#ifndef PICOAPI_H_ -#define PICOAPI_H_ - - - -#include "picodefs.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -#ifdef _WIN32 -# define PICO_EXPORT __declspec( dllexport ) -#else -# define PICO_EXPORT extern -#endif - -#define PICO_FUNC PICO_EXPORT pico_Status - - - -/* ********************************************************************/ -/* PICO data types */ -/* ********************************************************************/ - -/* Handle types (opaque) for Pico system, resource, engine ************/ - -typedef struct pico_system *pico_System; -typedef struct pico_resource *pico_Resource; -typedef struct pico_engine *pico_Engine; - - -/* Signed/unsigned integer data types *********************************/ - -#define PICO_INT16_MAX 32767 -#define PICO_UINT16_MAX 0xffff -#define PICO_INT32_MAX 2147483647 -#define PICO_UINT32_MAX 0xffffffff - -#include - -#if (SHRT_MAX == PICO_INT16_MAX) -typedef short pico_Int16; -#else -#error "platform not supported" -#endif - -#if (USHRT_MAX == PICO_UINT16_MAX) -typedef unsigned short pico_Uint16; -#else -#error "platform not supported" -#endif - -#if (INT_MAX == PICO_INT32_MAX) -typedef int pico_Int32; -#else -#error "platform not supported" -#endif - -#if (UINT_MAX == PICO_UINT32_MAX) -typedef unsigned int pico_Uint32; -#else -#error "platform not supported" -#endif - - -/* Char data type *****************************************************/ - -typedef unsigned char pico_Char; - - -/* String type to be used when ASCII string values are returned *******/ - -#define PICO_RETSTRINGSIZE 200 /* maximum length of returned strings */ - -typedef char pico_Retstring[PICO_RETSTRINGSIZE]; - - - -/* ********************************************************************/ -/* System-level API functions */ -/* ********************************************************************/ - -/* System initialization and termination functions ********************/ - -/** - Initializes the Pico system and returns its handle in 'outSystem'. - 'memory' and 'size' define the location and maximum size of memory - in number of bytes that the Pico system will use. The minimum size - required depends on the number of engines and configurations of - lingware to be used. No additional memory will be allocated by the - Pico system. This function must be called before any other API - function is called. It may only be called once (e.g. at application - startup), unless a call to 'pico_terminate'. -*/ -PICO_FUNC pico_initialize( - void *memory, - const pico_Uint32 size, - pico_System *outSystem - ); - -/** - Terminates the Pico system. Lingware resources still being loaded - are unloaded automatically. The memory area provided to Pico in - 'pico_initialize' is released. The system handle becomes - invalid. It is not allowed to call this function as long as Pico - engine instances are existing. No API function may be called after - this function, except for 'pico_initialize', which reinitializes - the system. -*/ -PICO_FUNC pico_terminate( - pico_System *system - ); - - -/* System status and error/warning message retrieval ******************/ - -/** - Returns in 'outMessage' a description of the system status or of an - error that occurred with the most recently called system-level API - function. -*/ -PICO_FUNC pico_getSystemStatusMessage( - pico_System system, - pico_Status errCode, - pico_Retstring outMessage - ); - -/** - Returns in 'outNrOfWarnings' the number of warnings that occurred - with the most recently called system-level API function. -*/ -PICO_FUNC pico_getNrSystemWarnings( - pico_System system, - pico_Int32 *outNrOfWarnings - ); - -/** - Returns in 'outMessage' a description of a warning that occurred - with the most recently called system-level API function. - 'warningIndex' must be in the range 0..N-1 where N is the number of - warnings returned by 'pico_getNrSystemWarnings'. 'outCode' returns - the warning as an integer code (cf. PICO_WARN_*). -*/ -PICO_FUNC pico_getSystemWarning( - pico_System system, - const pico_Int32 warningIndex, - pico_Status *outCode, - pico_Retstring outMessage - ); - - -/* Resource loading and unloading functions ***************************/ - -/** - Loads a resource file into the Pico system. The number of resource - files loaded in parallel is limited by PICO_MAX_NUM_RESOURCES. - Loading of a resource file may be done at any time (even in - parallel to a running engine doing TTS synthesis), but with the - general restriction that functions taking a system handle as their - first argument must be called in a mutually exclusive fashion. The - loaded resource will be available only to engines started after the - resource is fully loaded, i.e., not to engines currently - running. -*/ -PICO_FUNC pico_loadResource( - pico_System system, - const pico_Char *resourceFileName, - pico_Resource *outResource - ); - -/** - Unloads a resource file from the Pico system. If no engine uses the - resource file, the resource is removed immediately and its - associated internal memory is released, otherwise - PICO_EXC_RESOURCE_BUSY is returned. -*/ -PICO_FUNC pico_unloadResource( - pico_System system, - pico_Resource *inoutResource - ); - -/* *** Resource inspection functions *******************************/ - -/** - Gets the unique resource name of a loaded resource -*/ -PICO_FUNC pico_getResourceName( - pico_System system, - pico_Resource resource, - pico_Retstring outName); - - -/* Voice definition ***************************************************/ - -/** - Creates a voice definition. Resources must be added to the created - voice with 'pico_addResourceToVoiceDefinition' before using the - voice in 'pico_newEngine'. It is an error to create a voice - definition with a previously defined voice name. In that case use - 'pico_releaseVoiceName' first. -*/ -PICO_FUNC pico_createVoiceDefinition( - pico_System system, - const pico_Char *voiceName - ); - -/** - Adds a mapping pair ('voiceName', 'resourceName') to the voice - definition. Multiple mapping pairs can added to a voice defintion. - When calling 'pico_newEngine' with 'voiceName', the corresponding - resources from the mappings will be used with that engine. */ - -PICO_FUNC pico_addResourceToVoiceDefinition( - pico_System system, - const pico_Char *voiceName, - const pico_Char *resourceName - ); - - -/** - Releases the voice definition 'voiceName'. - -*/ -PICO_FUNC pico_releaseVoiceDefinition( - pico_System system, - const pico_Char *voiceName - ); - - -/* Engine creation and deletion functions *****************************/ - -/** - Creates and initializes a new Pico engine instance and returns its - handle in 'outEngine'. Only one instance per system is currently - possible. -*/ -PICO_FUNC pico_newEngine( - pico_System system, - const pico_Char *voiceName, - pico_Engine *outEngine - ); - - -/** - Disposes a Pico engine and releases all memory it occupied. The - engine handle becomes invalid. -*/ -PICO_FUNC pico_disposeEngine( - pico_System system, - pico_Engine *inoutEngine - ); - - - -/* ********************************************************************/ -/* Engine-level API functions */ -/* ********************************************************************/ - -/** - Puts text 'text' encoded in UTF8 into the Pico text input buffer. - 'textSize' is the maximum size in number of bytes accessible in - 'text'. The input text may also contain text-input commands to - change, for example, speed or pitch of the resulting speech - output. The number of bytes actually copied to the Pico text input - buffer is returned in 'outBytesPut'. Sentence ends are - automatically detected. '\0' characters may be embedded in 'text' - to finish text input or separate independently to be synthesized - text parts from each other. Repeatedly calling 'pico_getData' will - result in the content of the text input buffer to be synthesized - (up to the last sentence end or '\0' character detected). To empty - the internal buffers without finishing synthesis, use the function - 'pico_resetEngine'. -*/ -PICO_FUNC pico_putTextUtf8( - pico_Engine engine, - const pico_Char *text, - const pico_Int16 textSize, - pico_Int16 *outBytesPut - ); - -/** - Gets speech data from the engine. Every time this function is - called, the engine performs, within a short time slot, a small - amount of processing its input text, and then gives control back to - the calling application. Ie. after calling 'pico_putTextUtf8' - (incl. a final embedded '\0'), this function needs to be called - repeatedly till 'outBytesReceived' bytes are returned in - 'outBuffer'. The type of data returned in 'outBuffer' (e.g. 8 or 16 - bit PCM samples) is returned in 'outDataType' and depends on the - lingware resources. Possible 'outDataType' values are listed in - picodefs.h (PICO_DATA_*). - This function returns PICO_STEP_BUSY while processing input and - producing speech output. Once all data is returned and there is no - more input text available in the Pico text input buffer, - PICO_STEP_IDLE is returned. All other function return values - indicate a system error. -*/ -PICO_FUNC pico_getData( - pico_Engine engine, - void *outBuffer, - const pico_Int16 bufferSize, - pico_Int16 *outBytesReceived, - pico_Int16 *outDataType - ); - -/** - Resets the engine and clears all engine-internal buffers, in - particular text input and signal data output buffers. -*/ -PICO_FUNC pico_resetEngine( - pico_Engine engine - ); - - -/* Engine status and error/warning message retrieval ******************/ - -/** - Returns in 'outMessage' a description of the engine status or of an - error that occurred with the most recently called engine-level API - function. -*/ -PICO_FUNC pico_getEngineStatusMessage( - pico_Engine engine, - pico_Status errCode, - pico_Retstring outMessage - ); - -/** - Returns in 'outNrOfWarnings' the number of warnings that occurred - with the most recently called engine-level API function. -*/ -PICO_FUNC pico_getNrEngineWarnings( - pico_Engine engine, - pico_Int32 *outNrOfWarnings - ); - -/** - Returns in 'outMessage' a description of a warning that occurred - with the most recently called engine-level API function. - 'warningIndex' must be in the range 0..N-1 where N is the number of - warnings returned by 'pico_getNrEngineWarnings'. 'outCode' returns - the warning as an integer code (cf. PICO_WARN_*). -*/ -PICO_FUNC pico_getEngineWarning( - pico_Engine engine, - const pico_Int32 warningIndex, - pico_Status *outCode, - pico_Retstring outMessage - ); - -#ifdef __cplusplus -} -#endif - -#endif /*PICOAPI_H_*/ diff --git a/lib/picoapid.h b/lib/picoapid.h deleted file mode 100644 index ef62701..0000000 --- a/lib/picoapid.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 picoapid.h - * - * Pico api definitions commonly used by picoapi and picoapiext - * - * This header file must be part of the runtime-only pico system and therefore - * must not include picoapiext.h! - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#ifndef PICOAPID_H_ -#define PICOAPID_H_ - -#include "picodefs.h" -#include "picoapi.h" -#include "picoos.h" -#include "picorsrc.h" -#include "picoctrl.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* Pico system descriptor */ -typedef struct pico_system { - picoos_uint32 magic; /* magic number used to validate handles */ - picoos_Common common; - picorsrc_ResourceManager rm; - picoctrl_Engine engine; -} pico_system_t; - - -/* declared in picoapi.c */ -extern int is_valid_system_handle(pico_System system); -extern picoos_Common pico_sysGetCommon(pico_System this); - - -#if 0 -{ -#endif -#ifdef __cplusplus -} -#endif - -#endif /* PICOAPID_H_ */ diff --git a/lib/picobase.c b/lib/picobase.c deleted file mode 100644 index 9246551..0000000 --- a/lib/picobase.c +++ /dev/null @@ -1,1243 +0,0 @@ -/* - * 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 picobase.c - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#include "picoos.h" -#include "picodbg.h" -#include "picodefs.h" -#include "picobase.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -/** - * @addtogroup picobase - * - * @b Unicode_UTF8_functions - * - * UTF8 - * scalar value 1st Byte 2nd Byte 3rd Byte 4th Byte - * 00000000 0xxxxxxx 0xxxxxxx - * 00000yyy yyxxxxxx 110yyyyy 10xxxxxx - * zzzzyyyy yyxxxxxx 1110zzzz 10yyyyyy 10xxxxxx - * 000uuuuu zzzzyyyy yyxxxxx 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx - * -*/ -picoos_int32 picobase_utf8_length(const picoos_uint8 *utf8str, - const picoos_uint16 maxlen) { - - picoos_uint16 i; - picoos_uint16 len; - picoos_uint8 follow; - picoos_uint8 ok; - - ok = TRUE; - i = 0; - len = 0; - follow = 0; - while (ok && (i < maxlen) && (utf8str[i] != '\000')) { - if (follow > 0) { - if ((utf8str[i] >= (picoos_uint8)'\200') && - (utf8str[i] < (picoos_uint8)'\300')) { - follow--; - } else { - ok = FALSE; - } - } else if (utf8str[i] < (picoos_uint8)'\200') { - len++; - } else if (utf8str[i] >= (picoos_uint8)'\370') { - ok = FALSE; - } else if (utf8str[i] >= (picoos_uint8)'\360') { - follow = 3; - len++; - } else if (utf8str[i] >= (picoos_uint8)'\340') { - follow = 2; - len++; - } else if (utf8str[i] >= (picoos_uint8)'\300') { - follow = 1; - len++; - } else { - ok = FALSE; - } - i++; - } - if (ok) { - return len; - } else { - return -1; - } -} - - -static picoos_uint32 base_utf32_lowercase (picoos_uint32 utf32) -{ - - picoos_uint32 lc; - - lc = utf32; - if (((utf32 >= 65313) && (utf32 <= 65338))) { - lc = (utf32 + 32); - } else if (((utf32 >= 66560) && (utf32 <= 66599))) { - lc = (utf32 + 40); - } else if (((utf32 >= 7680) && (utf32 <= 9423))) { - switch (utf32) { - case 7680: case 7681: case 7682: case 7683: case 7684: case 7685: case 7686: case 7687: case 7688: case 7689: - case 7690: case 7691: case 7692: case 7693: case 7694: case 7695: case 7696: case 7697: case 7698: case 7699: case 7700: case 7701: - case 7702: case 7703: case 7704: case 7705: case 7706: case 7707: case 7708: case 7709: case 7710: case 7711: case 7712: case 7713: - case 7714: case 7715: case 7716: case 7717: case 7718: case 7719: case 7720: case 7721: case 7722: case 7723: case 7724: case 7725: - case 7726: case 7727: case 7728: case 7729: case 7730: case 7731: case 7732: case 7733: case 7734: case 7735: case 7736: case 7737: - case 7738: case 7739: case 7740: case 7741: case 7742: case 7743: case 7744: case 7745: case 7746: case 7747: case 7748: case 7749: - case 7750: case 7751: case 7752: case 7753: case 7754: case 7755: case 7756: case 7757: case 7758: case 7759: case 7760: case 7761: - case 7762: case 7763: case 7764: case 7765: case 7766: case 7767: case 7768: case 7769: case 7770: case 7771: case 7772: case 7773: - case 7774: case 7775: case 7776: case 7777: case 7778: case 7779: case 7780: case 7781: case 7782: case 7783: case 7784: case 7785: - case 7786: case 7787: case 7788: case 7789: case 7790: case 7791: case 7792: case 7793: case 7794: case 7795: case 7796: case 7797: - case 7798: case 7799: case 7800: case 7801: case 7802: case 7803: case 7804: case 7805: case 7806: case 7807: case 7808: case 7809: - case 7810: case 7811: case 7812: case 7813: case 7814: case 7815: case 7816: case 7817: case 7818: case 7819: case 7820: case 7821: - case 7822: case 7823: case 7824: case 7825: case 7826: case 7827: case 7828: case 7840: case 7841: case 7842: case 7843: - case 7844: case 7845: case 7846: case 7847: case 7848: case 7849: case 7850: case 7851: case 7852: case 7853: case 7854: case 7855: - case 7856: case 7857: case 7858: case 7859: case 7860: case 7861: case 7862: case 7863: case 7864: case 7865: case 7866: case 7867: - case 7868: case 7869: case 7870: case 7871: case 7872: case 7873: case 7874: case 7875: case 7876: case 7877: case 7878: case 7879: - case 7880: case 7881: case 7882: case 7883: case 7884: case 7885: case 7886: case 7887: case 7888: case 7889: case 7890: case 7891: - case 7892: case 7893: case 7894: case 7895: case 7896: case 7897: case 7898: case 7899: case 7900: case 7901: case 7902: case 7903: - case 7904: case 7905: case 7906: case 7907: case 7908: case 7909: case 7910: case 7911: case 7912: case 7913: case 7914: case 7915: - case 7916: case 7917: case 7918: case 7919: case 7920: case 7921: case 7922: case 7923: case 7924: case 7925: case 7926: case 7927: - case 7928: - if ( !(((utf32) % 2 == 1))) { - lc = (utf32 + 1); - } - break; - case 7944: case 7945: case 7946: case 7947: case 7948: case 7949: case 7950: case 7951: case 7960: - case 7961: case 7962: case 7963: case 7964: case 7965: case 7976: case 7977: case 7978: case 7979: case 7980: case 7981: - case 7982: case 7983: case 7992: case 7993: case 7994: case 7995: case 7996: case 7997: case 7998: case 7999: - case 8008: case 8009: case 8010: case 8011: case 8012: case 8013: case 8040: case 8041: case 8042: case 8043: case 8044: - case 8045: case 8046: case 8047: case 8072: case 8073: case 8074: case 8075: case 8076: case 8077: case 8078: case 8079: - case 8088: case 8089: case 8090: case 8091: case 8092: case 8093: case 8094: case 8095: case 8104: case 8105: - case 8106: case 8107: case 8108: case 8109: case 8110: case 8111: - lc = (utf32 - 8); - break; - case 8025: case 8026: case 8027: case 8028: case 8029: case 8030: case 8031: - if (((utf32) % 2 == 1)) { - lc = (utf32 - 8); - } - break; - case 8544: case 8545: case 8546: case 8547: case 8548: case 8549: case 8550: case 8551: case 8552: case 8553: - case 8554: case 8555: case 8556: case 8557: case 8558: case 8559: - lc = (utf32 + 16); - break; - case 9398: case 9399: case 9400: case 9401: case 9402: case 9403: case 9404: case 9405: case 9406: case 9407: - case 9408: case 9409: case 9410: case 9411: case 9412: case 9413: case 9414: case 9415: case 9416: case 9417: case 9418: case 9419: - case 9420: case 9421: case 9422: case 9423: - lc = (utf32 + 26); - break; - case 8120: - lc = 8112; - break; - case 8121: - lc = 8113; - break; - case 8122: - lc = 8048; - break; - case 8123: - lc = 8049; - break; - case 8124: - lc = 8115; - break; - case 8136: - lc = 8050; - break; - case 8137: - lc = 8051; - break; - case 8138: - lc = 8052; - break; - case 8139: - lc = 8053; - break; - case 8140: - lc = 8131; - break; - case 8152: - lc = 8144; - break; - case 8153: - lc = 8145; - break; - case 8154: - lc = 8054; - break; - case 8155: - lc = 8055; - break; - case 8168: - lc = 8160; - break; - case 8169: - lc = 8161; - break; - case 8170: - lc = 8058; - break; - case 8171: - lc = 8059; - break; - case 8172: - lc = 8165; - break; - case 8184: - lc = 8056; - break; - case 8185: - lc = 8057; - break; - case 8186: - lc = 8060; - break; - case 8187: - lc = 8061; - break; - case 8188: - lc = 8179; - break; - case 8486: - lc = 969; - break; - case 8490: - lc = 107; - break; - case 8491: - lc = 229; - break; - default: - break; - } - } else { - switch (utf32) { - case 65: case 66: case 67: case 68: case 69: case 70: case 71: case 72: case 73: case 74: - case 75: case 76: case 77: case 78: case 79: case 80: case 81: case 82: case 83: case 84: case 85: case 86: - case 87: case 88: case 89: case 90: case 192: case 193: case 194: case 195: case 196: case 197: case 198: - case 199: case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207: case 208: case 209: case 210: - case 211: case 212: case 213: case 214: case 216: case 217: case 218: case 219: case 220: case 221: case 222: - case 913: case 914: case 915: case 916: case 917: case 918: case 919: case 920: case 921: case 922: case 923: - case 924: case 925: case 926: case 927: case 928: case 929: case 931: case 932: case 933: case 934: case 935: - case 936: case 937: case 938: case 939: case 1040: case 1041: case 1042: case 1043: case 1044: case 1045: case 1046: - case 1047: case 1048: case 1049: case 1050: case 1051: case 1052: case 1053: case 1054: case 1055: case 1056: case 1057: case 1058: - case 1059: case 1060: case 1061: case 1062: case 1063: case 1064: case 1065: case 1066: case 1067: case 1068: case 1069: case 1070: - case 1071: - lc = (utf32 + 32); - break; - case 256: case 257: case 258: case 259: case 260: case 261: case 262: case 263: case 264: case 265: - case 266: case 267: case 268: case 269: case 270: case 271: case 272: case 273: case 274: case 275: case 276: case 277: - case 278: case 279: case 280: case 281: case 282: case 283: case 284: case 285: case 286: case 287: case 288: case 289: - case 290: case 291: case 292: case 293: case 294: case 295: case 296: case 297: case 298: case 299: case 300: case 301: - case 302: case 303: case 305: case 306: case 307: case 308: case 309: case 310: case 330: case 331: - case 332: case 333: case 334: case 335: case 336: case 337: case 338: case 339: case 340: case 341: case 342: case 343: - case 344: case 345: case 346: case 347: case 348: case 349: case 350: case 351: case 352: case 353: case 354: case 355: - case 356: case 357: case 358: case 359: case 360: case 361: case 362: case 363: case 364: case 365: case 366: case 367: - case 368: case 369: case 370: case 371: case 372: case 373: case 374: case 416: case 417: case 418: case 419: - case 420: case 478: case 479: case 480: case 481: case 482: case 483: case 484: case 485: case 486: case 487: - case 488: case 489: case 490: case 491: case 492: case 493: case 494: case 504: case 505: case 506: case 507: - case 508: case 509: case 510: case 511: case 512: case 513: case 514: case 515: case 516: case 517: case 518: case 519: - case 520: case 521: case 522: case 523: case 524: case 525: case 526: case 527: case 528: case 529: case 530: case 531: - case 532: case 533: case 534: case 535: case 536: case 537: case 538: case 539: case 540: case 541: case 542: - case 546: case 547: case 548: case 549: case 550: case 551: case 552: case 553: case 554: case 555: case 556: case 557: - case 558: case 559: case 560: case 561: case 562: case 984: case 985: case 986: case 987: case 988: case 989: - case 990: case 991: case 992: case 993: case 994: case 995: case 996: case 997: case 998: case 999: case 1000: case 1001: - case 1002: case 1003: case 1004: case 1005: case 1006: case 1120: case 1121: case 1122: case 1123: case 1124: case 1125: - case 1126: case 1127: case 1128: case 1129: case 1130: case 1131: case 1132: case 1133: case 1134: case 1135: case 1136: case 1137: - case 1138: case 1139: case 1140: case 1141: case 1142: case 1143: case 1144: case 1145: case 1146: case 1147: case 1148: case 1149: - case 1150: case 1151: case 1152: case 1162: case 1163: case 1164: case 1165: case 1166: case 1167: case 1168: case 1169: - case 1170: case 1171: case 1172: case 1173: case 1174: case 1175: case 1176: case 1177: case 1178: case 1179: case 1180: case 1181: - case 1182: case 1183: case 1184: case 1185: case 1186: case 1187: case 1188: case 1189: case 1190: case 1191: case 1192: case 1193: - case 1194: case 1195: case 1196: case 1197: case 1198: case 1199: case 1200: case 1201: case 1202: case 1203: case 1204: case 1205: - case 1206: case 1207: case 1208: case 1209: case 1210: case 1211: case 1212: case 1213: case 1214: case 1232: case 1233: - case 1234: case 1235: case 1236: case 1237: case 1238: case 1239: case 1240: case 1241: case 1242: case 1243: case 1244: case 1245: - case 1246: case 1247: case 1248: case 1249: case 1250: case 1251: case 1252: case 1253: case 1254: case 1255: case 1256: case 1257: - case 1258: case 1259: case 1260: case 1261: case 1262: case 1263: case 1264: case 1265: case 1266: case 1267: case 1268: - case 1280: case 1281: case 1282: case 1283: case 1284: case 1285: case 1286: case 1287: case 1288: case 1289: case 1290: case 1291: - case 1292: case 1293: case 1294: - if ( !(((utf32) % 2 == 1))) { - lc = (utf32 + 1); - } - break; - case 313: case 314: case 315: case 316: case 317: case 318: case 319: case 320: case 321: case 322: - case 323: case 324: case 325: case 326: case 327: case 377: case 378: case 379: case 380: case 381: - case 459: case 460: case 461: case 462: case 463: case 464: case 465: case 466: case 467: case 468: case 469: case 470: - case 471: case 472: case 473: case 474: case 475: case 1217: case 1218: case 1219: case 1220: case 1221: case 1222: - case 1223: case 1224: case 1225: case 1226: case 1227: case 1228: case 1229: - if (((utf32) % 2 == 1)) { - lc = (utf32 + 1); - } - break; - case 1024: case 1025: case 1026: case 1027: case 1028: case 1029: case 1030: case 1031: case 1032: case 1033: - case 1034: case 1035: case 1036: case 1037: case 1038: case 1039: - lc = (utf32 + 80); - break; - case 1329: case 1330: case 1331: case 1332: case 1333: case 1334: case 1335: case 1336: case 1337: case 1338: - case 1339: case 1340: case 1341: case 1342: case 1343: case 1344: case 1345: case 1346: case 1347: case 1348: case 1349: case 1350: - case 1351: case 1352: case 1353: case 1354: case 1355: case 1356: case 1357: case 1358: case 1359: case 1360: case 1361: case 1362: - case 1363: case 1364: case 1365: case 1366: - lc = (utf32 + 48); - break; - case 304: - lc = 105; - break; - case 376: - lc = 255; - break; - case 385: - lc = 595; - break; - case 386: - lc = 387; - break; - case 388: - lc = 389; - break; - case 390: - lc = 596; - break; - case 391: - lc = 392; - break; - case 393: - lc = 598; - break; - case 394: - lc = 599; - break; - case 395: - lc = 396; - break; - case 398: - lc = 477; - break; - case 399: - lc = 601; - break; - case 400: - lc = 603; - break; - case 401: - lc = 402; - break; - case 403: - lc = 608; - break; - case 404: - lc = 611; - break; - case 406: - lc = 617; - break; - case 407: - lc = 616; - break; - case 408: - lc = 409; - break; - case 412: - lc = 623; - break; - case 413: - lc = 626; - break; - case 415: - lc = 629; - break; - case 422: - lc = 640; - break; - case 423: - lc = 424; - break; - case 425: - lc = 643; - break; - case 428: - lc = 429; - break; - case 430: - lc = 648; - break; - case 431: - lc = 432; - break; - case 433: - lc = 650; - break; - case 434: - lc = 651; - break; - case 435: - lc = 436; - break; - case 437: - lc = 438; - break; - case 439: - lc = 658; - break; - case 440: - lc = 441; - break; - case 444: - lc = 445; - break; - case 452: - lc = 454; - break; - case 453: - lc = 454; - break; - case 455: - lc = 457; - break; - case 456: - lc = 457; - break; - case 458: - lc = 460; - break; - case 497: - lc = 499; - break; - case 498: - lc = 499; - break; - case 500: - lc = 501; - break; - case 502: - lc = 405; - break; - case 503: - lc = 447; - break; - case 544: - lc = 414; - break; - case 902: - lc = 940; - break; - case 904: - lc = 941; - break; - case 905: - lc = 942; - break; - case 906: - lc = 943; - break; - case 908: - lc = 972; - break; - case 910: - lc = 973; - break; - case 911: - lc = 974; - break; - case 1012: - lc = 952; - break; - case 1015: - lc = 1016; - break; - case 1017: - lc = 1010; - break; - case 1018: - lc = 1019; - break; - case 1272: - lc = 1273; - break; - default: - break; - } - } - return lc; -} - -/** - * Converts utf32 input to uppercase - * @param utf32 : a single character encoded in UTF32 - * @return a single uppercase character encoded in UTF32 -*/ -static picoos_uint32 base_utf32_uppercase (picoos_uint32 utf32) -{ - picoos_uint32 lc; - - lc = utf32; - if (((utf32 >= 65345) && (utf32 <= 65370))) { - lc = (utf32 - 32); - } else if (((utf32 >= 66600) && (utf32 <= 66639))) { - lc = (utf32 - 40); - } else if (((utf32 >= 7681) && (utf32 <= 9449))) { - switch (utf32) { - case 7681: case 7682: case 7683: case 7684: case 7685: case 7686: case 7687: case 7688: case 7689: case 7690: - case 7691: case 7692: case 7693: case 7694: case 7695: case 7696: case 7697: case 7698: case 7699: case 7700: case 7701: case 7702: - case 7703: case 7704: case 7705: case 7706: case 7707: case 7708: case 7709: case 7710: case 7711: case 7712: case 7713: case 7714: - case 7715: case 7716: case 7717: case 7718: case 7719: case 7720: case 7721: case 7722: case 7723: case 7724: case 7725: case 7726: - case 7727: case 7728: case 7729: case 7730: case 7731: case 7732: case 7733: case 7734: case 7735: case 7736: case 7737: case 7738: - case 7739: case 7740: case 7741: case 7742: case 7743: case 7744: case 7745: case 7746: case 7747: case 7748: case 7749: case 7750: - case 7751: case 7752: case 7753: case 7754: case 7755: case 7756: case 7757: case 7758: case 7759: case 7760: case 7761: case 7762: - case 7763: case 7764: case 7765: case 7766: case 7767: case 7768: case 7769: case 7770: case 7771: case 7772: case 7773: case 7774: - case 7775: case 7776: case 7777: case 7778: case 7779: case 7780: case 7781: case 7782: case 7783: case 7784: case 7785: case 7786: - case 7787: case 7788: case 7789: case 7790: case 7791: case 7792: case 7793: case 7794: case 7795: case 7796: case 7797: case 7798: - case 7799: case 7800: case 7801: case 7802: case 7803: case 7804: case 7805: case 7806: case 7807: case 7808: case 7809: case 7810: - case 7811: case 7812: case 7813: case 7814: case 7815: case 7816: case 7817: case 7818: case 7819: case 7820: case 7821: case 7822: - case 7823: case 7824: case 7825: case 7826: case 7827: case 7828: case 7829: case 7841: case 7842: case 7843: case 7844: - case 7845: case 7846: case 7847: case 7848: case 7849: case 7850: case 7851: case 7852: case 7853: case 7854: case 7855: case 7856: - case 7857: case 7858: case 7859: case 7860: case 7861: case 7862: case 7863: case 7864: case 7865: case 7866: case 7867: case 7868: - case 7869: case 7870: case 7871: case 7872: case 7873: case 7874: case 7875: case 7876: case 7877: case 7878: case 7879: case 7880: - case 7881: case 7882: case 7883: case 7884: case 7885: case 7886: case 7887: case 7888: case 7889: case 7890: case 7891: case 7892: - case 7893: case 7894: case 7895: case 7896: case 7897: case 7898: case 7899: case 7900: case 7901: case 7902: case 7903: case 7904: - case 7905: case 7906: case 7907: case 7908: case 7909: case 7910: case 7911: case 7912: case 7913: case 7914: case 7915: case 7916: - case 7917: case 7918: case 7919: case 7920: case 7921: case 7922: case 7923: case 7924: case 7925: case 7926: case 7927: case 7928: - case 7929: - if (((utf32) % 2 == 1)) { - lc = (utf32 - 1); - } - break; - case 7936: case 7937: case 7938: case 7939: case 7940: case 7941: case 7942: case 7943: case 7952: - case 7953: case 7954: case 7955: case 7956: case 7957: case 7968: case 7969: case 7970: case 7971: case 7972: case 7973: - case 7974: case 7975: case 7984: case 7985: case 7986: case 7987: case 7988: case 7989: case 7990: case 7991: - case 8000: case 8001: case 8002: case 8003: case 8004: case 8005: case 8032: case 8033: case 8034: case 8035: case 8036: - case 8037: case 8038: case 8039: case 8064: case 8065: case 8066: case 8067: case 8068: case 8069: case 8070: case 8071: - case 8080: case 8081: case 8082: case 8083: case 8084: case 8085: case 8086: case 8087: case 8096: case 8097: - case 8098: case 8099: case 8100: case 8101: case 8102: case 8103: - lc = (utf32 + 8); - break; - case 8017: case 8018: case 8019: case 8020: case 8021: case 8022: case 8023: - if (((utf32) % 2 == 1)) { - lc = (utf32 + 8); - } - break; - case 8560: case 8561: case 8562: case 8563: case 8564: case 8565: case 8566: case 8567: case 8568: case 8569: - case 8570: case 8571: case 8572: case 8573: case 8574: case 8575: - lc = (utf32 - 16); - break; - case 9424: case 9425: case 9426: case 9427: case 9428: case 9429: case 9430: case 9431: case 9432: case 9433: - case 9434: case 9435: case 9436: case 9437: case 9438: case 9439: case 9440: case 9441: case 9442: case 9443: case 9444: case 9445: - case 9446: case 9447: case 9448: case 9449: - lc = (utf32 - 26); - break; - case 7835: - lc = 7776; - break; - case 8048: - lc = 8122; - break; - case 8049: - lc = 8123; - break; - case 8050: - lc = 8136; - break; - case 8051: - lc = 8137; - break; - case 8052: - lc = 8138; - break; - case 8053: - lc = 8139; - break; - case 8054: - lc = 8154; - break; - case 8055: - lc = 8155; - break; - case 8056: - lc = 8184; - break; - case 8057: - lc = 8185; - break; - case 8058: - lc = 8170; - break; - case 8059: - lc = 8171; - break; - case 8060: - lc = 8186; - break; - case 8061: - lc = 8187; - break; - case 8112: - lc = 8120; - break; - case 8113: - lc = 8121; - break; - case 8115: - lc = 8124; - break; - case 8126: - lc = 921; - break; - case 8131: - lc = 8140; - break; - case 8144: - lc = 8152; - break; - case 8145: - lc = 8153; - break; - case 8160: - lc = 8168; - break; - case 8161: - lc = 8169; - break; - case 8165: - lc = 8172; - break; - case 8179: - lc = 8188; - break; - default: - break; - } - } else { - switch (utf32) { - case 97: case 98: case 99: case 100: case 101: case 102: case 103: case 104: case 105: case 106: - case 107: case 108: case 109: case 110: case 111: case 112: case 113: case 114: case 115: case 116: case 117: case 118: - case 119: case 120: case 121: case 122: case 224: case 225: case 226: case 227: case 228: case 229: case 230: - case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: - case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: - case 945: case 946: case 947: case 948: case 949: case 950: case 951: case 952: case 953: case 954: case 955: - case 956: case 957: case 958: case 959: case 960: case 961: case 963: case 964: case 965: case 966: case 967: - case 968: case 969: case 970: case 971: case 1072: case 1073: case 1074: case 1075: case 1076: case 1077: case 1078: - case 1079: case 1080: case 1081: case 1082: case 1083: case 1084: case 1085: case 1086: case 1087: case 1088: case 1089: case 1090: - case 1091: case 1092: case 1093: case 1094: case 1095: case 1096: case 1097: case 1098: case 1099: case 1100: case 1101: case 1102: - case 1103: - if ((utf32 != 247)) { - lc = (utf32 - 32); - } - break; - case 257: case 258: case 259: case 260: case 261: case 262: case 263: case 264: case 265: case 266: - case 267: case 268: case 269: case 270: case 271: case 272: case 273: case 274: case 275: case 276: case 277: case 278: - case 279: case 280: case 281: case 282: case 283: case 284: case 285: case 286: case 287: case 288: case 289: case 290: - case 291: case 292: case 293: case 294: case 295: case 296: case 297: case 298: case 299: case 300: case 301: case 302: - case 303: case 304: case 306: case 307: case 308: case 309: case 310: case 311: case 331: case 332: - case 333: case 334: case 335: case 336: case 337: case 338: case 339: case 340: case 341: case 342: case 343: case 344: - case 345: case 346: case 347: case 348: case 349: case 350: case 351: case 352: case 353: case 354: case 355: case 356: - case 357: case 358: case 359: case 360: case 361: case 362: case 363: case 364: case 365: case 366: case 367: case 368: - case 369: case 370: case 371: case 372: case 373: case 374: case 375: case 417: case 418: case 419: case 420: - case 421: case 481: case 482: case 483: case 484: case 485: case 486: case 487: case 488: case 489: case 490: - case 491: case 492: case 493: case 494: case 495: case 507: case 508: case 509: case 510: case 511: - case 513: case 514: case 515: case 516: case 517: case 518: case 519: case 520: case 521: case 522: case 523: case 524: - case 525: case 526: case 527: case 528: case 529: case 530: case 531: case 532: case 533: case 534: case 535: case 536: - case 537: case 538: case 539: case 540: case 541: case 542: case 543: case 544: case 546: case 547: case 548: - case 549: case 550: case 551: case 552: case 553: case 554: case 555: case 556: case 557: case 558: case 559: case 560: - case 561: case 562: case 563: case 985: case 986: case 987: case 988: case 989: case 990: case 991: case 992: - case 993: case 994: case 995: case 996: case 997: case 998: case 999: case 1000: case 1001: case 1002: case 1003: case 1004: - case 1005: case 1006: case 1007: case 1121: case 1122: case 1123: case 1124: case 1125: case 1126: case 1127: case 1128: - case 1129: case 1130: case 1131: case 1132: case 1133: case 1134: case 1135: case 1136: case 1137: case 1138: case 1139: case 1140: - case 1141: case 1142: case 1143: case 1144: case 1145: case 1146: case 1147: case 1148: case 1149: case 1150: case 1151: case 1152: - case 1153: case 1163: case 1164: case 1165: case 1166: case 1167: case 1168: case 1169: case 1170: case 1171: case 1172: - case 1173: case 1174: case 1175: case 1176: case 1177: case 1178: case 1179: case 1180: case 1181: case 1182: case 1183: case 1184: - case 1185: case 1186: case 1187: case 1188: case 1189: case 1190: case 1191: case 1192: case 1193: case 1194: case 1195: case 1196: - case 1197: case 1198: case 1199: case 1200: case 1201: case 1202: case 1203: case 1204: case 1205: case 1206: case 1207: case 1208: - case 1209: case 1210: case 1211: case 1212: case 1213: case 1214: case 1215: case 1233: case 1234: case 1235: case 1236: - case 1237: case 1238: case 1239: case 1240: case 1241: case 1242: case 1243: case 1244: case 1245: case 1246: case 1247: case 1248: - case 1249: case 1250: case 1251: case 1252: case 1253: case 1254: case 1255: case 1256: case 1257: case 1258: case 1259: case 1260: - case 1261: case 1262: case 1263: case 1264: case 1265: case 1266: case 1267: case 1268: case 1269: case 1281: case 1282: - case 1283: case 1284: case 1285: case 1286: case 1287: case 1288: case 1289: case 1290: case 1291: case 1292: case 1293: case 1294: - case 1295: - if (((utf32) % 2 == 1)) { - lc = (utf32 - 1); - } - break; - case 314: case 315: case 316: case 317: case 318: case 319: case 320: case 321: case 322: case 323: - case 324: case 325: case 326: case 327: case 328: case 378: case 379: case 380: case 381: case 382: - case 464: case 465: case 466: case 467: case 468: case 469: case 470: case 471: case 472: case 473: case 474: case 475: - case 476: case 1218: case 1219: case 1220: case 1221: case 1222: case 1223: case 1224: case 1225: case 1226: case 1227: - case 1228: case 1229: case 1230: - if ( !(((utf32) % 2 == 1))) { - lc = (utf32 - 1); - } - break; - case 1104: case 1105: case 1106: case 1107: case 1108: case 1109: case 1110: case 1111: case 1112: case 1113: - case 1114: case 1115: case 1116: case 1117: case 1118: case 1119: - lc = (utf32 - 80); - break; - case 1377: case 1378: case 1379: case 1380: case 1381: case 1382: case 1383: case 1384: case 1385: case 1386: - case 1387: case 1388: case 1389: case 1390: case 1391: case 1392: case 1393: case 1394: case 1395: case 1396: case 1397: case 1398: - case 1399: case 1400: case 1401: case 1402: case 1403: case 1404: case 1405: case 1406: case 1407: case 1408: case 1409: case 1410: - case 1411: case 1412: case 1413: case 1414: - lc = (utf32 - 48); - break; - case 181: - lc = 924; - break; - case 255: - lc = 376; - break; - case 305: - lc = 73; - break; - case 383: - lc = 83; - break; - case 387: - lc = 386; - break; - case 389: - lc = 388; - break; - case 392: - lc = 391; - break; - case 396: - lc = 395; - break; - case 402: - lc = 401; - break; - case 405: - lc = 502; - break; - case 409: - lc = 408; - break; - case 414: - lc = 544; - break; - case 424: - lc = 423; - break; - case 429: - lc = 428; - break; - case 432: - lc = 431; - break; - case 436: - lc = 435; - break; - case 438: - lc = 437; - break; - case 441: - lc = 440; - break; - case 445: - lc = 444; - break; - case 447: - lc = 503; - break; - case 453: - lc = 452; - break; - case 454: - lc = 452; - break; - case 456: - lc = 455; - break; - case 457: - lc = 455; - break; - case 459: - lc = 458; - break; - case 460: - lc = 458; - break; - case 462: - lc = 461; - break; - case 477: - lc = 398; - break; - case 479: - lc = 478; - break; - case 498: - lc = 497; - break; - case 499: - lc = 497; - break; - case 501: - lc = 500; - break; - case 505: - lc = 504; - break; - case 595: - lc = 385; - break; - case 596: - lc = 390; - break; - case 598: - lc = 393; - break; - case 599: - lc = 394; - break; - case 601: - lc = 399; - break; - case 603: - lc = 400; - break; - case 608: - lc = 403; - break; - case 611: - lc = 404; - break; - case 616: - lc = 407; - break; - case 617: - lc = 406; - break; - case 623: - lc = 412; - break; - case 626: - lc = 413; - break; - case 629: - lc = 415; - break; - case 640: - lc = 422; - break; - case 643: - lc = 425; - break; - case 648: - lc = 430; - break; - case 650: - lc = 433; - break; - case 651: - lc = 434; - break; - case 658: - lc = 439; - break; - case 837: - lc = 921; - break; - case 940: - lc = 902; - break; - case 941: - lc = 904; - break; - case 942: - lc = 905; - break; - case 943: - lc = 906; - break; - case 962: - lc = 931; - break; - case 972: - lc = 908; - break; - case 973: - lc = 910; - break; - case 974: - lc = 911; - break; - case 976: - lc = 914; - break; - case 977: - lc = 920; - break; - case 981: - lc = 934; - break; - case 982: - lc = 928; - break; - case 1008: - lc = 922; - break; - case 1009: - lc = 929; - break; - case 1010: - lc = 1017; - break; - case 1013: - lc = 917; - break; - case 1016: - lc = 1015; - break; - case 1019: - lc = 1018; - break; - case 1273: - lc = 1272; - break; - default: - break; - } - } - return lc; -} - -/** - * Gets the UTF8 character 'utf8char' from the UTF8 string 'utf8str' from - * position 'pos' - * @param utf8str: utf8 string - * @param pos: position from where the utf8 character is copied - * (also output set as position of the next utf8 character in the utf8 string) - * @param utf8char: zero terminated utf8 character containing 1 to 4 bytes (output) -*/ -static void picobase_get_utf8char (picoos_uint8 utf8[], picoos_int32 * pos, picobase_utf8char utf8char) -{ - - int i; - int l; - - utf8char[0] = 0; - l = picobase_det_utf8_length(utf8[*pos]); - i = 0; - while ((((i < l) && (i < PICOBASE_UTF8_MAXLEN)) && (utf8[*pos] != 0))) { - utf8char[i] = utf8[*pos]; - (*pos)++; - i++; - } - utf8char[i] = 0; -} - - -picoos_uint8 picobase_get_next_utf8char(const picoos_uint8 *utf8s, - const picoos_uint32 utf8slenmax, - picoos_uint32 *pos, - picobase_utf8char utf8char) { - picoos_uint8 i; - picoos_uint8 len; - picoos_uint32 poscnt; - - utf8char[0] = 0; - len = picobase_det_utf8_length(utf8s[*pos]); - if ((((*pos) + len) > utf8slenmax) || - (len > PICOBASE_UTF8_MAXLEN)) { - return FALSE; - } - - poscnt = *pos; - i = 0; - while ((i < len) && (utf8s[poscnt] != 0)) { - utf8char[i] = utf8s[poscnt]; - poscnt++; - i++; - } - utf8char[i] = 0; - if ((i < len) && (utf8s[poscnt] == 0)) { - return FALSE; - } - *pos = poscnt; - return TRUE; -} - -picoos_uint8 picobase_get_next_utf8charpos(const picoos_uint8 *utf8s, - const picoos_uint32 utf8slenmax, - picoos_uint32 *pos) { - picoos_uint8 i; - picoos_uint8 len; - picoos_uint32 poscnt; - - len = picobase_det_utf8_length(utf8s[*pos]); - if ((((*pos) + len) > utf8slenmax) || - (len > PICOBASE_UTF8_MAXLEN)){ - return FALSE; - } - - poscnt = *pos; - i = 0; - while ((i < len) && (utf8s[poscnt] != 0)) { - poscnt++; - i++; - } - if ((i < len) && (utf8s[poscnt] == 0)) { - return FALSE; - } - *pos = poscnt; - return TRUE; -} - -picoos_uint8 picobase_get_prev_utf8char(const picoos_uint8 *utf8s, - const picoos_uint32 utf8slenmin, - picoos_uint32 *pos, - picobase_utf8char utf8char) { - picoos_uint8 i, j; - picoos_uint8 len; - picoos_uint32 poscnt; - - utf8char[0] = 0; - if ((*pos) == 0) { - return FALSE; - } - poscnt = (*pos) - 1; - i = 1; - while ((i <= PICOBASE_UTF8_MAXLEN) && (poscnt >= utf8slenmin) && - (utf8s[poscnt] != 0)) { - len = picobase_det_utf8_length(utf8s[poscnt]); - if (len == i) { - for (j = 0; j < len; j++) { - utf8char[j] = utf8s[poscnt + j]; - } - utf8char[j] = 0; - *pos = poscnt; - return TRUE; - } - i++; - poscnt--; - } - return FALSE; -} - -picoos_uint8 picobase_get_prev_utf8charpos(const picoos_uint8 *utf8s, - const picoos_uint32 utf8slenmin, - picoos_uint32 *pos) { - picoos_uint8 i; - picoos_uint8 len; - picoos_uint32 poscnt; - - if ((*pos) == 0) { - return FALSE; - } - poscnt = (*pos) - 1; - i = 1; - while ((i <= PICOBASE_UTF8_MAXLEN) && (poscnt >= utf8slenmin) && - (utf8s[poscnt] != 0)) { - len = picobase_det_utf8_length(utf8s[poscnt]); - if (len == i) { - *pos = poscnt; - return TRUE; - } - i++; - poscnt--; - } - return FALSE; -} - -/** - * Converts utf8 input to utf32 - * @param utf8[] : character encoded in utf8 - * @param done : boolean indicating the completion of the operation (FALSE: conversion not done) - * @return a single character encoded in UTF32 -*/ -static picobase_utf32 picobase_utf8_to_utf32 (picoos_uint8 utf8[], picoos_uint8 * done) -{ - (*done) = TRUE; - if ((utf8[0] < (picoos_uint8)'\200')) { - return utf8[0]; - } else if ((utf8[0] >= (picoos_uint8)'\370')) { - return 0; - } else if ((utf8[0] >= (picoos_uint8)'\360')) { - return ((((262144 * (utf8[0] % 8)) + (4096 * (utf8[1] % 64))) + (64 * (utf8[2] % 64))) + (utf8[3] % 64)); - } else if ((utf8[0] >= (picoos_uint8)'\340')) { - return (((4096 * (utf8[0] % 16)) + (64 * (utf8[1] % 64))) + (utf8[2] % 64)); - } else if ((utf8[(0)] >= (picoos_uint8)'\300')) { - return ((64 * (utf8[0] % 32)) + (utf8[1] % 64)); - } else { - (*done) = FALSE; - return 0; - } -} - -static picoos_int32 picobase_utf32_to_utf8 (picobase_utf32 utf32, picobase_utf8 utf8[], picoos_int32 utf8MaxLen, picoos_uint8 * done) -{ - picoos_int32 len; - - (*done) = TRUE; - if (utf8MaxLen >= 4) { - if (utf32 < 128) { - len = 1; - utf8[0] = utf32; - } else if (utf32 < 2048) { - len = 2; - utf8[1] = (128 + (utf32 % 64)); - utf32 = (utf32 / 64); - utf8[0] = (192 + (utf32 % 32)); - } else if (utf32 < 65536) { - len = 3; - utf8[2] = (128 + (utf32 % 64)); - utf32 = (utf32 / 64); - utf8[1] = (128 + (utf32 % 64)); - utf32 = (utf32 / 64); - utf8[0] = (224 + utf32); - } else if (utf32 < 1048576) { - len = 4; - utf8[3] = (128 + (utf32 % 64)); - utf32 = (utf32 / 64); - utf8[2] = (128 + (utf32 % 64)); - utf32 = (utf32 / 64); - utf8[1] = (128 + (utf32 % 64)); - utf32 = (utf32 / 64); - utf8[0] = (240 + utf32); - } else { - (*done) = FALSE; - return 0; - } - if (len <= (utf8MaxLen-1)) { - utf8[len] = 0; - } - return len; - } else { - (*done) = FALSE; - return 0; - } -} - - -extern picoos_int32 picobase_lowercase_utf8_str (picoos_uchar utf8str[], picoos_char lowercase[], int lowercaseMaxLen, picoos_uint8 * done) -{ - picobase_utf8char utf8char; - picoos_int32 i; - picoos_int32 j; - picoos_int32 k; - picoos_int32 l; - picobase_utf32 utf32; - picoos_uint8 done1; - - k = 0; - i = 0; - (*done) = TRUE; - while (utf8str[i] != 0) { - picobase_get_utf8char(utf8str,& i,utf8char); - utf32 = picobase_utf8_to_utf32(utf8char, & done1); - utf32 = base_utf32_lowercase(utf32); - l = picobase_utf32_to_utf8(utf32, utf8char, PICOBASE_UTF8_MAXLEN, & done1); - j = 0; - while ((j < l) && (k < (lowercaseMaxLen-1))) { - lowercase[k] = utf8char[j]; - k++; - j++; - } - *done = *done && (j == l); - } - lowercase[k] = 0; - return k; -} - - -extern picoos_int32 picobase_uppercase_utf8_str (picoos_uchar utf8str[], picoos_char uppercase[], int uppercaseMaxLen, picoos_uint8 * done) -{ - picobase_utf8char utf8char; - picoos_int32 i; - picoos_int32 j; - picoos_int32 k; - picoos_int32 l; - picobase_utf32 utf32; - picoos_uint8 done1; - - k = 0; - i = 0; - (*done) = TRUE; - while (utf8str[i] != 0) { - picobase_get_utf8char(utf8str,& i,utf8char); - utf32 = picobase_utf8_to_utf32(utf8char, & done1); - utf32 = base_utf32_uppercase(utf32); - l = picobase_utf32_to_utf8(utf32, utf8char, PICOBASE_UTF8_MAXLEN, & done1); - j = 0; - while ((j < l) && (k < (uppercaseMaxLen-1))) { - uppercase[k] = utf8char[j]; - k++; - j++; - } - *done = *done && (j == l); - } - uppercase[k] = 0; - return k; -} - - -extern picoos_bool picobase_is_utf8_uppercase (picoos_uchar utf8str[], picoos_int32 utf8strmaxlen) -{ - picobase_utf8char utf8char; - picoos_int32 i; - picoos_uint32 utf32; - picoos_bool done; - picoos_bool isUpperCase; - - isUpperCase = TRUE; - i = 0; - while (isUpperCase && (i <= utf8strmaxlen-1) && (utf8str[i] != 0)) { - picobase_get_utf8char(utf8str,& i,utf8char); - utf32 = picobase_utf8_to_utf32(utf8char,& done); - isUpperCase = isUpperCase && (utf32 == base_utf32_uppercase(utf32)); - } - return isUpperCase; -} - - -extern picoos_bool picobase_is_utf8_lowercase (picoos_uchar utf8str[], picoos_int32 utf8strmaxlen) -{ - picobase_utf8char utf8char; - picoos_int32 i; - picoos_uint32 utf32; - picoos_bool done; - picoos_bool isLowerCase; - - isLowerCase = TRUE; - i = 0; - while (isLowerCase && (i <= utf8strmaxlen-1) && (utf8str[i] != 0)) { - picobase_get_utf8char(utf8str,& i,utf8char); - utf32 = picobase_utf8_to_utf32(utf8char,& done); - isLowerCase = isLowerCase && (utf32 == base_utf32_lowercase(utf32)); - } - return isLowerCase; -} - - -#ifdef __cplusplus -} -#endif - - - -/* end */ diff --git a/lib/picobase.h b/lib/picobase.h deleted file mode 100644 index 1c384e1..0000000 --- a/lib/picobase.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 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 picobase.h - * - * base functionality - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#ifndef PICOBASE_H_ -#define PICOBASE_H_ - -#include "picoos.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -/* maximum number of bytes of an UTF8 character */ -#define PICOBASE_UTF8_MAXLEN 4 - -typedef picoos_uint8 picobase_utf8char[PICOBASE_UTF8_MAXLEN+1]; /* always zero terminated */ -typedef picoos_uint8 picobase_utf8; -typedef picoos_uint16 picobase_utf16; -typedef picoos_uint32 picobase_utf32; - -/* ***************************************************************/ -/* Unicode UTF8 functions */ -/* ***************************************************************/ - -/** - * Determines the number of UTF8 characters contained in - * the UTF8 string 'utf8str' of maximum length maxlen (in bytes) - * @param utf8str : a string encoded in UTF8 - * @param maxlen : max length (in bytes) accessible in utf8str - * @return >=0 : length of the UTF8 string in number of UTF8 characters - * up to the first '\0' or maxlen - * @return <0 : not starting with a valid UTF8 character - * @remarks strict implementation, not allowing invalid utf8 -*/ -picoos_int32 picobase_utf8_length(const picoos_uint8 *utf8str, - const picoos_uint16 maxlen); - - -/** - * Determines the number of bytes an UTF8 character used based - * on the first byte of the UTF8 character - * @param firstchar: the first (and maybe only) byte of an UTF8 character - * @return positive value in {1,4} : number of bytes of the UTF8 character - * @return 0 :if not a valid UTF8 character start - * @remarks strict implementation, not allowing invalid utf8 -*/ -/* picoos_uint8 picobase_det_utf8_length(const picoos_uint8 firstchar); */ - -#define picobase_det_utf8_length(x) ( ((x)<(picoos_uint8)'\200')?1:(((x)>=(picoos_uint8)'\370')?0:(((x)>=(picoos_uint8)'\360')?4:(((x)>=(picoos_uint8)'\340')?3:(((x)>=(picoos_uint8)'\300')?2:0)))) ) - -/** - * Converts the content of 'utf8str' to lowercase and stores it on 'lowercase' - * on the first byte of the UTF8 character - * @param utf8str : utf8 string - * @param lowercaseMaxLen : maximal number of bytes available in 'lowercase' - * @param lowercase : string converted to lowercase (output) - * @param done : flag to report success/failure of the operation (output) - * @return TRUE if successful, FALSE otherwise -*/ -picoos_int32 picobase_lowercase_utf8_str (picoos_uchar utf8str[], picoos_char lowercase[], picoos_int32 lowercaseMaxLen, picoos_uint8 * done); - -/** - * Converts the content of 'utf8str' to upperrcase and stores it on 'uppercase' - * @param utf8str : utf8 string - * @param uppercase : string converted to uppercase (output) - * @param uppercaseMaxLen : maximal number of bytes available in 'uppercase' - * @param done : flag to report success/failure of the operation (output) - * @return TRUE if successful, FALSE otherwise -*/ -picoos_int32 picobase_uppercase_utf8_str (picoos_uchar utf8str[], picoos_char uppercase[], int uppercaseMaxLen, picoos_uint8 * done); - -/** - * Gets next UTF8 character 'utf8char' from the UTF8 string - * 'utf8s' starting at position 'pos' - * @param utf8s : UTF8 string - * @param utf8slenmax : max length accessible in utf8s - * @param pos : position from where the UTF8 character is checked and copied - * (set also as output to the position directly following the UTF8 char) - * @param utf8char : zero terminated UTF8 character containing 1 to 4 bytes (output) - * @return TRUE if okay - * @return FALSE if there is no valid UTF8 char or no more UTF8 char available within utf8len -*/ -picoos_uint8 picobase_get_next_utf8char(const picoos_uint8 *utf8s, - const picoos_uint32 utf8slenmax, - picoos_uint32 *pos, - picobase_utf8char utf8char); - -/** - * Same as picobase_get_next_utf8char - * without copying the char to utf8char -*/ -picoos_uint8 picobase_get_next_utf8charpos(const picoos_uint8 *utf8s, - const picoos_uint32 utf8slenmax, - picoos_uint32 *pos); - -/** - * Gets previous UTF8 character 'utf8char' from the UTF8 string - * 'utf8s' starting the backward search at position 'pos-1' - * @param utf8s : UTF8 string - * @param utf8slenmin : min length accessible in utf8s - * @param pos : the search for the prev UTF8 char starts at [pos-1] - * (set also as output to the start position of the prev UTF8 character) - * @param utf8char : zero terminated UTF8 character containing 1 to 4 bytes (output) - * @return TRUE if okay - * @return FALSE if there is no valid UTF8 char preceeding pos or no more UTF8 char available within utf8len -*/ -picoos_uint8 picobase_get_prev_utf8char(const picoos_uint8 *utf8s, - const picoos_uint32 utf8slenmin, - picoos_uint32 *pos, - picobase_utf8char utf8char); - -/** - * Same as picobase_get_prev_utf8char - * without copying the char to utf8char -*/ -picoos_uint8 picobase_get_prev_utf8charpos(const picoos_uint8 *utf8s, - const picoos_uint32 utf8slenmin, - picoos_uint32 *pos); - - -/** - * returns TRUE if the input string is UTF8 and uppercase - * @param str : UTF8 string - * @param strmaxlen : max length for the input string - * @return TRUE if string is UTF8 and uppercase - * @return FALSE otherwise -*/ -extern picoos_bool picobase_is_utf8_uppercase (picoos_uchar str[], picoos_int32 strmaxlen); - -/** - * returns TRUE if the input string is UTF8 and lowercase - * @param str : UTF8 string - * @param strmaxlen : max length for the input string - * @return TRUE if string is UTF8 and lowercase - * @return FALSE otherwise -*/ -extern picoos_bool picobase_is_utf8_lowercase (picoos_uchar str[], picoos_int32 strmaxlen); - -#ifdef __cplusplus -} -#endif - -#endif /*PICOBASE_H_*/ diff --git a/lib/picocep.c b/lib/picocep.c deleted file mode 100644 index 2510c13..0000000 --- a/lib/picocep.c +++ /dev/null @@ -1,1965 +0,0 @@ -/* - * 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 picocep.c - * - * Phonetic to Acoustic Mapping PU - Implementation - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -/** - * @addtogroup picocep - * Pico Cepstral Smoothing \n - * - itemtype, iteminfo1, iteminfo2, content -> TYPE(INFO1,INFO2)content - in the following - - items input - - processed: - - - PHONE(PHONID,StatesPerPhone)[FramesPerState|f0Index|mgcIndex]{StatesPerPhone} - - (StatesPerPhone is a constant (5) for the time being. The content size is therfore allways 34) - - unprocessed: - - all other item types are forwarded through the PU without modification - - items output - - FRAME(PHONID,F0 [?])ceps{25} - - each PHONE produces at least StatesPerPhone FRAME (if each state has FramesPerState == 1), but usually more. - - minimal input size (before processing starts) - - other limitations - - */ -#include "picodefs.h" -#include "picoos.h" -#include "picodbg.h" -#include "picodata.h" -#include "picokpdf.h" -#include "picodsp.h" -#include "picocep.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -#define PICOCEP_MAXWINLEN 10000 /* maximum number of frames that can be smoothed, i.e. maximum sentence length */ -#define PICOCEP_MSGSTR_SIZE 32 -#define PICOCEP_IN_BUFF_SIZE PICODATA_BUFSIZE_DEFAULT - -#define PICOCEP_OUT_DATA_FORMAT PICODATA_ITEMINFO1_FRAME_PAR_DATA_FORMAT_FIXED /* we output coefficients as fixed point values */ - -#define PICOCEP_STEPSTATE_COLLECT 0 -#define PICOCEP_STEPSTATE_PROCESS_PARSE 1 -#define PICOCEP_STEPSTATE_PROCESS_SMOOTH 2 -#define PICOCEP_STEPSTATE_PROCESS_FRAME 3 -#define PICOCEP_STEPSTATE_FEED 4 - -#define PICOCEP_LFZINVPOW 31 /* cannot be higher than 31 because 1< 2^16 */ - picoos_uint8 * outVoiced; - picoos_uint16 outVoicedReadPos, outVoicedWritePos; - - /*---------------------- LINGWARE related data -------------------*/ - /* pdflfz knowledge base */ - picokpdf_PdfMUL pdflfz, pdfmgc; - -} cep_subobj_t; - -/** - * picocep_highestBit - * @brief find the highest non-zero bit in input x - * @remarks this may be implemented by comparing x to powers of 2 - * or instead of calling this function perform multiplication - * and consult overflow register if available on target - * @note implemented as a series of macros - */ - -#define picocep_highestBitNZ(x) (x>=POW17?(x>=POW25?(x>=POW29?(x>=POW31?31:(x>=POW30?30:29)):(x>=POW27?(x>=POW28?28:27):(x>=POW26?26:25))):(x>=POW21?(x>=POW23?(x>=POW24?24:23):(x>=POW22?22:21)):(x>=POW19?(x>=POW20?20:19):(x>=POW18?18:17)))):(x>=POW9?(x>=POW13?(x>=POW15?(x>=POW16?16:15):(x>=POW14?14:13)):(x>=POW11?(x>=POW12?12:11):(x>=POW10?10:9))):(x>=POW5?(x>=POW7?(x>=POW8?8:7):(x>=POW6?6:5)):(x>=POW3?(x>=POW4?4:3):(x>=POW2?2:1))))) -#define picocep_highestBitU(x) (x==0?0:picocep_highestBitNZ(x)) -#define picocep_highestBitS(x,zz) (x==0?0:(x<0?((zz)=(-x),picocep_highestBitNZ(zz)):picocep_highestBitNZ(x))) - -/* ------------------------------------------------------------------------------ - Internal function definitions - ---------------------------------------------------------------------------------*/ - -static void initSmoothing(cep_subobj_t * cep); - -static picoos_int32 getFromPdf(picokpdf_PdfMUL pdf, picoos_uint32 vecstart, - picoos_uint8 cepnum, picocep_WantMeanOrIvar_t wantMeanOrIvar, - picocep_WantStaticOrDelta_t wantStaticOrDeltax); - -static void invMatrix(cep_subobj_t * cep, picoos_uint16 N, - picoos_int16 *smoothcep, picoos_uint8 cepnum, - picokpdf_PdfMUL pdf, picoos_uint8 invpow, picoos_uint8 invDoubleDec); - -static picoos_uint8 makeWUWandWUm(cep_subobj_t * cep, picokpdf_PdfMUL pdf, - picoos_uint16 *indices, picoos_uint16 b, picoos_uint16 N, - picoos_uint8 cepnum); - -static void getDirect(picokpdf_PdfMUL pdf, picoos_uint16 *indices, - picoos_uint16 activeEndPos, - picoos_uint8 cepnum, picoos_int16 *smoothcep); - -static void getVoiced(picokpdf_PdfMUL pdf, picoos_uint16 *indices, - picoos_uint16 activeEndPos, - picoos_uint8 *smoothcep); - -static picoos_uint16 get_pi_uint16(picoos_uint8 * buf, picoos_uint16 *pos); - -static void treat_phone(cep_subobj_t * cep, picodata_itemhead_t * ihead); - -static picoos_uint8 forwardingItem(picodata_itemhead_t * ihead); - -static picodata_step_result_t cepStep(register picodata_ProcessingUnit this, - picoos_int16 mode, picoos_uint16 * numBytesOutput); - -/* -------------------------------------------- - * generic PU management - * -------------------------------------------- - */ - -/** - * initialization of a cep PU (processing unit) - * @param this : handle to a cep PU struct - * @return PICO_OK : init succeded - * @return PICO_ERR_OTHER : init failed - * @callgraph - * @callergraph - */ -static pico_status_t cepInitialize(register picodata_ProcessingUnit this) -{ - /*pico_status_t nRes;*/ - cep_subobj_t * cep; - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - cep = (cep_subobj_t *) this->subObj; - /* inBuf */ - cep->inBufSize = PICODATA_BUFSIZE_CEP; - cep->inReadPos = 0; - cep->inWritePos = 0; - /* headx and cbuf */ - cep->headxBottom = cep->headxWritePos = 0; - cep->cbufBufSize = PICOCEP_MAXSIZE_CBUF; - cep->cbufWritePos = 0; - /* outBuf */ - cep->outBufSize = PICODATA_MAX_ITEMSIZE; - cep->outReadPos = 0; - cep->outWritePos = 0; - /* indices* */ - cep->indexReadPos = 0; - cep->indexWritePos = 0; - /* outCep, outF0, outVoiced */ - cep->outXCepReadPos = 0; - cep->outXCepWritePos = 0; - cep->outVoicedReadPos = 0; - cep->outVoicedWritePos = 0; - cep->outF0ReadPos = 0; - cep->outF0WritePos = 0; - - cep->needMoreInput = 0; - cep->inIgnoreState = 0; - cep->sentenceEnd = FALSE; - cep->procState = PICOCEP_STEPSTATE_COLLECT; - - cep->nNumFrames = 0; - - /*----------------------------------------------------------------- - * MANAGE Item I/O control management - ------------------------------------------------------------------*/ - cep->activeEndPos = PICOCEP_MAXWINLEN; - - /* kb pdflfz */ - cep->pdflfz = picokpdf_getPdfMUL( - this->voice->kbArray[PICOKNOW_KBID_PDF_LFZ]); - - /* kb pdfmgc */ - cep->pdfmgc = picokpdf_getPdfMUL( - this->voice->kbArray[PICOKNOW_KBID_PDF_MGC]); - - /* kb tab phones */ - /* cep->phones = - picoktab_getPhones(this->voice->kbArray[PICOKNOW_KBID_TAB_PHONES]); */ - - /*---------------------- other working variables ---------------------------*/ - /* define the (constant) FRAME_PAR item header */ - cep->framehead.type = PICODATA_ITEM_FRAME_PAR; - cep->framehead.info1 = PICOCEP_OUT_DATA_FORMAT; - cep->framehead.info2 = cep->pdfmgc->ceporder; - cep->framehead.len = sizeof(picoos_uint16) + (cep->framehead.info2 + 4) - * sizeof(picoos_uint16); - - /* constants used in makeWUWandWUm */ - initSmoothing(cep); - - cep->scmeanpowLFZ = cep->pdflfz->bigpow - cep->pdflfz->meanpow; - cep->scmeanpowMGC = cep->pdfmgc->bigpow - cep->pdfmgc->meanpow; - - cep->scmeanLFZ = (1 << (picoos_uint32) cep->scmeanpowLFZ); - - cep->scmeanMGC = (1 << (picoos_uint32) cep->scmeanpowMGC); - - return PICO_OK; -}/*cepInitialize*/ - -/** - * termination of a cep PU (processing unit) - * @param this : handle to a cep PU struct - * @return PICO_OK : termination succeded - * @return PICO_ERR_OTHER : termination failed - * @callgraph - * @callergraph - */ -static pico_status_t cepTerminate(register picodata_ProcessingUnit this) -{ - return PICO_OK; -} - -/** - * deallocation of a cep PU internal sub object - * @param this : handle to a cep PU struct - * @param mm : handle of the engine memory manager - * @return PICO_OK : deallocation succeded - * @return PICO_ERR_OTHER : deallocation failed - * @callgraph - * @callergraph - */ -static pico_status_t cepSubObjDeallocate(register picodata_ProcessingUnit this, - picoos_MemoryManager mm) -{ - - mm = mm; /* avoid warning "var not used in this function"*/ -#if defined(PICO_DEVEL_MODE) - printf("number of long mult is %d, number of short mult is %i\n",numlongmult,numshortmult); -#else - PICODBG_INFO_MSG(("number of long mult is %d, number of short mult is %i\n",numlongmult,numshortmult)); -#endif - if (NULL != this) { - cep_subobj_t * cep = (cep_subobj_t *) this->subObj; - picoos_deallocate(this->common->mm, (void *) &cep->outXCep); - picoos_deallocate(this->common->mm, (void *) &cep->outVoiced); - picoos_deallocate(this->common->mm, (void *) &cep->outF0); - picoos_deallocate(this->common->mm, (void *) &this->subObj); - } - return PICO_OK; -} - -/** - * creates a new cep PU (processing unit) - * @param mm : engine memory manager object pointer - * @param common : engine common object pointer - * @param cbIn : PU input buffer - * @param cbOut : PU output buffer - * @param voice : the voice descriptor object - * @return a valid PU handle if creation succeded - * @return NULL : creation failed - * @callgraph - * @callergraph - */ -picodata_ProcessingUnit picocep_newCepUnit(picoos_MemoryManager mm, - picoos_Common common, picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, picorsrc_Voice voice) -{ - picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, - cbOut, voice); - cep_subobj_t * cep; - - if (this == NULL) { - return NULL; - } - this->initialize = cepInitialize; - - PICODBG_DEBUG(("set this->step to cepStep")); - - this->step = cepStep; - this->terminate = cepTerminate; - this->subDeallocate = cepSubObjDeallocate; - this->subObj = picoos_allocate(mm, sizeof(cep_subobj_t)); - - cep = (cep_subobj_t *) this->subObj; - - if (this->subObj == NULL) { - picoos_deallocate(mm, (void*) &this); - return NULL; - }; - - /* allocate output coeeficient buffers */ - cep->outF0 = (picoos_int16 *) picoos_allocate(this->common->mm, - PICOCEP_MAXWINLEN * PICOKPDF_MAX_MUL_LFZ_CEPORDER - * sizeof(picoos_int16)); - cep->outXCep = (picoos_int16 *) picoos_allocate(this->common->mm, - PICOCEP_MAXWINLEN * PICOKPDF_MAX_MUL_MGC_CEPORDER - * sizeof(picoos_int16)); - cep->outVoiced = (picoos_uint8 *) picoos_allocate(this->common->mm, - PICOCEP_MAXWINLEN * sizeof(picoos_uint8)); - - if ((NULL == cep->outF0) || (NULL == cep->outXCep) || (NULL - == cep->outVoiced)) { - picoos_deallocate(this->common->mm, (void *) &(cep->outF0)); - picoos_deallocate(this->common->mm, (void *) &(cep->outXCep)); - picoos_deallocate(this->common->mm, (void *) &(cep->outVoiced)); - picoos_deallocate(mm, (void*) &cep); - picoos_deallocate(mm, (void*) &this); - return NULL; - } - cepInitialize(this); - - return this; -}/*picocep_newCepUnit*/ - -/* -------------------------------------------- - * processing and internal functions - * -------------------------------------------- - */ - -/** - * multiply by 1< 0) { - b -= 1; /* maximum positive value */ - }PICODBG_WARN(("picocep_fixptmultpow warning: overflow in fixed point multiplication %i*1<<%i. Clipping to %i\n", a, pow, b)); - } - return b; -} - -/** - * divide by 1< 0) { - a = (a + big) >> pow; - } else { - a = -1 * ((-1 * a + big) >> pow); - } - - return a; -} - -/** - * fixed point multiplication of x and y for large values of x or y or both - * @param x,y : operands 1 & 2, in fixed point S:M:N representation - * @param bigpow (int) : normalization factor=2**N, where N=number of binary decimal digits - * @param invDoubleDec : boolean indicating that x has double decimal size. - * do extra division by 1<= 0) { - a = x >> bigpow; - b = x - (a << bigpow); - } else { - a = -1 * ((x * -1) >> bigpow); /* most significant 2 bytes of x */ - b = x - (a << bigpow); - } - - /* least significant 2 bytes of x i.e. x modulo big */ - /* c = floor(y/big); */ - if (y >= 0) { - c = y >> bigpow; - d = y - (c << bigpow); - } else { - c = -1 * ((y * -1) >> bigpow); - d = y - (c << bigpow); - } - - if (invDoubleDec == 1) { - e = a * d + b * c + picocep_fixptdivpow(b * d, bigpow); - z = a * c + picocep_fixptdivpow(e, bigpow); - } else { - z = ((a * c) << bigpow) + (a * d + b * c) + picocep_fixptdivpow(b * d, - bigpow); /* 4 mult and 3 add instead of 1 mult. */ - } - - return z; -} - -/** - * fixed point multiplication of x and y - * @param x,y : operands 1 & 2, in fixed point S:M:N representation - * @param bigpow (int) : normalization factor=2**N, where N=number of binary decimal digits - * @param invDoubleDec : boolean indicating that x has double decimal size. - * do extra division by 1< 31 + pow) { - PICODBG_WARN(("picocep_fixptmult warning: overflow in fixed point multiplication %i*%i, multsz = %i, pow = %i, decrease bigpow\n", x, y, multsz, pow)); - } -#endif - z = picocep_fixptmultdouble(x, y, bigpow, invDoubleDec); /* perform long multiplication for large x and y */ -#if defined(PICO_DEBUG) - numlongmult++; /* keep track of number of long multiplications */ -#endif - } - return z; -}/* picocep_fixptmult */ - -/** - * fixed point ^division of a vs b - * @param a,b : operands 1 & 2, in fixed point S:M:N representation - * @param bigpow (int) : normalization factor=2**N, where N=number of binary decimal digits - * @return z(int) : result, in fixed point S:M:N representation - * Notes - * - input and output values are 32 bit signed integers - * meant to represent a S.M.N encoding of a floating point value where - * - S : 1 sign bit - * - M : number of binary integer digits (M=32-1-N) - * - N : number of binary decimal digits (N=log2(big)) - * - standard implementation of division by iteratively calculating - * the remainder and setting corresponding bit - * calculate integer part by integer division (DIV), - * then add X bits of precision in decimal part - * @callgraph - * @callergraph - */ -static picoos_int32 picocep_fixptdiv(picoos_int32 a, picoos_int32 b, - picoos_uint8 bigpow) -{ - picoos_int32 r, c, f, h, stop; - r = (a < 0) ? -a : a; /* take absolute value; b is already guaranteed to be positive in smoothing operation */ - if (r == 0) { - return 0; - } - c = 0; - stop = 0; - - /* can speed up slightly by setting stop = 2 => slightly less precision */ - h = r / b; /* in first loop h can be multiple bits, after first loop h can only be 0 or 1 */ - /* faster implementation on target by using comparison instead of DIV? */ - /* For our LDL even in first loop h <= 1, but not in backward step */ - c = c + (h << bigpow); /* after first loop simply set bit */ - r = r - h * b; /* corresponds to modulo operation */ - bigpow--; - r <<= 1; - - while ((bigpow > stop) && (r != 0)) { /* calculate bigpow bits after fixed point */ - /* can speed up slightly by setting stop = 2 => slightly less precision */ - if (r >= b) { - c += (1 << bigpow); /* after first loop simply set bit */ - r -= b; /* corresponds to modulo operation */ - } - bigpow--; - r <<= 1; - } - - if (r != 0) { - f = r + (b >> 1); - if (f >= b) { - if (f >= b + b) { - c += 2; - } else { - c++; - } - } - } - /* final step: do rounding (experimentally improves accuracy for our problem) */ - c = (a >= 0) ? c : -c; /* b is guaranteed to be positive because corresponds to diag0 */ - return c; -}/* picocep_fixptdiv */ - -/** - * perform inversion of diagonal element of WUW matrix - * @param d : diagonal element to be inverted - * @param rowscpow (int) : fixed point base for each dimension of the vectors stored in the database - * @param bigpow (int) : fixed point base used during cepstral smoothing - * @param invpow : fixed point base of inverted pivot elements - * @return inverted pivot element - * @note - * - d is guaranteed positive - * @callgraph - * @callergraph - */ -static picoos_int32 picocep_fixptInvDiagEle(picoos_uint32 d, - picoos_uint8* rowscpow, picoos_uint8 bigpow, picoos_uint8 invpow) -{ - picoos_uint32 r, b, c, h, f, stop; - picoos_uint8 dlen; - /* picoos_int32 zz; */ - c = 0; - stop = 0; - - dlen = picocep_highestBitU(d); - if (invpow + bigpow > 30 + dlen) { /* c must be < 2^32, hence d which is >= 2^(dlen-1) must be > 2^(invpow+bigpow-32), or invpow+bigpow must be <= dlen+30*/ - *rowscpow = invpow + bigpow - 30 - dlen;PICODBG_DEBUG(("input to picocep_fixptInvDiagEle is %i <= 1<<%i = 1< 0) { - c += (h << bigpow); - r -= h * b; - } - bigpow--; - r <<= 1; - - /* loop */ - while ((bigpow > stop) && (r != 0)) { - if (r >= b) { - c += (1 << bigpow); - r -= b; - } - bigpow--; - r <<= 1; - } - - if (r != 0) { - f = r + (b >> 1); - if (f >= b) { - if (f >= b + b) { - c += 2; - } else { - c++; - } - } - } - - return c; -}/* picocep_fixptInvDiagEle */ - -/** - * perform division of two operands a and b by multiplication by inverse of b - * @param a (int32) : operand 1 in fixed point S:M:N representation - * @param invb(uint32) : inverse of operand b, in fixed point P:Q representation (sign is positive) - * @param bigpow(uint8) : N = bigpow when invDoubleDec==0, else N = 2*bigpow - * @param invpow(uint8) : Q = invpow = number of binary decimal digits for invb - * @param invDoubleDec : boolean to indicate that a and the return value c have 2*N binary decimal digits instead of N - * @return c(int32) : result in fixed point S:v:w where w = 2*N when invDoubleDec == 1 - * @note Calls - * - picocep_fixptmult - * @callgraph - * @callergraph - */ -static picoos_int32 picocep_fixptinv(picoos_int32 a, picoos_uint32 invb, - picoos_uint8 bigpow, picoos_uint8 invpow, picoos_uint8 invDoubleDec) -{ - picoos_int32 c; - picoos_int8 normpow; - - c = picocep_fixptmult(a, invb, bigpow, invDoubleDec); - - /* if invDoubleDec==0, picocep_fixptmult assumes a and invb are in base 1< normfactor = big^3/big2 - */ - if (invDoubleDec == 1) { - normpow = 3 * bigpow; - } else { - normpow = bigpow; - } - if (normpow < invpow) { - /* divide with rounding */ - c = picocep_fixptdivpow(c, invpow - normpow); - } else { - c = picocep_fixptmultpow(c, normpow - invpow); - } - return c; -} - -/** - * initializes the coefficients to calculate delta and delta-delta values and the squares of the coefficients - * @param cep : the CEP PU sub-object handle - * @callgraph - * @callergraph - */ -static void initSmoothing(cep_subobj_t * cep) -{ - cep->xi[0] = 1; - cep->xi[1] = -1; - cep->xi[2] = 2; - cep->xi[3] = -4; - cep->xi[4] = 2; - cep->xsqi[0] = 1; - cep->xsqi[1] = 1; - cep->xsqi[2] = 4; - cep->xsqi[3] = 16; - cep->xsqi[4] = 4; - - cep->x1[0] = -1; - cep->x1[1] = 2; - cep->xsq1[0] = 1; - cep->xsq1[1] = 4; - - cep->x2[0] = -1; - cep->x2[1] = -4; - cep->x2[2] = 2; - cep->xsq2[0] = 1; - cep->xsq2[1] = 16; - cep->xsq2[2] = 4; - - cep->xm[0] = 1; - cep->xm[1] = 2; - cep->xm[2] = -4; - cep->xsqm[0] = 1; - cep->xsqm[1] = 4; - cep->xsqm[2] = 16; - - cep->xn[0] = 1; - cep->xn[1] = 2; - cep->xsqn[0] = 1; - cep->xsqn[1] = 4; -} - -/** - * matrix inversion - * @param cep : PU sub object pointer - * @param N - * @param smoothcep : pointer to picoos_int16, sequence of smoothed cepstral vectors - * @param cepnum : cepstral dimension to be treated - * @param pdf : pdf resource - * @param invpow : fixed point base for inverse - * @param invDoubleDec : boolean indicating that result of picocep_fixptinv has fixed point base 2*bigpow - * picocep_fixptmult absorbs double decimal size by dividing its result by extra factor big - * @return void - * @remarks diag0, diag1, diag2, WUm, invdiag0 globals needed in this function (object members in pico) - * @callgraph - * @callergraph - */ -static void invMatrix(cep_subobj_t * cep, picoos_uint16 N, - picoos_int16 *smoothcep, picoos_uint8 cepnum, - picokpdf_PdfMUL pdf, picoos_uint8 invpow, picoos_uint8 invDoubleDec) -{ - picoos_int32 j, v1, v2, h; - picoos_uint32 k; - picoos_uint8 rowscpow, prevrowscpow; - picoos_uint8 ceporder = pdf->ceporder; - picoos_uint8 bigpow = pdf->bigpow; - picoos_uint8 meanpow = pdf->meanpow; - - /* LDL factorization */ - prevrowscpow = 0; - cep->invdiag0[0] = picocep_fixptInvDiagEle(cep->diag0[0], &rowscpow, - bigpow, invpow); /* inverse has fixed point basis 1<diag1[0] = picocep_fixptinv((cep->diag1[0]) << rowscpow, - cep->invdiag0[0], bigpow, invpow, invDoubleDec); /* perform division via inverse */ - cep->diag2[0] = picocep_fixptinv((cep->diag2[0]) << rowscpow, - cep->invdiag0[0], bigpow, invpow, invDoubleDec); - cep->WUm[0] = (cep->WUm[0]) << rowscpow; /* if diag0 too low, multiply LHS and RHS of row in matrix equation by 1<WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag1[j - 1], - cep->WUm[j - 1], bigpow, invDoubleDec); - if (j > 1) { - cep->WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag2[j - 2], - cep->WUm[j - 2], bigpow, invDoubleDec); - } - - /* update row j */ - v1 = picocep_fixptmult((cep->diag1[j - 1]) / (1 << rowscpow), - cep->diag0[j - 1], bigpow, invDoubleDec); /* undo scaling by 1<diag0[j] = cep->diag0[j] - picocep_fixptmult(cep->diag1[j - 1], - v1, bigpow, invDoubleDec); - if (j > 1) { - v2 = picocep_fixptmult((cep->diag2[j - 2]) / (1 << prevrowscpow), - cep->diag0[j - 2], bigpow, invDoubleDec); /* undo scaling by 1<diag0[j] = cep->diag0[j] - picocep_fixptmult( - cep->diag2[j - 2], v2, bigpow, invDoubleDec); - } - prevrowscpow = rowscpow; - cep->invdiag0[j] = picocep_fixptInvDiagEle(cep->diag0[j], &rowscpow, - bigpow, invpow); /* inverse has fixed point basis 1<WUm[j] = (cep->WUm[j]) << rowscpow; - if (j < N - 1) { - h = picocep_fixptmult(cep->diag2[j - 1], v1, bigpow, invDoubleDec); - cep->diag1[j] = picocep_fixptinv((cep->diag1[j] - h) << rowscpow, - cep->invdiag0[j], bigpow, invpow, invDoubleDec); /* eliminate column j below pivot */ - } - if (j < N - 2) { - cep->diag2[j] = picocep_fixptinv((cep->diag2[j]) << rowscpow, - cep->invdiag0[j], bigpow, invpow, invDoubleDec); /* eliminate column j below pivot */ - } - } - - /* divide all entries of WUm by diag0 */ - for (j = 0; j < N; j++) { - cep->WUm[j] = picocep_fixptinv(cep->WUm[j], cep->invdiag0[j], bigpow, - invpow, invDoubleDec); - if (invDoubleDec == 1) { - cep->WUm[j] = picocep_fixptdivpow(cep->WUm[j], bigpow); - } - } - - /* backward substitution */ - for (j = N - 2; j >= 0; j--) { - cep->WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag1[j], cep->WUm[j - + 1], bigpow, invDoubleDec); - if (j < N - 2) { - cep->WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag2[j], - cep->WUm[j + 2], bigpow, invDoubleDec); - } - } - /* copy N frames into smoothcep (only for coeff # "cepnum") */ - /* coefficients normalized to occupy short; for correct waveform energy, divide by (1<<(bigpow-meanpow)) then convert e.g. to picoos_single */ - k = cepnum; - for (j = 0; j < N; j++) { - smoothcep[k] = (picoos_int16)(cep->WUm[j]/(1< At x W x A - * @remarks WUm --> At x W x b - * @callgraph - * @callergraph - */ -static picoos_uint8 makeWUWandWUm(cep_subobj_t * cep, picokpdf_PdfMUL pdf, - picoos_uint16 *indices, picoos_uint16 b, picoos_uint16 N, - picoos_uint8 cepnum) -{ - picoos_uint16 Id[2], Idd[3]; - /*picoos_uint32 vecstart, k;*/ - picoos_uint32 vecstart; - picoos_int32 *x = NULL, *xsq = NULL; - picoos_int32 mean, ivar; - picoos_uint16 i, j, numd = 0, numdd = 0; - picoos_uint8 vecsize = pdf->vecsize; - picoos_int32 prev_WUm, prev_diag0, prev_diag1, prev_diag1_1, prev_diag2; - - prev_WUm = prev_diag0 = prev_diag1 = prev_diag1_1 = prev_diag2 = 0; - for (i = 0; i < N; i++) { - - if ((1 < i) && (i < N - 2)) { - x = cep->xi; - xsq = cep->xsqi; - numd = 2; - numdd = 3; - Id[0] = Idd[0] = i - 1; - Id[1] = Idd[2] = i + 1; - Idd[1] = i; - } else if (i == 0) { - x = cep->x1; - xsq = cep->xsq1; - numd = numdd = 1; - Id[0] = Idd[0] = 1; - } else if (i == 1) { - x = cep->x2; - xsq = cep->xsq2; - numd = 1; - numdd = 2; - Id[0] = Idd[1] = 2; - Idd[0] = 1; - } else if (i == N - 2) { - x = cep->xm; - xsq = cep->xsqm; - numd = 1; - numdd = 2; - Id[0] = Idd[0] = N - 3; - Idd[1] = N - 2; - } else if (i == N - 1) { - x = cep->xn; - xsq = cep->xsqn; - numd = numdd = 1; - Id[0] = Idd[0] = N - 2; - } - - /* process static means and static inverse variances */ - if (i > 0 && indices[b + i] == indices[b + i - 1]) { - cep->diag0[i] = prev_diag0; - cep->WUm[i] = prev_WUm; - } else { - vecstart = indices[b + i] * vecsize; - ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, - PICOCEP_WANTSTATIC); - prev_diag0 = cep->diag0[i] = ivar << 2; /* multiply ivar by 4 (4 used to be first entry of xsq) */ - mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN, - PICOCEP_WANTSTATIC); - prev_WUm = cep->WUm[i] = mean << 1; /* multiply mean by 2 (2 used to be first entry of x) */ - } - - /* process delta means and delta inverse variances */ - for (j = 0; j < numd; j++) { - vecstart = indices[b + Id[j]] * vecsize; - ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, - PICOCEP_WANTDELTA); - cep->diag0[i] += xsq[j] * ivar; - - mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN, - PICOCEP_WANTDELTA); - if (mean != 0) { - cep->WUm[i] += x[j] * mean; - } - } - - /* process delta delta means and delta delta inverse variances */ - for (j = 0; j < numdd; j++) { - vecstart = indices[b + Idd[j]] * vecsize; - ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, - PICOCEP_WANTDELTA2); - cep->diag0[i] += xsq[numd + j] * ivar; - - mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN, - PICOCEP_WANTDELTA2); - if (mean != 0) { - cep->WUm[i] += x[numd + j] * mean; - } - } - - cep->diag0[i] = (cep->diag0[i] + 2) / 4; /* long DIV with rounding */ - cep->WUm[i] = (cep->WUm[i] + 1) / 2; /* long DIV with rounding */ - - /* calculate diag(A,-1) */ - if (i < N - 1) { - if (i < N - 2) { - if (i > 0 && indices[b + i + 1] == indices[b + i]) { - cep->diag1[i] = prev_diag1; - } else { - vecstart = indices[b + i + 1] * vecsize; - /* - diag1[i] = getFromPdf(pdf, vecstart, numvuv, ceporder, numdeltas, cepnum, - bigpow, meanpowUm, ivarpow, PICOCEP_WANTIVAR, PICOCEP_WANTDELTA2); - */ - prev_diag1 = cep->diag1[i] = getFromPdf(pdf, vecstart, - cepnum, PICOCEP_WANTIVAR, PICOCEP_WANTDELTA2); - } - /* - k = vecstart +pdf->numvuv+pdf->ceporder*2 + pdf->numdeltas*3 + - pdf->ceporder*2 +cepnum; - cep->diag1[i] = (picoos_int32)(pdf->content[k]) << pdf->bigpow; - */ - } else { - cep->diag1[i] = 0; - } - if (i > 0) { - if (i > 1 && indices[b + i] == indices[b + i - 1]) { - cep->diag1[i] += prev_diag1_1; - } else { - vecstart = indices[b + i] * vecsize; - /* - k = vecstart + pdf->numvuv + pdf->ceporder * 2 + pdf->numdeltas * 3 + pdf->ceporder * 2 + cepnum; - cep->diag1[i] += (picoos_int32)(pdf->content[k]) << pdf->bigpow; */ - /* cepnum'th delta delta ivar */ - - prev_diag1_1 = getFromPdf(pdf, vecstart, cepnum, - PICOCEP_WANTIVAR, PICOCEP_WANTDELTA2); - cep->diag1[i] += prev_diag1_1; - } - - } /*i < N-1 */ - cep->diag1[i] *= -2; - } - } - - /* calculate diag(A,-2) */ - for (i = 0; i < N - 2; i++) { - if (i > 0 && indices[b + i + 1] == indices[b + i]) { - cep->diag2[i] = prev_diag2; - } else { - vecstart = indices[b + i + 1] * vecsize; - /* - k = vecstart + pdf->numvuv + pdf->ceporder * 2 + pdf->numdeltas * 3 + pdf->ceporder * 2 + cepnum; - cep->diag2[i] = (picoos_int32)(pdf->content[k]) << pdf->bigpow; - k -= pdf->ceporder; - ivar = (picoos_int32)(pdf->content[k]) << pdf->bigpow; - */ - cep->diag2[i] = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, - PICOCEP_WANTDELTA2); - ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, - PICOCEP_WANTDELTA); - cep->diag2[i] -= (ivar + 2) / 4; - prev_diag2 = cep->diag2[i]; - } - } - - return 0; -}/* makeWUWandWUm */ - -/** - * Retrieve actual values for MGC from PDF resource - * @param pdf : pointer to picoos_uint8, sequence of pdf vectors, each vector of length 1+ceporder*2+numdeltas*3+ceporder*3 - * @param vecstart : indices of pdf vectors for all frames in current sentence - * @param cepnum : cepstral dimension to be treated - * @param wantMeanOrIvar : flag to select mean or variance values - * @param wantStaticOrDeltax : flag to select static or delta values - * @return the actual value retrieved - * @callgraph - * @callergraph - */ -static picoos_int32 getFromPdf(picokpdf_PdfMUL pdf, picoos_uint32 vecstart, - picoos_uint8 cepnum, picocep_WantMeanOrIvar_t wantMeanOrIvar, - picocep_WantStaticOrDelta_t wantStaticOrDeltax) -{ - picoos_uint8 s, ind; - picoos_uint8 *p; - picoos_uint8 ceporder, ceporder2, cc; - picoos_uint32 k; - picoos_int32 mean = 0, ivar = 0; - - if (pdf->numdeltas == 0xFF) { - switch (wantMeanOrIvar) { - case PICOCEP_WANTMEAN: - switch (wantStaticOrDeltax) { - case PICOCEP_WANTSTATIC: - p = pdf->content - + (vecstart + pdf->numvuv + cepnum * 2); /* cepnum'th static mean */ - mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8)) - | *p) << (pdf->meanpowUm[cepnum]); - break; - case PICOCEP_WANTDELTA: - cc = pdf->ceporder + cepnum; - p = pdf->content + (vecstart + pdf->numvuv + cc * 2); /* cepnum'th delta mean */ - mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8)) - | *p) << (pdf->meanpowUm[cc]); - break; - case PICOCEP_WANTDELTA2: - cc = pdf->ceporder * 2 + cepnum; - p = pdf->content + (vecstart + pdf->numvuv + cc * 2); /* cepnum'th delta delta mean */ - mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8)) - | *p) << (pdf->meanpowUm[cc]); - break; - default: - /* should never come here */ - PICODBG_ERROR(("unknown type wantStaticOrDeltax = %i", wantStaticOrDeltax)); - } - return mean; - break; - case PICOCEP_WANTIVAR: - switch (wantStaticOrDeltax) { - case PICOCEP_WANTSTATIC: - k = vecstart + pdf->numvuv + pdf->ceporder * 6 + cepnum; /* cepnum'th static ivar */ - ivar = (picoos_int32) (pdf->content[k]) - << (pdf->ivarpow[cepnum]); - break; - case PICOCEP_WANTDELTA: - ceporder = pdf->ceporder; - k = vecstart + pdf->numvuv + ceporder * 7 + cepnum; /* cepnum'th delta ivar */ - ivar = (picoos_int32) (pdf->content[k]) - << (pdf->ivarpow[ceporder + cepnum]); - break; - case PICOCEP_WANTDELTA2: - ceporder = pdf->ceporder; - k = vecstart + pdf->numvuv + ceporder * 8 + cepnum; /* cepnum'th delta delta ivar */ - ivar = (picoos_int32) (pdf->content[k]) - << (pdf->ivarpow[2 * ceporder + cepnum]); - break; - default: - /* should never get here */ - PICODBG_ERROR(("unknown type wantStaticOrDeltax = %i", wantStaticOrDeltax)); - } - return ivar; - break; - default: - /* should never come here */ - PICODBG_ERROR(("unknown type wantMeanOrIvar = %n", wantMeanOrIvar)); - return 0; - } - } else { - switch (wantMeanOrIvar) { - case PICOCEP_WANTMEAN: - switch (wantStaticOrDeltax) { - case PICOCEP_WANTSTATIC: - p = pdf->content - + (vecstart + pdf->numvuv + cepnum * 2); /* cepnum'th static mean */ - mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8)) - | *p) << (pdf->meanpowUm[cepnum]); - return mean; - break; - case PICOCEP_WANTDELTA: - ceporder = pdf->ceporder; - s = 0; - ind = 0; - while ((s < pdf->numdeltas) && (ind < cepnum || (ind - == 0 && cepnum == 0))) { /* rawmean deltas are sparse so investigate indices in column */ - k = vecstart + pdf->numvuv + ceporder * 2 + s; /* s'th delta index */ - ind = (picoos_uint8) (pdf->content[k]); /* is already picoos_uint8 but just to make explicit */ - if (ind == cepnum) { - k = vecstart + pdf->numvuv + ceporder * 2 - + pdf->numdeltas + s * 2; /* s'th sparse delta mean, corresponds to cepnum'th delta mean */ - mean - = ((picoos_int32) ((picoos_int16) ((pdf->content[k - + 1]) << 8)) | pdf->content[k]) - << (pdf->meanpowUm[ceporder - + cepnum]); - return mean; - } - s++; - } - return 0; - break; - case PICOCEP_WANTDELTA2: - ceporder = pdf->ceporder; - ceporder2 = ceporder * 2; - s = pdf->numdeltas; - ind = 2 * ceporder; - while ((s-- > 0) && (ind > ceporder + cepnum)) { /* rawmean deltas are sparse so investigate indices in column */ - k = vecstart + pdf->numvuv + ceporder2 + s; /* s'th delta index */ - ind = (picoos_uint8) (pdf->content[k]); /* is already picoos_uint8 but just to make explicit */ - if (ind == ceporder + cepnum) { - k = vecstart + pdf->numvuv + ceporder2 - + pdf->numdeltas + s * 2; /* s'th sparse delta mean, corresponds to cepnum'th delta delta mean */ - mean - = ((picoos_int32) ((picoos_int16) ((pdf->content[k - + 1]) << 8)) | pdf->content[k]) - << (pdf->meanpowUm[ceporder2 - + cepnum]); - return mean; - } - } - return 0; - break; - default: - PICODBG_ERROR(("getFromPdf: unknown type wantStaticOrDeltax = %i\n", wantStaticOrDeltax)); - return 0; - } - break; - case PICOCEP_WANTIVAR: - switch (wantStaticOrDeltax) { - case PICOCEP_WANTSTATIC: - k = vecstart + pdf->numvuv + pdf->ceporder * 2 - + pdf->numdeltas * 3 + cepnum; /* cepnum'th static ivar */ - ivar = (picoos_int32) (pdf->content[k]) - << (pdf->ivarpow[cepnum]); - break; - case PICOCEP_WANTDELTA: - ceporder = pdf->ceporder; - k = vecstart + pdf->numvuv + ceporder * 3 - + pdf->numdeltas * 3 + cepnum; /* cepnum'th delta ivar */ - ivar = (picoos_int32) (pdf->content[k]) - << (pdf->ivarpow[ceporder + cepnum]); - break; - case PICOCEP_WANTDELTA2: - ceporder2 = 2 * pdf->ceporder; - k = vecstart + pdf->numvuv + ceporder2 + pdf->numdeltas - * 3 + ceporder2 + cepnum; /* cepnum'th delta delta ivar */ - ivar = (picoos_int32) (pdf->content[k]) - << (pdf->ivarpow[ceporder2 + cepnum]); - break; - default: - PICODBG_ERROR(("unknown type wantStaticOrDeltax = %i", wantStaticOrDeltax)); - } - return ivar; - break; - default: - PICODBG_ERROR(("unknown type wantMeanOrIvar = %i", wantMeanOrIvar)); - return 0; - } - } - return 0; -} - -/** - * Retrieve actual values for MGC from PDF resource - Variant "Direct" - * @param pdf : pointer to picoos_uint8, sequence of pdf vectors, each vector of length 1+ceporder*2+numdeltas*3+ceporder*3 - * @param indices : indices of pdf vectors for all frames in current sentence - * @param activeEndPos : ?? - * @param cepnum : cepstral dimension to be treated - * @param smoothcep : ?? - * @return the actual value retrieved - * @callgraph - * @callergraph - */ -static void getDirect(picokpdf_PdfMUL pdf, picoos_uint16 *indices, - picoos_uint16 activeEndPos, - picoos_uint8 cepnum, picoos_int16 *smoothcep) -{ - picoos_uint16 i; - picoos_uint32 j; - picoos_uint32 vecstart; - picoos_int32 mean, ivar; - picoos_int32 prev_mean; - picoos_uint8 vecsize = pdf->vecsize; - picoos_uint8 order = pdf->ceporder; - - j = cepnum; - prev_mean = 0; - for (i = 0; i < activeEndPos; i++) { - if (i > 0 && indices[i] == indices[i - 1]) { - mean = prev_mean; - } else { - vecstart = indices[i] * vecsize; - mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN, - PICOCEP_WANTSTATIC); - ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, - PICOCEP_WANTSTATIC); - prev_mean = mean = picocep_fixptdiv(mean, ivar, pdf->bigpow); - } - smoothcep[j] = (picoos_int16)(mean/(1<meanpow)); - j += order; - } -} - -/** - * Retrieve actual values for voicing from PDF resource - * @param pdf : pointer to picoos_uint8, sequence of pdf vectors, each vector of length 1+ceporder*2+numdeltas*3+ceporder*3 - * @param indices : indices of pdf vectors for all frames in current sentence - * @param activeEndPos : end position of indices to be considered - * @return smoothcep : the values retrieved - * @callgraph - * @callergraph - */ -static void getVoiced(picokpdf_PdfMUL pdf, picoos_uint16 *indices, - picoos_uint16 activeEndPos, - picoos_uint8 *smoothcep) -{ - picoos_uint16 i, j; - picoos_uint32 vecstart; - picoos_uint8 vecsize = pdf->vecsize; - - if (pdf->numvuv == 0) { - /* do nothing */ - } else { - for (i = 0, j = 0; i < activeEndPos; i++, j++) { - vecstart = indices[i] * vecsize; - smoothcep[j] = pdf->content[vecstart]; /* odd value is voiced, even if unvoiced */ - } - } -} - -/** reads platform-independent uint16 from buffer at *pos and advances *pos - * @param buf : buffer picoos_uint8 - * @param *pos : start position inside buffer of pi uint16 - * @return the uint16 - * @callgraph - * @callergraph - */ -static picoos_uint16 get_pi_uint16(picoos_uint8 * buf, picoos_uint16 *pos) -{ - picoos_uint16 res; - res = buf[(*pos)] | ((picoos_uint16) buf[(*pos) + 1] << 8); - *pos += 2; - return res; -} -/** - * Looks up indices of one phone item and fills index buffers. Consumes Item - * @param cep : the CEP PU sub object pointer - * @param ihead : pointer to the start of the phone item - * @callgraph - * @callergraph - */ -static void treat_phone(cep_subobj_t * cep, picodata_itemhead_t * ihead) -{ - picoos_uint16 state, frame, frames; - picoos_uint16 indlfz, indmgc; - picoos_uint16 pos; - picoos_uint8 bufferFull; - - /* treat all states - * for each state, repeat putting the index into the index buffer framesperstate times. - */ - /* set state and frame to the first state and frame in the phone to be considered */ - state = 0; /* the first state to be considered */ - frame = 0; /* the first frame to be considered */ - /* numFramesPerState: 2 byte, lf0Index: 2 byte, mgcIndex: 2 byte -> 6 bytes per state */ - PICODBG_DEBUG(("skipping to phone state %i ",state)); - pos = cep->inReadPos + PICODATA_ITEM_HEADSIZE + state * 6; - /* */ - PICODBG_DEBUG(("state info starts at inBuf pos %i ",pos)); - /* get the current frames per state */ - frames = get_pi_uint16(cep->inBuf, &pos); - /* */ - PICODBG_DEBUG(("number of frames for this phone state: %i",frames)); - /* */ - PICODBG_DEBUG(("PARSE starting with frame %i",frame)); - - bufferFull = cep->indexWritePos >= PICOCEP_MAXWINLEN; - while ((state < ihead->info2) && (bufferFull == FALSE)) { - - /* get the current state's lf0 and mgc indices and adjust according to state */ - /* the indices have to be calculated as follows: - * new index = (index-1) + stateoffset(state) */ - - indlfz = get_pi_uint16(cep->inBuf, &pos); /* lfz index */ - indlfz += -1 + cep->pdflfz->stateoffset[state]; /* transform index */ - indmgc = get_pi_uint16(cep->inBuf, &pos); /* mgc index */ - indmgc += -1 + cep->pdfmgc->stateoffset[state]; /* transform index */ - - /* are we reaching the end of the index buffers? */ - if ((cep->indexWritePos - frame) + frames > PICOCEP_MAXWINLEN) { - /* number of frames that will still fit */ - frames = PICOCEP_MAXWINLEN - (cep->indexWritePos - frame); - bufferFull = TRUE; - PICODBG_DEBUG(("smoothing buffer full at state=%i frame=%i",state, frame)); - } - while (frame < frames) { - cep->indicesMGC[cep->indexWritePos] = indmgc; - cep->indicesLFZ[cep->indexWritePos] = indlfz; - cep->phoneId[cep->indexWritePos] = ihead->info1; - cep->indexWritePos++; - frame++; - } - /* proceed to next state */ - PICODBG_DEBUG(("finished state %i with %i frames, now at index write pos %i", - state, frames,cep->indexWritePos)); - state++; - if (state < ihead->info2) { - frame = 0; - frames = get_pi_uint16(cep->inBuf, &pos); - } - } - /* consume the phone item */ - cep->inReadPos = cep->nextInPos; - /* */ - PICODBG_DEBUG(("finished phone, advancing inReadPos to %i",cep->inReadPos)); -} - -/** - * Returns true if an Item has to be forwarded to next PU - * @param ihead : pointer to item head structure - * @return TRUE : the item should be forwarded - * @return FALSE : the item should be consumed - * @callgraph - * @callergraph - */ -static picoos_uint8 forwardingItem(picodata_itemhead_t * ihead) -{ - if ((PICODATA_ITEM_CMD == ihead->type) && (PICODATA_ITEMINFO1_CMD_IGNSIG - == ihead->info1)) { - return FALSE; - } else { - return TRUE; - } -} - -/** - * performs a step of the cep processing - * @param this : pointer to current PU (Control Unit) - * @param mode : mode for the PU (not used) - * @param numBytesOutput : pointer to output number fo bytes produced - * @return one of the "picodata_step_result_t" values - * @callgraph - * @callergraph - */ -static picodata_step_result_t cepStep(register picodata_ProcessingUnit this, - picoos_int16 mode, picoos_uint16 * numBytesOutput) -{ - register cep_subobj_t * cep; - picodata_itemhead_t ihead /* , ohead */; - picoos_uint8 * icontents; - pico_status_t sResult = PICO_OK; - picoos_uint16 blen, clen; - picoos_uint16 numinb, numoutb; - -#if defined (PICO_DEBUG) - picoos_char msgstr[PICOCEP_MSGSTR_SIZE]; -#endif - numinb = 0; - numoutb = 0; - - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - cep = (cep_subobj_t *) this->subObj; - mode = mode; /* avoid warning "var not used in this function"*/ - - /*Init number of output bytes*/ - *numBytesOutput = 0; - - while (1) { /* exit via return */ - - PICODBG_DEBUG(("doing pu state %i", cep->procState)); - - switch (cep->procState) { - - case PICOCEP_STEPSTATE_COLLECT: - /* *************** item collector ***********************************/ - - PICODBG_TRACE(("COLLECT")); - - /*collecting items from the PU input buffer*/ - sResult = picodata_cbGetItem(this->cbIn, - &(cep->inBuf[cep->inWritePos]), cep->inBufSize - - cep->inWritePos, &blen); - if (PICO_EOF == sResult) { /* there are no more items available and we always need more data here */ - PICODBG_DEBUG(("COLLECT need more data, returning IDLE")); - return PICODATA_PU_IDLE; - } - - PICODBG_DEBUG(("got item, status: %d", sResult)); - - if ((PICO_OK == sResult) && (blen > 0)) { - /* we now have one item */ - cep->inWritePos += blen; - cep->procState = PICOCEP_STEPSTATE_PROCESS_PARSE; - } else { - /* ignore item and stay in collect */ - PICODBG_ERROR(("COLLECT got bad result %i", sResult)); - cep->inReadPos = cep->inWritePos = 0; - } - /* return PICODATA_PU_ATOMIC; */ - break; - - case PICOCEP_STEPSTATE_PROCESS_PARSE: - /* **************** put item indices into index buffers (with repetition) ******************/ - - PICODBG_TRACE(("PARSE")); - - PICODBG_DEBUG(("getting info from inBuf in range: [%i,%i[", cep->inReadPos, cep->inWritePos)); - if (cep->inWritePos <= cep->inReadPos) { - /* no more items in inBuf */ - /* we try to get more data */ - PICODBG_DEBUG(("no more items in inBuf, try to collect more")); - /* cep->needMoreInput = TRUE; */ - cep->inReadPos = cep->inWritePos = 0; - cep->procState = PICOCEP_STEPSTATE_COLLECT; - break; - } - /* look at the current item */ - /*verify that current item is valid */ - if (!picodata_is_valid_item(cep->inBuf + cep->inReadPos, - cep->inWritePos - cep->inReadPos)) { - PICODBG_ERROR(("found invalid item")); - sResult = picodata_get_iteminfo( - cep->inBuf + cep->inReadPos, cep->inWritePos - - cep->inReadPos, &ihead, &icontents);PICODBG_DEBUG(("PARSE bad item %s",picodata_head_to_string(&ihead,msgstr,PICOCEP_MSGSTR_SIZE))); - - return PICODATA_PU_ERROR; - } - - sResult = picodata_get_iteminfo(cep->inBuf + cep->inReadPos, - cep->inWritePos - cep->inReadPos, &ihead, &icontents); - - if (PICO_EXC_BUF_UNDERFLOW == sResult) { - /* no more items in inBuf */ - /* we try to get more data */ - PICODBG_DEBUG(("no more items in inBuf, try to collect more")); - /* cep->needMoreInput = TRUE; */ - cep->inReadPos = cep->inWritePos = 0; - cep->procState = PICOCEP_STEPSTATE_COLLECT; - break; - } else if (PICO_OK != sResult) { - PICODBG_ERROR(("unknown exception (sResult == %i)",sResult)); - return (picodata_step_result_t) picoos_emRaiseException( - this->common->em, sResult, NULL, NULL); - break; - } - - PICODBG_DEBUG(("PARSE looking at item %s",picodata_head_to_string(&ihead,msgstr,PICOCEP_MSGSTR_SIZE))); - - cep->nextInPos = PICODATA_ITEM_HEADSIZE + ihead.len; - - /* we decide what to do next depending on the item and the state of the index buffer: - * - process buffer if buffer not empty and sentence end or flush or ignsig/start (don't consume item yet) - * - fill buffer with (part of) phone contents if item is a phone - * - consume or copy for later output otherwise - */ - - if (cep->inIgnoreState) { - if ((PICODATA_ITEM_CMD == ihead.type) - && (PICODATA_ITEMINFO1_CMD_IGNSIG == ihead.info1) - && (PICODATA_ITEMINFO2_CMD_END == ihead.info2)) { - cep->inIgnoreState = 0; - }PICODBG_DEBUG(("cep: PARSE consuming item of inBuf")); - cep->inReadPos = cep->nextInPos; - break; - } - - /* see if it is a sentence end boundary or termination boundary (flush) and there are indices to smooth -> smooth */ - if ((PICODATA_ITEM_BOUND == ihead.type) - && ((PICODATA_ITEMINFO1_BOUND_SEND == ihead.info1) - || (PICODATA_ITEMINFO1_BOUND_TERM == ihead.info1)) - && (cep->indexWritePos > 0)) { - /* we smooth the buffer */ - cep->activeEndPos = cep->indexWritePos; - cep->sentenceEnd = TRUE; - /* output whatever we got */ - PICODBG_DEBUG(("cep: PARSE found sentence terminator; setting activeEndPos to %i",cep->activeEndPos)); - cep->procState = PICOCEP_STEPSTATE_PROCESS_SMOOTH; - break; - } else if (PICODATA_ITEM_PHONE == ihead.type) { - /* it is a phone */ - PICODBG_DEBUG(("cep: PARSE treating PHONE")); - treat_phone(cep, &ihead); - - } else { - if ((PICODATA_ITEM_CMD == ihead.type) - && (PICODATA_ITEMINFO1_CMD_IGNSIG == ihead.info1) - && (PICODATA_ITEMINFO2_CMD_START == ihead.info2)) { - cep->inIgnoreState = 1; - } - /* sentence end or flush remaining after frame or other non-processable item, e.g. command */ - /* do we have to forward? */ - if (forwardingItem(&ihead)) { - /* if no active frames, output immediately */ - if (cep->indexWritePos <= 0) { - /* copy item to outBuf */ - PICODBG_DEBUG(("PARSE copy item in inBuf to outBuf")); - picodata_copy_item(cep->inBuf + cep->inReadPos, - cep->inWritePos - cep->inReadPos, - cep->outBuf, cep->outBufSize, &blen); - cep->outWritePos += blen; - PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], - (picoos_uint8 *)"cep: do forward item ", - cep->outBuf, PICODATA_MAX_ITEMSIZE); - /* output item and then go to parse to treat a new item. */ - cep->feedFollowState - = PICOCEP_STEPSTATE_PROCESS_PARSE; - cep->procState = PICOCEP_STEPSTATE_FEED; - } else if ((cep->headxWritePos < PICOCEP_MAXNR_HEADX) - && (cep->cbufWritePos + ihead.len - < cep->cbufBufSize)) { - /* there is enough space to store item */ - PICODBG_DEBUG(("unhandled item (type %c, length %i). Storing associated with index %i",ihead.type, ihead.len, cep->indexWritePos)); - sResult - = picodata_get_itemparts( - cep->inBuf + cep->inReadPos, - cep->inWritePos - cep->inReadPos, - &(cep->headx[cep->headxWritePos].head), - &(cep->cbuf[cep->cbufWritePos]), - cep->cbufBufSize - - cep->cbufWritePos, &clen); - - if (sResult != PICO_OK) { - PICODBG_ERROR(("problem getting item parts")); - picoos_emRaiseException(this->common->em, - sResult, NULL, NULL); - return PICODATA_PU_ERROR; - } - /* remember sync position */ - cep->headx[cep->headxWritePos].frame - = cep->indexWritePos; - - if (clen > 0) { - cep->headx[cep->headxWritePos].cind - = cep->cbufWritePos; - cep->cbufWritePos += clen; - } else { - cep->headx[cep->headxWritePos].cind = 0; - } - cep->headxWritePos++; - } else { - /* buffer full, smooth and output whatever we got */ - PICODBG_DEBUG(("PARSE is forced to smooth prematurely; setting activeEndPos to %i", cep->activeEndPos)); - cep->procState = PICOCEP_STEPSTATE_PROCESS_SMOOTH; - /* don't consume item yet */ - break; - } - } else { - }PICODBG_DEBUG(("cep: PARSE consuming item of inBuf")); - cep->inReadPos = cep->nextInPos; - } - break; - - case PICOCEP_STEPSTATE_PROCESS_SMOOTH: - /* **************** smooth (indexed) coefficients and store smoothed in outBuffers ****************/ - - PICODBG_TRACE(("SMOOTH")); - { - picokpdf_PdfMUL pdf; - - /* picoos_uint16 framesTreated = 0; */ - picoos_uint8 cepnum; - picoos_uint16 N; - - N = cep->activeEndPos; /* numframes in current step */ - - /* the range to be smoothed starts at 0 and is N long */ - - /* smooth each cepstral dimension separately */ - /* still to be experimented if higher order coeff can remain unsmoothed, i.e. simple copy from pdf */ - - /* reset the f0, ceps and voiced outfuffers */ - cep->outXCepReadPos = cep->outXCepWritePos = 0; - cep->outVoicedReadPos = cep->outVoicedWritePos = 0; - cep->outF0ReadPos = cep->outF0WritePos = 0; - - PICODBG_DEBUG(("smoothing %d frames\n", N)); - - /* smooth f0 */ - pdf = cep->pdflfz; - for (cepnum = 0; cepnum < pdf->ceporder; cepnum++) { - if (cep->activeEndPos <= 0) { - /* do nothing */ - } else if (3 < N) { - makeWUWandWUm(cep, pdf, cep->indicesLFZ, 0, N, - cepnum); /* update diag0, diag1, diag2, WUm */ - invMatrix(cep, N, cep->outF0 + cep->outF0WritePos, cepnum, pdf, - PICOCEP_LFZINVPOW, PICOCEP_LFZDOUBLEDEC); - } else { - getDirect(pdf, cep->indicesLFZ, cep->activeEndPos, - cepnum, cep->outF0 + cep->outF0WritePos); - } - }/* end for cepnum */ - cep->outF0WritePos += cep->activeEndPos * pdf->ceporder; - - /* smooth mgc */ - pdf = cep->pdfmgc; - for (cepnum = 0; cepnum < pdf->ceporder; cepnum++) { - if (cep->activeEndPos <= 0) { - /* do nothing */ - } else if (3 < N) { - makeWUWandWUm(cep, pdf, cep->indicesMGC, 0, N, - cepnum); /* update diag0, diag1, diag2, WUm */ - invMatrix(cep, N, cep->outXCep - + cep->outXCepWritePos, cepnum, - pdf, PICOCEP_MGCINVPOW, - PICOCEP_MGCDOUBLEDEC); - } else { - getDirect(pdf, cep->indicesMGC, cep->activeEndPos, - cepnum, cep->outXCep + cep->outXCepWritePos); - } - }/* end for cepnum */ - cep->outXCepWritePos += cep->activeEndPos * pdf->ceporder; - - getVoiced(pdf, cep->indicesMGC, cep->activeEndPos, cep->outVoiced - + cep->outVoicedWritePos); - cep->outVoicedWritePos += cep->activeEndPos; - - } - /* setting indexReadPos to the next active index to be used. (will be advanced by FRAME when - * reading the phoneId */ - cep->indexReadPos = 0; - cep->procState = PICOCEP_STEPSTATE_PROCESS_FRAME; - return PICODATA_PU_BUSY; /*data to feed*/ - - break; - - case PICOCEP_STEPSTATE_PROCESS_FRAME: - - /* *************** creating output items (type FRAME) ***********************************/ - - PICODBG_TRACE(("FRAME")); - - if ((cep->headxBottom < cep->headxWritePos) - && (cep->headx[cep->headxBottom].frame - <= cep->indexReadPos)) { - - /* output item in headx/cbuf */ - /* copy item to outBuf */ - PICODBG_DEBUG(("FRAME copy item in inBuf to outBuf")); - picodata_put_itemparts( - &(cep->headx[cep->headxBottom].head), - &(cep->cbuf[cep->headx[cep->headxBottom].cind]), - cep->headx[cep->headxBottom].head.len, cep->outBuf, - cep->outBufSize, &blen); - cep->outWritePos += blen; - /* consume item in headx/cbuf */ - PICODBG_DEBUG(("PARSE consuming item of headx/cbuf")); - cep->headxBottom++; - - /* output item and then go to parse to treat a new item. */ - cep->feedFollowState = PICOCEP_STEPSTATE_PROCESS_FRAME; - cep->procState = PICOCEP_STEPSTATE_FEED; - break; - } - - if (cep->indexReadPos < cep->activeEndPos) { - /*------------ there are frames to output ----------------------------------------*/ - /* still frames to output, create new FRAME_PAR item */ - - cep->nNumFrames++; - - PICODBG_DEBUG(("FRAME creating FRAME_PAR: active: [0,%i[, read=%i, write=%i", - cep->activeEndPos, cep->indexReadPos, cep->indexWritePos - )); - - /* create FRAME_PAR items from cep->outXX one by one */ - - /* converting the ceps shorts into floats: - * scmeanpow = pdf->bigpow - pdf->meanpow; - * for all sval: - * fval = (picoos_single) sval / scmeanpow; - */ - - cep->outWritePos = cep->outReadPos = 0; - cep->outBuf[cep->outWritePos++] = cep->framehead.type; - cep->outBuf[cep->outWritePos++] = cep->framehead.info1; - cep->outBuf[cep->outWritePos++] = cep->framehead.info2; - cep->outBuf[cep->outWritePos++] = cep->framehead.len; - - PICODBG_DEBUG(("FRAME writing position after header: %i",cep->outWritePos)); - - { - picoos_uint16 tmpUint16; - picoos_int16 tmpInt16; - picoos_uint16 i; - - /* */ - PICODBG_DEBUG(("FRAME reading phoneId[%i] = %c:",cep->indexReadPos, cep->phoneId[cep->indexReadPos])); - /* */ - - tmpUint16 - = (picoos_uint16) cep->phoneId[cep->indexReadPos]; - - picoos_mem_copy((void *) &tmpUint16, - (void *) &cep->outBuf[cep->outWritePos], - sizeof(tmpUint16)); - - cep->outWritePos += sizeof(tmpUint16); - - PICODBG_DEBUG(("FRAME writing position after phone id: %i",cep->outWritePos)); - - for (i = 0; i < cep->pdflfz->ceporder; i++) { - - tmpUint16 = (cep->outVoiced[cep->outVoicedReadPos] - & 0x01) ? cep->outF0[cep->outF0ReadPos] - : (picoos_uint16) 0; - - picoos_mem_copy((void *) &tmpUint16, - (void *) &cep->outBuf[cep->outWritePos], - sizeof(tmpUint16)); - cep->outWritePos += sizeof(tmpUint16); - - tmpUint16 - = (picoos_uint16) (cep->outVoiced[cep->outVoicedReadPos]); - picoos_mem_copy((void *) &tmpUint16, - (void *) &cep->outBuf[cep->outWritePos], - sizeof(tmpUint16)); - cep->outWritePos += sizeof(tmpUint16); - tmpUint16 - = (picoos_uint16) (cep->outF0[cep->outF0ReadPos]); - picoos_mem_copy((void *) &tmpUint16, - (void *) &cep->outBuf[cep->outWritePos], - sizeof(tmpUint16)); - cep->outWritePos += sizeof(tmpUint16); - - cep->outVoicedReadPos++; - cep->outF0ReadPos++; - } - - PICODBG_DEBUG(("FRAME writing position after f0: %i",cep->outWritePos)); - - for (i = 0; i < cep->pdfmgc->ceporder; i++) { - tmpInt16 = cep->outXCep[cep->outXCepReadPos++]; - picoos_mem_copy((void *) &tmpInt16, - (void *) &cep->outBuf[cep->outWritePos], - sizeof(tmpInt16)); - cep->outWritePos += sizeof(tmpInt16); - } - - PICODBG_DEBUG(("FRAME writing position after cepstrals: %i",cep->outWritePos)); - - tmpUint16 - = (picoos_uint16) cep->indicesMGC[cep->indexReadPos++]; - - picoos_mem_copy((void *) &tmpUint16, - (void *) &cep->outBuf[cep->outWritePos], - sizeof(tmpUint16)); - - PICODBG_DEBUG(("FRAME writing position after mgc index: %i",cep->outWritePos)); - - cep->outWritePos += sizeof(tmpUint16); - - } - /* finished to create FRAME_PAR, now output and then come back*/ - cep->feedFollowState = PICOCEP_STEPSTATE_PROCESS_FRAME; - cep->procState = PICOCEP_STEPSTATE_FEED; - - } else if (cep->sentenceEnd) { - /*------------ no more frames to output at end of sentence ----------------------------------------*/ - PICODBG_INFO(("End of sentence - Processed frames : %d", - cep->nNumFrames)); - cep->nNumFrames = 0;PICODBG_DEBUG(("FRAME no more active frames for this sentence")); - /* no frames left in this sentence*/ - /* reset for new sentence */ - initSmoothing(cep); - cep->sentenceEnd = FALSE; - cep->indexReadPos = cep->indexWritePos = 0; - cep->activeEndPos = PICOCEP_MAXWINLEN; - cep->headxBottom = cep->headxWritePos = 0; - cep->cbufWritePos = 0; - cep->procState = PICOCEP_STEPSTATE_PROCESS_PARSE; - } else { - /*------------ no more frames can be output but sentence end not reached ----------------------------------------*/ - PICODBG_DEBUG(("Maximum number of frames per sentence reached")); - cep->procState = PICOCEP_STEPSTATE_PROCESS_PARSE; - } - /*----------------------------------------------------*/ - break; - - case PICOCEP_STEPSTATE_FEED: - /* ***********************************************************************/ - /* FEED: combine input item with pos/phon pairs to output item */ - /* ***********************************************************************/ - - PICODBG_DEBUG(("FEED")); - - PICODBG_DEBUG(("FEED putting outBuf item into cb")); - - /*feeding items to PU output buffer*/ - sResult = picodata_cbPutItem(this->cbOut, cep->outBuf, - cep->outBufSize, &blen); - - if (PICO_EXC_BUF_OVERFLOW == sResult) { - /* we have to redo this item */ - PICODBG_DEBUG(("FEED got overflow, returning PICODATA_PU_OUT_FULL")); - return PICODATA_PU_OUT_FULL; - } else if (PICO_OK == sResult) { - - if (cep->outBuf[0] != 'k') { - PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], - (picoos_uint8 *)"cep: ", - cep->outBuf, PICODATA_MAX_ITEMSIZE); - } - - *numBytesOutput += blen; - /*-------------------------*/ - /*reset the output pointers*/ - /*-------------------------*/ - if (cep->outReadPos >= cep->outWritePos) { - cep->outReadPos = 0; - cep->outWritePos = 0; - } - cep->procState = cep->feedFollowState; - PICODBG_DEBUG(("FEED ok, going back to procState %i", cep->procState)); - return PICODATA_PU_BUSY; - } else { - PICODBG_DEBUG(("FEED got exception %i when trying to output item",sResult)); - cep->procState = cep->feedFollowState; - return (picodata_step_result_t) sResult; - } - break; - - default: - /*NOT feeding items*/ - sResult = PICO_EXC_BUF_IGNORE; - break; - }/*end switch (cep->procState) */ - return PICODATA_PU_BUSY; /*check if there is more data to process after feeding*/ - - }/*end while*/ - /* we should never come here */ - return PICODATA_PU_ERROR; -}/*cepStep*/ - -/* Picocep.c end */ diff --git a/lib/picocep.h b/lib/picocep.h deleted file mode 100644 index 79a5d7c..0000000 --- a/lib/picocep.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 picocep.h - * - * Cepstral Smoothing PU - Header file - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#ifndef PICOCEP_H_ -#define PICOCEP_H_ - -#include "picoos.h" -#include "picodata.h" -#include "picorsrc.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -/* ****************************************************************************** - * items related to the generic interface - ********************************************************************************/ -picodata_ProcessingUnit picocep_newCepUnit(picoos_MemoryManager mm, - picoos_Common common, picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, picorsrc_Voice voice); - -#ifdef __cplusplus -} -#endif - -#endif /*PICOCEP_H_*/ diff --git a/lib/picoctrl.c b/lib/picoctrl.c deleted file mode 100644 index 5af70e3..0000000 --- a/lib/picoctrl.c +++ /dev/null @@ -1,840 +0,0 @@ -/* - * 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 */ diff --git a/lib/picoctrl.h b/lib/picoctrl.h deleted file mode 100644 index 1dfea54..0000000 --- a/lib/picoctrl.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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.h - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#ifndef PICOCTRL_H_ -#define PICOCTRL_H_ - -#include "picodefs.h" -#include "picoos.h" -#include "picorsrc.h" -#include "picodata.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -#define PICOCTRL_MAX_PROC_UNITS 25 - -/* temporarily increased for preprocessing -#define PICOCTRL_DEFAULT_ENGINE_SIZE 200000 -*/ -#define PICOCTRL_DEFAULT_ENGINE_SIZE 1000000 - -typedef struct picoctrl_engine * picoctrl_Engine; - -picoos_int16 picoctrl_isValidEngineHandle(picoctrl_Engine this); - -picoctrl_Engine picoctrl_newEngine ( - picoos_MemoryManager mm, - picorsrc_ResourceManager rm, - const picoos_char * voiceName - ); - -void picoctrl_disposeEngine( - picoos_MemoryManager mm, - picorsrc_ResourceManager rm, - picoctrl_Engine * this - ); - -pico_status_t picoctrl_engFeedText( - picoctrl_Engine engine, - picoos_char * text, - picoos_int16 textSize, - picoos_int16 * bytesPut); - -pico_status_t picoctrl_engReset( - picoctrl_Engine engine - ); - -picoos_Common picoctrl_engGetCommon(picoctrl_Engine this); - -picodata_step_result_t picoctrl_engFetchOutputItemBytes( - picoctrl_Engine engine, - picoos_char * buffer, - picoos_int16 bufferSize, - picoos_int16 * bytesReceived -); - -void picoctrl_engResetExceptionManager( - picoctrl_Engine this - ); - - -picodata_step_result_t picoctrl_getLastScheduledPU( - picoctrl_Engine engine - ); - -picodata_step_result_t picoctrl_getLastProducedItemType( - picoctrl_Engine engine - ); - -#ifdef __cplusplus -} -#endif - -#endif /*PICOCTRL_H_*/ diff --git a/lib/picodata.c b/lib/picodata.c deleted file mode 100644 index 244e4b6..0000000 --- a/lib/picodata.c +++ /dev/null @@ -1,1152 +0,0 @@ -/* - * 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 picodata.c - * - * 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 "picorsrc.h" -#include "picotrns.h" -#include "picodata.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -/* we output coefficients as fixed point values */ -#define PICOCEP_OUT_DATA_FORMAT PICODATA_ITEMINFO1_FRAME_PAR_DATA_FORMAT_FIXED - -/* *************************************************************** - * CharBuffer * - *****************************************************************/ - -/* - * method signatures - */ -typedef pico_status_t (* picodata_cbPutItemMethod) (register picodata_CharBuffer this, - const picoos_uint8 *buf, const picoos_uint16 blenmax, - picoos_uint16 *blen); - -typedef pico_status_t (* picodata_cbGetItemMethod) (register picodata_CharBuffer this, - picoos_uint8 *buf, const picoos_uint16 blenmax, - picoos_uint16 *blen, const picoos_uint8 issd); - -typedef pico_status_t (* picodata_cbSubResetMethod) (register picodata_CharBuffer this); -typedef pico_status_t (* picodata_cbSubDeallocateMethod) (register picodata_CharBuffer this, picoos_MemoryManager mm); - -typedef struct picodata_char_buffer -{ - picoos_char *buf; - picoos_uint16 rear; /* next free position to write */ - picoos_uint16 front; /* next position to read */ - picoos_uint16 len; /* empty: len = 0, full: len = size */ - picoos_uint16 size; - - picoos_Common common; - - picodata_cbGetItemMethod getItem; - picodata_cbPutItemMethod putItem; - - picodata_cbSubResetMethod subReset; - picodata_cbSubDeallocateMethod subDeallocate; - void * subObj; -} char_buffer_t; - - -static pico_status_t data_cbPutItem(register picodata_CharBuffer this, - const picoos_uint8 *buf, const picoos_uint16 blenmax, - picoos_uint16 *blen); - -static pico_status_t data_cbGetItem(register picodata_CharBuffer this, - picoos_uint8 *buf, const picoos_uint16 blenmax, - picoos_uint16 *blen, const picoos_uint8 issd); - -pico_status_t picodata_cbReset(register picodata_CharBuffer this) -{ - this->rear = 0; - this->front = 0; - this->len = 0; - if (NULL != this->subObj) { - return this->subReset(this); - } else { - return PICO_OK; - } -} - -/* CharBuffer constructor */ -picodata_CharBuffer picodata_newCharBuffer(picoos_MemoryManager mm, - picoos_Common common, - picoos_objsize_t size) -{ - picodata_CharBuffer this; - - this = (picodata_CharBuffer) picoos_allocate(mm, sizeof(*this)); - PICODBG_DEBUG(("new character buffer, size=%i", size)); - if (NULL == this) { - return NULL; - } - this->buf = picoos_allocate(mm, size); - if (NULL == this->buf) { - picoos_deallocate(mm, (void*) &this); - return NULL; - } - this->size = size; - this->common = common; - - this->getItem = data_cbGetItem; - this->putItem = data_cbPutItem; - - this->subReset = NULL; - this->subDeallocate = NULL; - this->subObj = NULL; - - picodata_cbReset(this); - return this; -} - -void picodata_disposeCharBuffer(picoos_MemoryManager mm, - picodata_CharBuffer *this) -{ - if (NULL != (*this)) { - /* terminate */ - if (NULL != (*this)->subObj) { - (*this)->subDeallocate(*this,mm); - } - picoos_deallocate(mm,(void*)&(*this)->buf); - picoos_deallocate(mm,(void*)this); - } -} - -pico_status_t picodata_cbPutCh(register picodata_CharBuffer this, - picoos_char ch) -{ - if (this->len < this->size) { - this->buf[this->rear++] = ch; - this->rear %= this->size; - this->len++; - return PICO_OK; - } else { - return PICO_EXC_BUF_OVERFLOW; - } -} - - -picoos_int16 picodata_cbGetCh(register picodata_CharBuffer this) -{ - picoos_char ch; - if (this->len > 0) { - ch = this->buf[this->front++]; - this->front %= this->size; - this->len--; - return ch; - } else { - return PICO_EOF; - } -} - -/* *************************************************************** - * items: CharBuffer functions * - *****************************************************************/ - -static pico_status_t data_cbGetItem(register picodata_CharBuffer this, - picoos_uint8 *buf, const picoos_uint16 blenmax, - picoos_uint16 *blen, const picoos_uint8 issd) -{ - picoos_uint16 i; - - if (this->len < PICODATA_ITEM_HEADSIZE) { /* item not in cb? */ - *blen = 0; - if (this->len == 0) { /* is cb empty? */ - PICODBG_DEBUG(("no item to get")); - return PICO_EOF; - } else { /* cb not empty, but not a valid item */ - PICODBG_WARN(("problem getting item, incomplete head, underflow")); - } - return PICO_EXC_BUF_UNDERFLOW; - } - *blen = PICODATA_ITEM_HEADSIZE + (picoos_uint8)(this->buf[((this->front) + - PICODATA_ITEMIND_LEN) % this->size]); - - /* if getting speech data in item */ - if (issd) { - /* check item type */ - if (this->buf[this->front] != PICODATA_ITEM_FRAME) { - PICODBG_WARN(("item type mismatch for speech data: %c", - this->buf[this->front])); - for (i=0; i<*blen; i++) { - this->front++; - this->front %= this->size; - this->len--; - } - *blen = 0; - return PICO_OK; - } - } - - if (*blen > this->len) { /* item in cb not complete? */ - PICODBG_WARN(("problem getting item, incomplete content, underflow; " - "blen=%d, len=%d", *blen, this->len)); - *blen = 0; - return PICO_EXC_BUF_UNDERFLOW; - } - if (blenmax < *blen) { /* buf not large enough? */ - PICODBG_WARN(("problem getting item, overflow")); - *blen = 0; - return PICO_EXC_BUF_OVERFLOW; - } - - /* if getting speech data in item */ - if (issd) { - /* skip item header */ - for (i = 0; i < PICODATA_ITEM_HEADSIZE; i++) { - this->front++; - this->front %= this->size; - this->len--; - } - *blen -= PICODATA_ITEM_HEADSIZE; - } - - /* all ok, now get item (or speech data only) */ - for (i = 0; i < *blen; i++) { - buf[i] = (picoos_uint8)(this->buf[this->front++]); - this->front %= this->size; - this->len--; - } - -#if defined(PICO_DEBUG) - if (issd) { - PICODBG_DEBUG(("got speech data: %d samples", *blen)); - } else { - PICODBG_DEBUG(("got item: %c|%d|%d|%d||", buf[PICODATA_ITEMIND_TYPE], - buf[PICODATA_ITEMIND_INFO1], buf[PICODATA_ITEMIND_INFO2], - buf[PICODATA_ITEMIND_LEN])); - for (i=PICODATA_ITEM_HEADSIZE; i<*blen; i++) { - if (buf[PICODATA_ITEMIND_TYPE] == PICODATA_ITEM_WORDGRAPH) { - PICODBG_DEBUG(("%c", buf[i])); - } else { - PICODBG_DEBUG((" %d", buf[i])); - } - } - } -#endif - - return PICO_OK; -} - -static pico_status_t data_cbPutItem(register picodata_CharBuffer this, - const picoos_uint8 *buf, const picoos_uint16 blenmax, - picoos_uint16 *blen) -{ - picoos_uint16 i; - - if (blenmax < PICODATA_ITEM_HEADSIZE) { /* itemlen not accessible? */ - PICODBG_WARN(("problem putting item, underflow")); - *blen = 0; - return PICO_EXC_BUF_UNDERFLOW; - } - *blen = buf[PICODATA_ITEMIND_LEN] + PICODATA_ITEM_HEADSIZE; - if (*blen > (this->size - this->len)) { /* cb not enough space? */ - PICODBG_WARN(("problem putting item, overflow")); - *blen = 0; - return PICO_EXC_BUF_OVERFLOW; - } - if (*blen > blenmax) { /* item in buf not completely accessible? */ - PICODBG_WARN(("problem putting item, underflow")); - *blen = 0; - return PICO_EXC_BUF_UNDERFLOW; - } - /* all ok, now put complete item */ - -#if defined(PICO_DEBUG) - PICODBG_DEBUG(("putting item: %c|%d|%d|%d||", - buf[PICODATA_ITEMIND_TYPE], - buf[PICODATA_ITEMIND_INFO1], - buf[PICODATA_ITEMIND_INFO2], - buf[PICODATA_ITEMIND_LEN])); - for (i=PICODATA_ITEM_HEADSIZE; i<*blen; i++) { - if (buf[PICODATA_ITEMIND_TYPE] == PICODATA_ITEM_WORDGRAPH) { - PICODBG_DEBUG(("%c", buf[i])); - } else { - PICODBG_DEBUG((" %d", buf[i])); - } - } -#endif - - for (i = 0; i < *blen; i++) { - /* put single byte */ - this->buf[this->rear++] = (picoos_char)buf[i]; - this->rear %= this->size; - this->len++; - } - return PICO_OK; -} - -/*---------------------------------------------------------- - * Names : picodata_cbGetItem - * picodata_cbGetSpeechData - * Function: gets one item from 'this' and writes it on 'blenmax' sized 'buf'. - * gets one item from 'this' and writes the speech data to - * 'blenmax' sized 'buf'. - * Returns : PICO_OK : one item was copied - * PICO_EOF : 'this' is empty; no new items available - * PICO_BUF_UNDERFLOW : 'this' doesn't contain a full/valid item - * PICO_BUF_OVERFLOW : 'buf[blenmax]' too small to hold item - * on return, '*blen' contains the number of bytes written to 'buf' - * ---------------------------------------------------------*/ -pico_status_t picodata_cbGetItem(register picodata_CharBuffer this, - picoos_uint8 *buf, const picoos_uint16 blenmax, - picoos_uint16 *blen) -{ - return this->getItem(this, buf, blenmax, blen, FALSE); -} - -pico_status_t picodata_cbGetSpeechData(register picodata_CharBuffer this, - picoos_uint8 *buf, const picoos_uint16 blenmax, - picoos_uint16 *blen) -{ - - return this->getItem(this, buf, blenmax, blen, TRUE); -} - - -pico_status_t picodata_cbPutItem(register picodata_CharBuffer this, - const picoos_uint8 *buf, const picoos_uint16 blenmax, - picoos_uint16 *blen) -{ - - return this->putItem(this,buf,blenmax,blen); -} - -/* unsafe, just for measuring purposes */ -picoos_uint8 picodata_cbGetFrontItemType(register picodata_CharBuffer this) -{ - return this->buf[this->front]; -} -/* *************************************************************** - * items: support function * - *****************************************************************/ - -picoos_uint8 is_valid_itemtype(const picoos_uint8 ch) { - switch (ch) { - case PICODATA_ITEM_WSEQ_GRAPH: - case PICODATA_ITEM_TOKEN: - case PICODATA_ITEM_WORDGRAPH: - case PICODATA_ITEM_WORDINDEX: - case PICODATA_ITEM_WORDPHON: - case PICODATA_ITEM_SYLLPHON: - case PICODATA_ITEM_BOUND: - case PICODATA_ITEM_PUNC: - case PICODATA_ITEM_CMD: - case PICODATA_ITEM_PHONE: - case PICODATA_ITEM_FRAME: - case PICODATA_ITEM_FRAME_PAR: - return TRUE; - break; - case PICODATA_ITEM_OTHER: - default: - break; - } - PICODBG_WARN(("item type problem: %c", ch)); - return FALSE; -} - -picoos_uint8 picodata_is_valid_itemhead(const picodata_itemhead_t *head) { - if ((NULL != head) && is_valid_itemtype(head->type)) { - return TRUE; - } else { - PICODBG_WARN(("item header problem")); - return FALSE; - } -} - -/* ***************************************************/ - - -pico_status_t picodata_get_itemparts_nowarn( - const picoos_uint8 *buf, const picoos_uint16 blenmax, - picodata_itemhead_t *head, picoos_uint8 *content, - const picoos_uint16 clenmax, picoos_uint16 *clen) -{ - if (blenmax >= PICODATA_ITEM_HEADSIZE) { - head->type = buf[PICODATA_ITEMIND_TYPE]; - head->info1 = buf[PICODATA_ITEMIND_INFO1]; - head->info2 = buf[PICODATA_ITEMIND_INFO2]; - head->len = buf[PICODATA_ITEMIND_LEN]; - *clen = head->len; - if (blenmax >= (*clen + PICODATA_ITEM_HEADSIZE)) { - if (clenmax >= head->len) { - picoos_uint16 i; - for (i=0; ilen; i++) { - content[i] = buf[PICODATA_ITEM_HEADSIZE+i]; - } - return PICO_OK; - } - *clen = 0; - return PICO_EXC_BUF_OVERFLOW; - } - } - *clen = 0; - return PICO_EXC_BUF_UNDERFLOW; -} - -pico_status_t picodata_get_itemparts( - const picoos_uint8 *buf, const picoos_uint16 blenmax, - picodata_itemhead_t *head, picoos_uint8 *content, - const picoos_uint16 clenmax, picoos_uint16 *clen) -{ - pico_status_t status = picodata_get_itemparts_nowarn(buf,blenmax,head,content,clenmax,clen); - if (PICO_EXC_BUF_OVERFLOW == status) { - PICODBG_WARN(("problem getting item, overflow")); - } else if (PICO_EXC_BUF_UNDERFLOW == status) { - PICODBG_WARN(("problem getting item, overflow")); - } - return status; -} -pico_status_t picodata_put_itemparts(const picodata_itemhead_t *head, - const picoos_uint8 *content, const picoos_uint16 clenmax, - picoos_uint8 *buf, const picoos_uint16 blenmax, picoos_uint16 *blen) -{ - *blen = head->len + PICODATA_ITEM_HEADSIZE; - if (blenmax >= *blen) { - if (clenmax >= head->len) { - picoos_uint16 i; - buf[PICODATA_ITEMIND_TYPE] = head->type; - buf[PICODATA_ITEMIND_INFO1] = head->info1; - buf[PICODATA_ITEMIND_INFO2] = head->info2; - buf[PICODATA_ITEMIND_LEN] = head->len; - for (i=0; ilen; i++) { - buf[PICODATA_ITEM_HEADSIZE+i] = content[i]; - } - return PICO_OK; - } - PICODBG_WARN(("problem putting item, underflow")); - *blen = 0; - return PICO_EXC_BUF_UNDERFLOW; - } - PICODBG_WARN(("problem putting item, overflow")); - *blen = 0; - return PICO_EXC_BUF_OVERFLOW; -} - -pico_status_t picodata_get_iteminfo( - picoos_uint8 *buf, const picoos_uint16 blenmax, - picodata_itemhead_t *head, picoos_uint8 **content) { - if (blenmax >= PICODATA_ITEM_HEADSIZE) { - head->type = buf[PICODATA_ITEMIND_TYPE]; - head->info1 = buf[PICODATA_ITEMIND_INFO1]; - head->info2 = buf[PICODATA_ITEMIND_INFO2]; - head->len = buf[PICODATA_ITEMIND_LEN]; - if (head->len == 0) { - *content = NULL; - } else { - *content = &buf[PICODATA_ITEM_HEADSIZE]; - } - return PICO_OK; - } - return PICO_EXC_BUF_UNDERFLOW; -} - -pico_status_t picodata_copy_item(const picoos_uint8 *inbuf, - const picoos_uint16 inlenmax, picoos_uint8 *outbuf, - const picoos_uint16 outlenmax, picoos_uint16 *numb) -{ - if (picodata_is_valid_item(inbuf, inlenmax)) { - *numb = PICODATA_ITEM_HEADSIZE + inbuf[PICODATA_ITEMIND_LEN]; - } else { - *numb = 0; - } - if (*numb > 0) { - if (outlenmax >= inlenmax) { - picoos_uint16 i; - for (i=0; i<*numb; i++) { - outbuf[i] = inbuf[i]; - } - return PICO_OK; - } else { - PICODBG_WARN(("buffer problem, out: %d > in: %d", outlenmax, inlenmax)); - *numb = 0; - return PICO_EXC_BUF_OVERFLOW; - } - } else { - PICODBG_WARN(("item problem in inbuf")); - return PICO_ERR_OTHER; - } -} - -pico_status_t picodata_set_iteminfo1(picoos_uint8 *buf, - const picoos_uint16 blenmax, const picoos_uint8 info) { - if (PICODATA_ITEMIND_INFO1 < blenmax) { - buf[PICODATA_ITEMIND_INFO1] = info; - return PICO_OK; - } else - return PICO_EXC_BUF_UNDERFLOW; -} - -pico_status_t picodata_set_iteminfo2(picoos_uint8 *buf, - const picoos_uint16 blenmax, const picoos_uint8 info) { - if (PICODATA_ITEMIND_INFO2 < blenmax) { - buf[PICODATA_ITEMIND_INFO2] = info; - return PICO_OK; - } else - return PICO_EXC_BUF_UNDERFLOW; -} - -/* sets the len field in the header contained in the item in buf; - return values: - PICO_OK <- all ok - PICO_EXC_BUF_UNDERFLOW <- underflow in buf -*/ -pico_status_t picodata_set_itemlen(picoos_uint8 *buf, - const picoos_uint16 blenmax, const picoos_uint8 len) { - if (PICODATA_ITEMIND_LEN < blenmax) { - buf[PICODATA_ITEMIND_LEN] = len; - return PICO_OK; - } else - return PICO_EXC_BUF_UNDERFLOW; -} - -picoos_uint8 picodata_is_valid_item(const picoos_uint8 *item, - const picoos_uint16 ilenmax) -{ - if (ilenmax >= PICODATA_ITEM_HEADSIZE) { - picodata_itemhead_t head; - head.type = item[0]; - head.info1 = item[1]; - head.info2 = item[2]; - head.len = item[3]; - if ((ilenmax >= (head.len + PICODATA_ITEM_HEADSIZE)) && - picodata_is_valid_itemhead(&head)) - { - return TRUE; - } - } - return FALSE; -} - -/* *************************************************************** - * ProcessingUnit * - *****************************************************************/ -picoos_uint16 picodata_get_default_buf_size (picodata_putype_t puType) -{ - return (PICODATA_PUTYPE_TEXT == puType) ? PICODATA_BUFSIZE_TEXT - : (PICODATA_PUTYPE_TOK == puType) ? PICODATA_BUFSIZE_TOK - : (PICODATA_PUTYPE_PR == puType) ? PICODATA_BUFSIZE_PR - : (PICODATA_PUTYPE_PR == puType) ? PICODATA_BUFSIZE_PR - : (PICODATA_PUTYPE_WA == puType) ? PICODATA_BUFSIZE_WA - : (PICODATA_PUTYPE_SA == puType) ? PICODATA_BUFSIZE_SA - : (PICODATA_PUTYPE_ACPH == puType) ? PICODATA_BUFSIZE_ACPH - : (PICODATA_PUTYPE_SPHO == puType) ? PICODATA_BUFSIZE_SPHO - : (PICODATA_PUTYPE_PAM == puType) ? PICODATA_BUFSIZE_PAM - : (PICODATA_PUTYPE_CEP == puType) ? PICODATA_BUFSIZE_CEP - : (PICODATA_PUTYPE_SIG == puType) ? PICODATA_BUFSIZE_SIG - : (PICODATA_PUTYPE_SINK == puType) ? PICODATA_BUFSIZE_SINK - : PICODATA_BUFSIZE_DEFAULT; -} - - -typedef struct simple_pu_data -{ - picorsrc_Voice voice; -} simple_pu_data_t; - -static pico_status_t puSimpleInitialize (register picodata_ProcessingUnit this) { - return PICO_OK; -} - -static pico_status_t puSimpleTerminate (register picodata_ProcessingUnit this) { - return PICO_OK; -} - -static picodata_step_result_t puSimpleStep (register picodata_ProcessingUnit this, - picoos_int16 mode, - picoos_uint16 * numBytesOutput) { - picoos_int16 ch; - picoos_int16 result = PICO_OK; - mode = mode; /*PP 13.10.08 : fix warning "var not used in this function"*/ - *numBytesOutput = 0; - while ((result == PICO_OK) && (ch = picodata_cbGetCh(this->cbIn)) != PICO_EOF) { - result = picodata_cbPutCh(this->cbOut,(picoos_char) ch); - (*numBytesOutput)++; - } - if (PICO_OK != result) { - (*numBytesOutput)--; - } - if (PICO_OK == result) { - return PICODATA_PU_IDLE; - } else { - return PICODATA_PU_ERROR; - } -} - - -picodata_ProcessingUnit picodata_newProcessingUnit( - picoos_MemoryManager mm, - picoos_Common common, - picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, - picorsrc_Voice voice) -{ - picodata_ProcessingUnit this = (picodata_ProcessingUnit) picoos_allocate(mm, sizeof(*this)); - if (this == NULL) { - picoos_emRaiseException(common->em,PICO_EXC_OUT_OF_MEM,NULL,NULL); - return NULL; - } - this->common = common; - this->cbIn = cbIn; - this->cbOut = cbOut; - this->voice = voice; - this->initialize = puSimpleInitialize; - this->terminate = puSimpleTerminate; - this->step = puSimpleStep; - this->subDeallocate = NULL; - this->subObj = NULL; - return this; -} - -void picodata_disposeProcessingUnit( - picoos_MemoryManager mm, - picodata_ProcessingUnit * this) -{ - if (NULL != (*this)) { - /* terminate */ - if (NULL != (*this)->subObj) { - (*this)->subDeallocate(*this,mm); - } - picoos_deallocate(mm,(void *)this); - } - -} - - -picodata_CharBuffer picodata_getCbIn(picodata_ProcessingUnit this) -{ - if (NULL == this) { - picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL); - return NULL; - } else { - return this->cbIn; - } -} - -picodata_CharBuffer picodata_getCbOut(picodata_ProcessingUnit this) -{ - if (NULL == this) { - picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL); - return NULL; - } else { - return this->cbOut; - } -} - -pico_status_t picodata_setCbIn(picodata_ProcessingUnit this, picodata_CharBuffer cbIn) -{ - if (NULL == this) { - picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL); - return PICO_ERR_OTHER; - } else { - this->cbIn = cbIn; - return PICO_OK; - } - -} - -pico_status_t picodata_setCbOut(picodata_ProcessingUnit this, picodata_CharBuffer cbOut) -{ - if (NULL == this) { - picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL); - return PICO_ERR_OTHER; - } else { - this->cbOut = cbOut; - return PICO_OK; - } -} - - -/* *************************************************************** - * auxiliary functions * - *****************************************************************/ - -static void transDurUniform( - picoos_uint8 frame_duration_exp, /* 2's exponent of frame duration in ms, e.g. 2 for 4ms, 3 for 8ms */ - picoos_int8 array_length, - picoos_uint8 * inout, - picoos_int16 inputdur, /* input duration in ms */ - picoos_int16 targetdur, /* target duration in ms */ - picoos_int16 * restdur /* in/out, rest in ms */ - ) -{ - picoos_int8 i; - picoos_int32 fact, rest; - - /* calculate rest and factor in number of frames (in PICODATA_PICODATA_PRECISION) */ - rest = (*restdur) << (PICODATA_PRECISION - frame_duration_exp); - fact = (targetdur << (PICODATA_PRECISION - frame_duration_exp)) / inputdur; - - for (i = 0; i < array_length; i++) { - rest += fact * inout[i]; - /* instead of rounding, we carry the rest to the next state */ - inout[i] = rest >> PICODATA_PRECISION; - rest -= inout[i] << PICODATA_PRECISION; - } - (*restdur) = rest >> (PICODATA_PRECISION - frame_duration_exp); -} - -static void transDurWeighted( - picoos_uint8 frame_duration_exp, /* 2's exponent of frame duration in ms, e.g. 2 for 4ms, 3 for 8ms */ - picoos_int8 array_length, - picoos_uint8 * inout, - const picoos_uint16 * weight, /* integer weights */ - picoos_int16 inputdur, /* input duration in ms */ - picoos_int16 targetdur, /* target duration in ms */ - picoos_int16 * restdur /* in/out, rest in ms */ - ) -{ - picoos_int8 i; - picoos_int32 fact, rest, out, weighted_sum; - - /* calculate rest and factor in number of frames (in PICODATA_PICODATA_PRECISION) */ - rest = (*restdur) << (PICODATA_PRECISION - frame_duration_exp); - weighted_sum = 0; - for (i=0; i < array_length; i++) { - weighted_sum += inout[i] * weight[i]; - } - if (0 == weighted_sum) { - transDurUniform(frame_duration_exp,array_length,inout,inputdur,targetdur,restdur); - return; - } - /* get the additive change factor in PICODATA_PRECISION: */ - if (targetdur > inputdur) { - fact = ((targetdur - inputdur) << (PICODATA_PRECISION-frame_duration_exp))/ weighted_sum; - } else { - fact = -((inputdur - targetdur) << (PICODATA_PRECISION-frame_duration_exp))/ weighted_sum; - } - - /* input[i] * fact * weight[i] is the additive modification in PICODATA_PRECISION */ - for (i=0; i < array_length; i++) { - rest += fact * inout[i] * weight[i]; - /* instead of rounding, we carry the rest to the next state */ - out = inout[i] + (rest >> PICODATA_PRECISION); - if (out < 0) { - out = 0; - } - rest -= ((out-inout[i]) << PICODATA_PRECISION); - inout[i] = out; - } - (*restdur) = rest >> (PICODATA_PRECISION - frame_duration_exp); -} - - - -void picodata_transformDurations( - picoos_uint8 frame_duration_exp, - picoos_int8 array_length, - picoos_uint8 * inout, - const picoos_uint16 * weight, /* integer weights */ - picoos_int16 mintarget, /* minimum target duration in ms */ - picoos_int16 maxtarget, /* maximum target duration in ms */ - picoos_int16 facttarget, /* factor to be multiplied with original length to get the target - the factor is fixed-point with PICODATA_PRECISION PICODATA_PRECISION, i.e. - the factor as float would be facttarget / PICODATA_PRECISION_FACT - if factor is 0, only min/max are considered */ - picoos_int16 * dur_rest /* in/out, rest in ms */ - ) -{ - picoos_int32 inputdur, targetdur; - picoos_int8 i; - - /* find the original duration in ms */ - inputdur = 0; - for (i=0; i < array_length; i++) { - inputdur += inout[i]; - } - - PICODBG_TRACE(("######## transforming duration fact=%i, limits = [%i,%i] (input frames: %i)",facttarget,mintarget,maxtarget, inputdur)); - - inputdur <<= frame_duration_exp; - - /* find the target duration */ - if (facttarget) { - targetdur = (facttarget * inputdur + PICODATA_PREC_HALF) >> PICODATA_PRECISION; - } else { - targetdur = inputdur; - } - - /* we need to modify input if there is an explicit factor or input is not in the target range */ - if (facttarget || (targetdur < mintarget) || (maxtarget < targetdur)) { - /* make sure we are in the limits */ - if (targetdur < mintarget) { - targetdur = mintarget; - } else if (maxtarget < targetdur) { - targetdur = maxtarget; - } - /* perform modification */ - if (NULL == weight) { - transDurUniform(frame_duration_exp,array_length,inout,inputdur,targetdur,dur_rest); - } else { - transDurWeighted(frame_duration_exp,array_length,inout,weight,inputdur,targetdur,dur_rest); - } - } -} - - - -extern picoos_uint8 picodata_getPuTypeFromExtension(picoos_uchar * filename, picoos_bool input) -{ - if (input) { - if (picoos_has_extension(filename, PICODATA_PUTYPE_TOK_INPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_TOK; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_PR_INPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_PR; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_WA_INPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_WA; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_SA_INPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_SA; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_ACPH_INPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_ACPH; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_SPHO_INPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_SPHO; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_PAM_INPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_PAM; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_CEP_INPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_CEP; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_SIG_INPUT_EXTENSION) || - picoos_has_extension(filename, PICODATA_PUTYPE_WAV_INPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_SIG; - } - else { - return PICODATA_ITEMINFO2_CMD_TO_UNKNOWN; - } - } - else { - if (picoos_has_extension(filename, PICODATA_PUTYPE_TOK_OUTPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_TOK; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_PR_OUTPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_PR; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_WA_OUTPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_WA; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_SA_OUTPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_SA; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_ACPH_OUTPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_ACPH; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_SPHO_OUTPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_SPHO; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_PAM_OUTPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_PAM; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_CEP_OUTPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_CEP; - } - else if (picoos_has_extension(filename, PICODATA_PUTYPE_SIG_OUTPUT_EXTENSION) || - picoos_has_extension(filename, PICODATA_PUTYPE_WAV_OUTPUT_EXTENSION)) { - return PICODATA_ITEMINFO2_CMD_TO_SIG; - } - else { - return PICODATA_ITEMINFO2_CMD_TO_UNKNOWN; - } - } - return PICODATA_ITEMINFO2_CMD_TO_UNKNOWN; -} - - - - -/** - * - * @param transducer - * @param common - * @param xsampa_parser - * @param svoxpa_parser - * @param xsampa2svoxpa_mapper - * @param inputPhones - * @param alphabet - * @param outputPhoneIds - * @param maxOutputPhoneIds - * @return - */ -pico_status_t picodata_mapPAStrToPAIds(picotrns_SimpleTransducer transducer, - picoos_Common common, picokfst_FST xsampa_parser, - picokfst_FST svoxpa_parser, picokfst_FST xsampa2svoxpa_mapper, - picoos_uchar * inputPhones, picoos_uchar * alphabet, - picoos_uint8 * outputPhoneIds, picoos_int32 maxOutputPhoneIds) -{ - pico_status_t status = PICO_OK; - if (picoos_strcmp(alphabet, PICODATA_XSAMPA) == 0) { - if ((NULL != xsampa_parser) && (NULL != xsampa2svoxpa_mapper)) { - picotrns_stInitialize(transducer); - status = picotrns_stAddWithPlane(transducer, inputPhones, - PICOKFST_PLANE_ASCII); - if (PICO_OK != status) { - picoos_emRaiseWarning(common->em, status, NULL, - (picoos_char *) "phoneme sequence too long (%s)", - inputPhones); - } else { - status = picotrns_stTransduce(transducer, xsampa_parser); - if (PICO_OK != status) { - picoos_emRaiseWarning(common->em, status, NULL, - (picoos_char *) "not recognized as xsampa (%s)", - inputPhones); - } else { - status = picotrns_stTransduce(transducer, xsampa2svoxpa_mapper); - if (PICO_OK != status) { - picoos_emRaiseWarning(common->em, status, NULL, - (picoos_char *) "illeagal phoneme sequence (%s)", - inputPhones); - } else { - status = picotrns_stGetSymSequence(transducer, outputPhoneIds, - maxOutputPhoneIds); - } - } - } - return status; - } - } else if (picoos_strcmp(alphabet, PICODATA_SVOXPA) == 0) { - if ((NULL != svoxpa_parser)) { - picotrns_stInitialize(transducer); - status = picotrns_stAddWithPlane(transducer, inputPhones, - PICOKFST_PLANE_ASCII); - if (PICO_OK == status) { - status = picotrns_stTransduce(transducer, svoxpa_parser); - } - if (PICO_OK == status) { - status = picotrns_stGetSymSequence(transducer, outputPhoneIds, - maxOutputPhoneIds); - } - return status; - } - } - picoos_strlcpy(outputPhoneIds, (picoos_char *) "", maxOutputPhoneIds); - picoos_emRaiseWarning(common->em, PICO_EXC_NAME_ILLEGAL, NULL, - (picoos_char *) "alphabet not supported (%s)", alphabet); - return PICO_EXC_NAME_ILLEGAL; - -} - -#if defined (PICO_DEBUG) -/* *************************************************************** - * For Debugging only * - *****************************************************************/ - - -/* put string representation of 'itemtype' into 'str' (allocated size 'strsize') - * return 'str' */ -static picoos_char * data_itemtype_to_string(const picoos_uint8 itemtype, - picoos_char * str, picoos_uint16 strsize) -{ - picoos_char * tmpstr; - switch (itemtype) { - case PICODATA_ITEM_BOUND: - tmpstr = (picoos_char *)"BOUND"; - break; - case PICODATA_ITEM_FRAME_PAR: - tmpstr = (picoos_char *)"FRAME_PAR"; - break; - case PICODATA_ITEM_PHONE: - tmpstr = (picoos_char *)"PHONE"; - break; - case PICODATA_ITEM_CMD: - tmpstr = (picoos_char *)"CMD"; - break; - case PICODATA_ITEM_ERR: - tmpstr = (picoos_char *)"ERR"; - break; - case PICODATA_ITEM_FRAME: - tmpstr = (picoos_char *)"FRAME"; - break; - case PICODATA_ITEM_OTHER: - tmpstr = (picoos_char *)"OTHER"; - break; - case PICODATA_ITEM_PUNC: - tmpstr = (picoos_char *)"PUNC"; - break; - case PICODATA_ITEM_SYLLPHON: - tmpstr = (picoos_char *)"SYLLPHON"; - break; - case PICODATA_ITEM_WORDGRAPH: - tmpstr = (picoos_char *)"WORDGRAPH"; - break; - case PICODATA_ITEM_WORDINDEX: - tmpstr = (picoos_char *)"WORDINDEX"; - break; - case PICODATA_ITEM_WORDPHON: - tmpstr = (picoos_char *)"WORDPHON"; - break; - case PICODATA_ITEM_WSEQ_GRAPH: - tmpstr = (picoos_char *)"WSEQ_GRAPH"; - break; - default: - tmpstr = (picoos_char *)"UNKNOWN"; - break; - } - picopal_slprintf((picopal_char *) str, strsize, (picopal_char *)"%s", - tmpstr); - return str; -} - - -picoos_char * picodata_head_to_string(const picodata_itemhead_t *head, - picoos_char * str, picoos_uint16 strsize) -{ - picoos_uint16 typelen; - - if (NULL == head) { - picoos_strlcpy(str,(picoos_char *)"[head is NULL]",strsize); - } else { - data_itemtype_to_string(head->type, str, strsize); - typelen = picoos_strlen(str); - picopal_slprintf((picopal_char *) str+typelen, strsize-typelen, - (picopal_char *)"|%c|%c|%i", head->info1, head->info2, - head->len); - } - - return str; -} - -void picodata_info_item(const picoknow_KnowledgeBase kb, - const picoos_uint8 *pref6ch, - const picoos_uint8 *item, - const picoos_uint16 itemlenmax, - const picoos_char *filterfn) -{ -#define SA_USE_PHST 1 - picoos_uint16 i; - picoos_uint8 ch; - - if ((itemlenmax < 4) || (item == NULL)) { - PICODBG_INFO_MSG(("invalid item\n")); - } - - /* first 6 char used for prefix */ - PICODBG_INFO_MSG_F(filterfn, ("%6s(", pref6ch)); - - /* type */ - ch = item[0]; - if ((32 <= ch) && (ch < 127)) { - PICODBG_INFO_MSG_F(filterfn, ("'%c',", ch)); - } else { - PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); - } - /* info1 */ - ch = item[1]; - if ((32 <= ch) && (ch < 127)) - switch (item[0]) { - case PICODATA_ITEM_PUNC: - case PICODATA_ITEM_BOUND: - case PICODATA_ITEM_CMD: - case PICODATA_ITEM_TOKEN: - case PICODATA_ITEM_FRAME_PAR: - PICODBG_INFO_MSG_F(filterfn, ("'%c',", ch)); - break; - default: - PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); - } - else - PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); - - /* info2 */ - ch = item[2]; - if ((32 <= ch) && (ch < 127)) - switch (item[0]) { - case PICODATA_ITEM_PUNC: - case PICODATA_ITEM_BOUND: - case PICODATA_ITEM_CMD: - case PICODATA_ITEM_WORDPHON: - case PICODATA_ITEM_SYLLPHON: - PICODBG_INFO_MSG_F(filterfn, ("'%c',", ch)); - break; - default: - PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); - } - else - PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); - - /* len */ - ch = item[3]; - PICODBG_INFO_MSG_F(filterfn, ("%3d)", ch)); - - for (i = 0; i < ch; i++) { - if ((item[0] == PICODATA_ITEM_WSEQ_GRAPH) || - (item[0] == PICODATA_ITEM_TOKEN) || - (item[0] == PICODATA_ITEM_WORDGRAPH) || - ((item[0] == PICODATA_ITEM_CMD) && !((item[1] == PICODATA_ITEMINFO1_CMD_SPEED) || - (item[1] == PICODATA_ITEMINFO1_CMD_PITCH) || - (item[1] == PICODATA_ITEMINFO1_CMD_VOLUME) || - (item[1] == PICODATA_ITEMINFO1_CMD_SPELL) || - (item[1] == PICODATA_ITEMINFO1_CMD_SIL)))) { - PICODBG_INFO_MSG_F(filterfn, ("%c", item[4 + i])); - } else { - PICODBG_INFO_MSG_F(filterfn, ("%4d", item[4 + i])); - } - } - -#if defined (SA_USE_PHST) - { -#include "picokdbg.h" - picoos_uint8 j; - picokdbg_Dbg kdbg; - kdbg = picokdbg_getDbg(kb); - - if ((item[0] == PICODATA_ITEM_WORDPHON) || - (item[0] == PICODATA_ITEM_SYLLPHON) || - ((item[0] == PICODATA_ITEM_CMD) && (item[1] == PICODATA_ITEMINFO1_CMD_PHONEME))) { - if (picokdbg_getPhoneSym(kdbg, item[4])) { - PICODBG_INFO_MSG_F(filterfn, (" ")); - for (j = 0; j < item[3]; j++) { - PICODBG_INFO_MSG_F(filterfn, ("%s", - picokdbg_getPhoneSym(kdbg, item[4 + j]))); - } - } - } - } -#endif - - PICODBG_INFO_MSG_F(filterfn, ("\n")); -} - - -#endif /* PICO_DEBUG */ - -#ifdef __cplusplus -} -#endif - - -/* picodata.c end */ diff --git a/lib/picodata.h b/lib/picodata.h deleted file mode 100644 index 637a3ff..0000000 --- a/lib/picodata.h +++ /dev/null @@ -1,643 +0,0 @@ -/* - * 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 picodata.h - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -#ifndef PICODATA_H_ -#define PICODATA_H_ - -#include "picodefs.h" -#include "picoos.h" -#include "picotrns.h" -#include "picokfst.h" -#include "picorsrc.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* *************************************************************** - * Constants * - *****************************************************************/ - -#define PICODATA_MAX_ITEMS_PER_PHRASE 30 - -/** - * @addtogroup picodata - * Pico Data : Item Format \n - * - The item header is identical for all item types and PUs. Item types - that are not handled by a PU are copied. - - Item Header structure\n - --------------------- - - Byte Content - - 0x00 item type - - 0x01 item info 1 - - 0x02 item info 2 - - 0x03 item length in bytes (not including the header) - - depending on the item type/info, a specific subheader may follow - (included in length) -*/ - -/* item header fields (tmp.: use item functions below to acces header fields */ -#define PICODATA_ITEMIND_TYPE 0 -#define PICODATA_ITEMIND_INFO1 1 -#define PICODATA_ITEMIND_INFO2 2 -#define PICODATA_ITEMIND_LEN 3 - -/* *************************************************************** - * CharBuffer * - *****************************************************************/ -typedef struct picodata_char_buffer * picodata_CharBuffer; - -picodata_CharBuffer picodata_newCharBuffer(picoos_MemoryManager mm, - picoos_Common common, picoos_objsize_t size); - -void picodata_disposeCharBuffer(picoos_MemoryManager mm, - picodata_CharBuffer * this); - -/* should not be used for PUs but only for feeding the initial cb */ -pico_status_t picodata_cbPutCh(register picodata_CharBuffer this, picoos_char ch); - -/* should not be used for PUs other than first PU in the chain (picotok) */ -picoos_int16 picodata_cbGetCh(register picodata_CharBuffer this); - -/* reset cb (as if after newCharBuffer) */ -pico_status_t picodata_cbReset (register picodata_CharBuffer this); - -/* ** CharBuffer item functions, cf. below in items section ****/ - -/* *************************************************************** - * items * - *****************************************************************/ - -/* item header size */ -#define PICODATA_ITEM_HEADSIZE 4 - -typedef struct picodata_itemhead -{ - picoos_uint8 type; - picoos_uint8 info1; - picoos_uint8 info2; - picoos_uint8 len; -} picodata_itemhead_t; - - -/* -------------- System wide defines referred to by items -------- */ -/* ---- These maybe better stored in a knowledge module/resoruce*/ -#define PICODATA_ACC0 '\x30' /* 48 '0' */ -#define PICODATA_ACC1 '\x31' /* 49 '1' */ -#define PICODATA_ACC2 '\x32' /* 50 '2' */ -#define PICODATA_ACC3 '\x33' /* 51 '3' */ -#define PICODATA_ACC4 '\x34' /* 52 '4' */ - -/* reserved for future use: - * user-imposed Part-Of-Speech ids for user lexica and phoneme tags - * These values should be applied BEFORE POS-disambiguation. The POS lingware either assigns the same - * ids to corresponding internal unique or composed POS or else the POS-D will consider these values - * "default" */ -#define PICODATA_POS_XNPR 20 -#define PICODATA_POS_XN 21 -#define PICODATA_POS_XV 22 -#define PICODATA_POS_XA 23 -#define PICODATA_POS_XADV 24 -#define PICODATA_POS_XX 25 - -/* ------------------------- item types ---------------------------- */ -/* new item types, info1, info2 to be defined during PU development */ -/* make sure this stays in sync with "is_valid_itemtype" function */ -#define PICODATA_ITEM_WSEQ_GRAPH '\x73' /* 115, 's' */ -#define PICODATA_ITEM_TOKEN '\x74' /* 116 't' */ -#define PICODATA_ITEM_WORDGRAPH '\x67' /* 103 'g' */ -#define PICODATA_ITEM_WORDINDEX '\x69' /* 105 'i' */ -#define PICODATA_ITEM_WORDPHON '\x77' /* 119 'w' */ -#define PICODATA_ITEM_SYLLPHON '\x79' /* 121 'y' */ -#define PICODATA_ITEM_BOUND '\x62' /* 98 'b' */ -/* #define PICODATA_ITEM_BOUND_DUR '\x64' */ /* 100 'd' */ /* duration-constrained bound */ -#define PICODATA_ITEM_PUNC '\x70' /* 112 'p' */ -#define PICODATA_ITEM_CMD '\x63' /* 99 'c' */ -#define PICODATA_ITEM_PHONE '\x68' /* 104 'h' */ /*reserved for PAM*/ -#define PICODATA_ITEM_FRAME_PAR '\x6b' /* 107 'k' */ /*reserved for CEP*/ -#define PICODATA_ITEM_FRAME '\x66' /* 102 'f' */ /*reserved for SIG*/ -#define PICODATA_ITEM_OTHER '\x6f' /* 111 'o' */ -#define PICODATA_ITEM_ERR '\x00' /* 0 '^@' */ - -/* generic iteminfo1 */ -#define PICODATA_ITEMINFO1_ERR '\x00' /* 0 '^@' */ /* error state */ -#define PICODATA_ITEMINFO1_NA '\x01' /* 1 '^A' */ /* not applicable */ - -/* generic iteminfo2 */ -#define PICODATA_ITEMINFO2_ERR '\x00' /* 0 '^@' */ /* error state */ -#define PICODATA_ITEMINFO2_NA '\x01' /* 1 '^A' */ /* not applicable */ - -/* ------------------------- PUNC item type ---------------------------- */ -/* iteminfo1 */ -#define PICODATA_ITEMINFO1_PUNC_SENTEND '\x73' /* 115 's' */ -#define PICODATA_ITEMINFO1_PUNC_PHRASEEND '\x70' /* 112 'p' */ -#define PICODATA_ITEMINFO1_PUNC_FLUSH '\x66' /* 102 'f' */ -/* iteminfo2 */ -#define PICODATA_ITEMINFO2_PUNC_SENT_T '\x74' /* 116 't' */ -#define PICODATA_ITEMINFO2_PUNC_SENT_Q '\x71' /* 113 'q' */ -#define PICODATA_ITEMINFO2_PUNC_SENT_E '\x65' /* 101 'e' */ -#define PICODATA_ITEMINFO2_PUNC_PHRASE '\x70' /* 112 'p' */ -#define PICODATA_ITEMINFO2_PUNC_PHRASE_FORCED '\x66' /* 102 'f' */ -/* len for PUNC item is ALWAYS = 0 */ -/* ------------------------- BOUND item type ---------------------------- */ -/* iteminfo1 : phrase strength*/ -#define PICODATA_ITEMINFO1_BOUND_SBEG '\x62' /* 98 'b', at sentence begin */ -#define PICODATA_ITEMINFO1_BOUND_SEND '\x73' /* 115 's', at sentence end */ -#define PICODATA_ITEMINFO1_BOUND_TERM '\x74' /* 116 't', replaces a flush */ -#define PICODATA_ITEMINFO1_BOUND_PHR0 '\x30' /* 48 '0', no break, no item */ -#define PICODATA_ITEMINFO1_BOUND_PHR1 '\x31' /* 49 '1', pri. phrase bound. */ -#define PICODATA_ITEMINFO1_BOUND_PHR2 '\x32' /* 50 '2', short break */ -#define PICODATA_ITEMINFO1_BOUND_PHR3 '\x33' /* 51 '3', sec. phr. bound., no break*/ -/* iteminfo2 : phrase type*/ -#define PICODATA_ITEMINFO2_BOUNDTYPE_P '\x50' /* 80 'P' */ -#define PICODATA_ITEMINFO2_BOUNDTYPE_T '\x54' /* 84 'T' */ -#define PICODATA_ITEMINFO2_BOUNDTYPE_Q '\x51' /* 81 'Q' */ -#define PICODATA_ITEMINFO2_BOUNDTYPE_E '\x45' /* 69 'E' */ -/* len for BOUND item is ALWAYS = 0 */ -/* ------------------------- CMD item type ---------------------------- */ -/* iteminfo1 */ -#define PICODATA_ITEMINFO1_CMD_FLUSH 'f' /* 102 flush command (all PUs)*/ -#define PICODATA_ITEMINFO1_CMD_PLAY 'p' /* 112 play command : PU in info 2 will read items from file-->Filename in item content.*/ -#define PICODATA_ITEMINFO1_CMD_SAVE 's' /* 115 save command : PU in info 2 will save items to file-->Filename in item content.*/ -#define PICODATA_ITEMINFO1_CMD_UNSAVE 'u' /* 117 save command : PU in info 2 will stop saving items to file*/ -#define PICODATA_ITEMINFO1_CMD_PROSDOMAIN 'd' /* 100 prosody domain : domain type in info 2, domain name in item content */ -#define PICODATA_ITEMINFO1_CMD_SPELL 'e' /* 101 spell command : info 2 contains start/stop info, - spell type/pause len as little endian uint16 in item content */ -#define PICODATA_ITEMINFO1_CMD_IGNSIG 'i' /* ignore signal command : info 2 contains start/stop info */ -#define PICODATA_ITEMINFO1_CMD_PHONEME 'o' /* phoneme command : info 2 contains start/stop info, phonemes in item content */ -#define PICODATA_ITEMINFO1_CMD_IGNORE 'I' /* ignore text command : info 2 contains start/stop info */ -#define PICODATA_ITEMINFO1_CMD_SIL 'z' /* silence command : info 2 contains type of silence; - silence duration as little endian uint16 in item content */ -#define PICODATA_ITEMINFO1_CMD_CONTEXT 'c' /* context command : context name in item content */ -#define PICODATA_ITEMINFO1_CMD_VOICE 'v' /* context command : voice name in item content */ -#define PICODATA_ITEMINFO1_CMD_MARKER 'm' /* marker command : marker name in item content */ -#define PICODATA_ITEMINFO1_CMD_PITCH 'P' /* 80 pitch command : abs/rel info in info 2; pitch level as little endian - uint16 in item content; relative value is in promille */ -#define PICODATA_ITEMINFO1_CMD_SPEED 'R' /* 82 speed command : abs/rel info in info 2, speed level as little endian - uint16 in item content; elative value is in promille */ -#define PICODATA_ITEMINFO1_CMD_VOLUME 'V' /* 86 volume command : abs/rel info in info 2, volume level as little endian - uint16 in item content; relative value is in promille */ -#define PICODATA_ITEMINFO1_CMD_SPEAKER 'S' /* 83 speaker command : abs/rel info in info 2, speaker level as little endian - uint16 in item content; relative value is in promille */ - -/* iteminfo2 for PLAY/SAVE */ -#define PICODATA_ITEMINFO2_CMD_TO_TOK 't' /* CMD+PLAY/SAVE+TOKENISATION*/ -#define PICODATA_ITEMINFO2_CMD_TO_PR 'g' /* CMD+PLAY/SAVE+PREPROC*/ -#define PICODATA_ITEMINFO2_CMD_TO_WA 'w' /* CMD+PLAY/SAVE+WORDANA*/ -#define PICODATA_ITEMINFO2_CMD_TO_SA 'a' /* CMD+PLAY/SAVE+SENTANA*/ -#define PICODATA_ITEMINFO2_CMD_TO_ACPH 'h' /* CMD+PLAY/SAVE+ACCENTUATION&PHRASING*/ -#define PICODATA_ITEMINFO2_CMD_TO_SPHO 'p' /* CMD+PLAY/SAVE+ACCENTUATION&PHRASING*/ -#define PICODATA_ITEMINFO2_CMD_TO_PAM 'q' /* CMD+PLAY/SAVE+PHONETIC-ACOUSTIC MAPPING*/ -#define PICODATA_ITEMINFO2_CMD_TO_CEP 'c' /* CMD+PLAY/SAVE+CEP_SMOOTHER*/ -#define PICODATA_ITEMINFO2_CMD_TO_SIG 's' /* CMD+PLAY/SAVE+SIG_GEN */ - -#if 0 -#define PICODATA_ITEMINFO2_CMD_TO_FST 'f' /* CMD+PLAY/SAVE+FST for Syll and Phonotactic constraints*/ -#endif - -#define PICODATA_ITEMINFO2_CMD_TO_UNKNOWN 255 - -/* iteminfo2 for start/end commands */ -#define PICODATA_ITEMINFO2_CMD_START 's' -#define PICODATA_ITEMINFO2_CMD_END 'e' - -/* iteminfo2 for speed/pitch/volume commands */ -#define PICODATA_ITEMINFO2_CMD_ABSOLUTE 'a' -#define PICODATA_ITEMINFO2_CMD_RELATIVE 'r' - -/* len for CMD item could be >= 0 */ -/* ------------------------- TOKEN item type ---------------------------- */ -/* iteminfo1: simple token type : */ -#define PICODATA_ITEMINFO1_TOKTYPE_SPACE 'W' -#define PICODATA_ITEMINFO1_TOKTYPE_LETTERV 'V' -#define PICODATA_ITEMINFO1_TOKTYPE_LETTER 'L' -#define PICODATA_ITEMINFO1_TOKTYPE_DIGIT 'D' -#define PICODATA_ITEMINFO1_TOKTYPE_SEQ 'S' -#define PICODATA_ITEMINFO1_TOKTYPE_CHAR 'C' -#define PICODATA_ITEMINFO1_TOKTYPE_BEGIN 'B' -#define PICODATA_ITEMINFO1_TOKTYPE_END 'E' -#define PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED 'U' -/* iteminfo2 : token subtype */ -/* len for WORDTOK item is ALWAYS > 0, if len==0 an error should be raised */ - -/** - * @addtogroup picodata - * - * ------------------------- WORDGRAPH item type ---------------------------- - * - iteminfo1 : POS and multi-POS values defined in lingware - * - iteminfo2 : not applicable - * - len for WORDGRAPH item is ALWAYS > 0, if len==0 an error should be raised - * (currently picopr may produce empty WORDGRAPH that is eliminated by picowa) - * \n------------------------- WORDINDEX item type ---------------------------- - * - iteminfo1 : POS and multi-POS values defined in lingware - * - iteminfo2 : not applicable - * - len for WORDINDEX item is ALWAYS > 0, if len==0 an error should be raised - * \n------------------------- WORDPHON item type ---------------------------- - * - iteminfo1 : POS values defined in lingware - * - iteminfo2 : Uses PICODATA_ACC0 .. ACC4 - * -len WORDPHON item is ALWAYS > 0, if len==0 an error should be raised - * \n------------------------- SYLLPHON item type ---------------------------- - * - iteminfo1 : not applicable - * - iteminfo2 : Uses PICODATA_ACC0 .. ACC4 - * - len for SYLLPHON item is ALWAYS > 0, if len==0 an error should be raised - * \n------------------------- PHONE item type (PRODUCED BY PAM)----------------- - * - iteminfo1 : phonId : the phonetic identity of the phone - * - iteminfo2 : n_S_P_Phone : number of states per phoneme - * - len for PHON item is ALWAYS > 0, if len==0 an error should be raised - * \n------------------------- FRAME_PAR item type (PRODUCED BY CEP) -------- - * - iteminfo1 : format (float, fixed) - * - iteminfo2 : vector size - * - len for FRAME_PAR item is ALWAYS > 0, if len==0 an error should be raised - * \n------------------------- FRAME item type (PRODUCED BY SIG) ----------- - * - iteminfo1 : number of samples per frame - * - iteminfo2 : number of bytes per sample - * - len for FRAME item is ALWAYS > 0, if len==0 an error should be raised - * - */ -#define PICODATA_ITEMINFO1_FRAME_PAR_DATA_FORMAT_FIXED '\x78' /* 120 'x' fixed point */ -#define PICODATA_ITEMINFO1_FRAME_PAR_DATA_FORMAT_FLOAT '\x66' /* 102 'f' floating point */ - -/* *************************************************************** - * items: CharBuffer functions * - *****************************************************************/ - -/* gets a single item (head and content) from a CharBuffer in buf; - blenmax is the max length (in number of bytes) of buf; blen is - set to the number of bytes gotten in buf; return values: - PICO_OK <- one item gotten - PICO_EOF <- no item available, cb is empty - PICO_EXC_BUF_UNDERFLOW <- cb not empty, but no valid item - PICO_EXC_BUF_OVERFLOW <- buf not large enough -*/ -pico_status_t picodata_cbGetItem(register picodata_CharBuffer this, - picoos_uint8 *buf, const picoos_uint16 blenmax, - picoos_uint16 *blen); - -/* gets the speech data (without item head) from a CharBuffer in buf; - blenmax is the max length (in number of bytes) of buf; blen is - set to the number of bytes gotten in buf; return values: - PICO_OK <- speech data of one item gotten - PICO_EOF <- no item available, cb is empty - PICO_EXC_BUF_UNDERFLOW <- cb not empty, but no valid item - PICO_EXC_BUF_OVERFLOW <- buf not large enough -*/ -pico_status_t picodata_cbGetSpeechData(register picodata_CharBuffer this, - picoos_uint8 *buf, const picoos_uint16 blenmax, - picoos_uint16 *blen); - -/* puts a single item (head and content) to a CharBuffer; clenmax is - the max length (in number of bytes) accessible in content; clen is - set to the number of bytes put from content; return values: - PICO_OK <- one item put - PICO_EXC_BUF_UNDERFLOW <- no valid item in buf - PICO_EXC_BUF_OVERFLOW <- cb not large enough -*/ -pico_status_t picodata_cbPutItem(register picodata_CharBuffer this, - const picoos_uint8 *buf, const picoos_uint16 blenmax, - picoos_uint16 *blen); - -/* unsafe, just for measuring purposes */ -picoos_uint8 picodata_cbGetFrontItemType(register picodata_CharBuffer this); - -/* *************************************************************** - * items: support function * - *****************************************************************/ - -/* checks, whether item of type 'ch' is a valid item type */ -picoos_uint8 is_valid_itemtype(const picoos_uint8 ch); - -/* gets from buf a single item, values in head set and item content - copied to content; blenmax and clenmax are the max lengths (in - number of bytes) accessible in buf and content; clen is set to the - number of bytes gotten in content; return values: - PICO_OK <- all ok - PICO_EXC_BUF_UNDERFLOW <- blenmax problem, or no valid item - PICO_EXC_BUF_OVERFLOW <- overflow in content -*/ -pico_status_t picodata_get_itemparts_nowarn( - const picoos_uint8 *buf, const picoos_uint16 blenmax, - picodata_itemhead_t *head, picoos_uint8 *content, - const picoos_uint16 clenmax, picoos_uint16 *clen); - -/* gets from buf a single item, values in head set and item content - copied to content; blenmax and clenmax are the max lengths (in - number of bytes) accessible in buf and content; clen is set to the - number of bytes gotten in content; return values: - PICO_OK <- all ok - PICO_EXC_BUF_UNDERFLOW <- blenmax problem, or no valid item - PICO_EXC_BUF_OVERFLOW <- overflow in content -*/ -pico_status_t picodata_get_itemparts( - const picoos_uint8 *buf, const picoos_uint16 blenmax, - picodata_itemhead_t *head, picoos_uint8 *content, - const picoos_uint16 clenmax, picoos_uint16 *clen); - -/* puts a single item to buf; values in head and content copied to - buf; clenmax is the max length (in number of bytes) accessible in - content; blenmax is the max length (bytes) accessible in buf; blen - is set to the number of bytes put to buf; return values: - PICO_OK <- all ok - PICO_EXC_BUF_UNDERFLOW <- clenmax problem, or no valid item - PICO_EXC_BUF_OVERFLOW <- overflow in buf -*/ -pico_status_t picodata_put_itemparts(const picodata_itemhead_t *head, - const picoos_uint8 *content, const picoos_uint16 clenmax, - picoos_uint8 *buf, const picoos_uint16 blenmax, picoos_uint16 *blen); - -/* gets from buf info of a single item, values in head are set and - content is set to the start of content in buf (not copied!); - content is set to NULL if the content length is 0; blenmax is the - max lengths (in number of bytes) accessible in buf; return values: - PICO_OK <- all ok - PICO_EXC_BUF_UNDERFLOW <- blenmax problem, or no valid item -*/ -pico_status_t picodata_get_iteminfo( - picoos_uint8 *buf, const picoos_uint16 blenmax, - picodata_itemhead_t *head, picoos_uint8 **content); - -/* copies the item in inbuf to outbuf after first checking if there is - a valid item in inbuf; inlenmax and outlenmax are the max length - (in number of byte) accessible in the buffers); in *numb the total - number of bytes copied to outbuf (incl. header) is returned; return - values: - PICO_OK <- item copied - PICO_EXC_BUF_OVERFLOW <- overflow in outbuf - PICO_ERR_OTHER <- no valid item in inbuf -*/ -pico_status_t picodata_copy_item(const picoos_uint8 *inbuf, - const picoos_uint16 inlenmax, picoos_uint8 *outbuf, - const picoos_uint16 outlenmax, picoos_uint16 *numb); - -/* sets the info1 field in the header contained in the item in buf; - return values: - PICO_OK <- all ok - PICO_EXC_BUF_UNDERFLOW <- underflow in buf -*/ -pico_status_t picodata_set_iteminfo1(picoos_uint8 *buf, - const picoos_uint16 blenmax, const picoos_uint8 info); - -/* sets the info2 field in the header contained in the item in buf; - return values: - PICO_OK <- all ok - PICO_EXC_BUF_UNDERFLOW <- underflow in buf -*/ -pico_status_t picodata_set_iteminfo2(picoos_uint8 *buf, - const picoos_uint16 blenmax, const picoos_uint8 info); - -/* sets the len field in the header contained in the item in buf; - return values: - PICO_OK <- all ok - PICO_EXC_BUF_UNDERFLOW <- underflow in buf -*/ -pico_status_t picodata_set_itemlen(picoos_uint8 *buf, - const picoos_uint16 blenmax, const picoos_uint8 len); - -/* check item validity and return TRUE if valid; return FALSE if - invalid; ilenmax is the max index to be used in item -*/ -picoos_uint8 picodata_is_valid_item(const picoos_uint8 *item, - const picoos_uint16 ilenmax); - -/* return TRUE if head is a valid item head, FALSE otherwise */ -picoos_uint8 picodata_is_valid_itemhead(const picodata_itemhead_t *head); - - -/* *************************************************************** - * ProcessingUnit * - *****************************************************************/ -/* public */ - -#define PICODATA_MAX_ITEMSIZE (picoos_uint16) (PICODATA_ITEM_HEADSIZE + 256) - -/* different buffer sizes per processing unit */ -#define PICODATA_BUFSIZE_DEFAULT (picoos_uint16) PICODATA_MAX_ITEMSIZE -#define PICODATA_BUFSIZE_TEXT (picoos_uint16) 1 * PICODATA_BUFSIZE_DEFAULT -#define PICODATA_BUFSIZE_TOK (picoos_uint16) 2 * PICODATA_BUFSIZE_DEFAULT -#define PICODATA_BUFSIZE_PR (picoos_uint16) 2 * PICODATA_BUFSIZE_DEFAULT -#define PICODATA_BUFSIZE_WA (picoos_uint16) 2 * PICODATA_BUFSIZE_DEFAULT -#define PICODATA_BUFSIZE_SA (picoos_uint16) 2 * PICODATA_BUFSIZE_DEFAULT -#define PICODATA_BUFSIZE_ACPH (picoos_uint16) 2 * PICODATA_BUFSIZE_DEFAULT -#define PICODATA_BUFSIZE_SPHO (picoos_uint16) 4 * PICODATA_BUFSIZE_DEFAULT -#define PICODATA_BUFSIZE_PAM (picoos_uint16) 4 * PICODATA_BUFSIZE_DEFAULT -#define PICODATA_BUFSIZE_CEP (picoos_uint16) 16 * PICODATA_BUFSIZE_DEFAULT -#define PICODATA_BUFSIZE_SIG (picoos_uint16) 16 * PICODATA_BUFSIZE_DEFAULT -#define PICODATA_BUFSIZE_SINK (picoos_uint16) 1 * PICODATA_BUFSIZE_DEFAULT - -/* different types of processing units */ -typedef enum picodata_putype { - PICODATA_PUTYPE_TEXT, /* text */ - PICODATA_PUTYPE_TOK, /* tokenizer output */ - PICODATA_PUTYPE_PR, /* preprocessor output */ - PICODATA_PUTYPE_WA, /* word analysis */ - PICODATA_PUTYPE_SA, /* sentence analysis */ - PICODATA_PUTYPE_ACPH, /* accentuation and phrasing */ - PICODATA_PUTYPE_SPHO, /* sentence phonology (textana postproc) */ - PICODATA_PUTYPE_PAM, /* phonetics to acoustics mapper processing unit */ - PICODATA_PUTYPE_CEP, /* cepstral smoothing processing unit */ - PICODATA_PUTYPE_SIG, /* signal generation processing unit*/ - PICODATA_PUTYPE_SINK /* item sink unit*/ -} picodata_putype_t; - -picoos_uint16 picodata_get_default_buf_size (picodata_putype_t puType); - -/* result values returned from the pu->puStep() methode */ -typedef enum picodata_step_result { - PICODATA_PU_ERROR, - /* PICODATA_PU_EMPTY, *//* reserved (no internal data to be processed) */ - PICODATA_PU_IDLE, /* need more input to process internal data */ - PICODATA_PU_BUSY, /* processing internal data */ - PICODATA_PU_ATOMIC, /* same as pu_busy, but wants to get next time slot (while in an "atomar" operation) */ - PICODATA_PU_OUT_FULL /* can't proceed because output is full. (next time slot to be assigned to pu's output's consumer) */ -} picodata_step_result_t; - -typedef struct picodata_processing_unit * picodata_ProcessingUnit; - -picodata_ProcessingUnit picodata_newProcessingUnit( - picoos_MemoryManager mm, - picoos_Common common, - picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, - picorsrc_Voice voice); - -void picodata_disposeProcessingUnit( - picoos_MemoryManager mm, - picodata_ProcessingUnit * this); - -picodata_CharBuffer picodata_getCbIn(picodata_ProcessingUnit this); -picodata_CharBuffer picodata_getCbOut(picodata_ProcessingUnit this); -pico_status_t picodata_setCbIn(picodata_ProcessingUnit this, picodata_CharBuffer cbIn); -pico_status_t picodata_setCbOut(picodata_ProcessingUnit this, picodata_CharBuffer cbOut); - -/* protected */ -typedef pico_status_t (* picodata_puInitializeMethod) (register picodata_ProcessingUnit this); -typedef pico_status_t (* picodata_puTerminateMethod) (register picodata_ProcessingUnit this); -typedef picodata_step_result_t (* picodata_puStepMethod) (register picodata_ProcessingUnit this, picoos_int16 mode, picoos_uint16 * numBytesOutput); -typedef pico_status_t (* picodata_puSubDeallocateMethod) (register picodata_ProcessingUnit this, picoos_MemoryManager mm); - -typedef struct picodata_processing_unit -{ - /* public */ - picodata_puInitializeMethod initialize; - picodata_puStepMethod step; - picodata_puTerminateMethod terminate; - picorsrc_Voice voice; - - /* protected */ - picoos_Common common; - picodata_CharBuffer cbIn, cbOut; - picodata_puSubDeallocateMethod subDeallocate; - void * subObj; - -} picodata_processing_unit_t; - -/* currently, only wav input and output is supported */ -#define PICODATA_PUTYPE_TEXT_OUTPUT_EXTENSION (picoos_uchar*)".txt" -#define PICODATA_PUTYPE_TOK_INPUT_EXTENSION PICODATA_PUTYPE_TEXT_OUTPUT_EXTENSION -#define PICODATA_PUTYPE_TOK_OUTPUT_EXTENSION (picoos_uchar*)".tok" -#define PICODATA_PUTYPE_PR_INPUT_EXTENSION PICODATA_PUTYPE_TOK_OUTPUT_EXTENSION -#define PICODATA_PUTYPE_PR_OUTPUT_EXTENSION (picoos_uchar*)".pr" -#define PICODATA_PUTYPE_WA_INPUT_EXTENSION PICODATA_PUTYPE_PR_OUTPUT_EXTENSION -#define PICODATA_PUTYPE_WA_OUTPUT_EXTENSION (picoos_uchar*)".wa" -#define PICODATA_PUTYPE_SA_INPUT_EXTENSION PICODATA_PUTYPE_WA_OUTPUT_EXTENSION -#define PICODATA_PUTYPE_SA_OUTPUT_EXTENSION (picoos_uchar*)".sa" -#define PICODATA_PUTYPE_ACPH_INPUT_EXTENSION PICODATA_PUTYPE_SA_OUTPUT_EXTENSION -#define PICODATA_PUTYPE_ACPH_OUTPUT_EXTENSION (picoos_uchar*)".acph" -#define PICODATA_PUTYPE_SPHO_INPUT_EXTENSION PICODATA_PUTYPE_ACPH_OUTPUT_EXTENSION -#define PICODATA_PUTYPE_SPHO_OUTPUT_EXTENSION (picoos_uchar*)".spho" -#define PICODATA_PUTYPE_PAM_INPUT_EXTENSION PICODATA_PUTYPE_SPHO_OUTPUT_EXTENSION -#define PICODATA_PUTYPE_PAM_OUTPUT_EXTENSION (picoos_uchar*)".pam" -#define PICODATA_PUTYPE_CEP_INPUT_EXTENSION PICODATA_PUTYPE_PAM_OUTPUT_EXTENSION -#define PICODATA_PUTYPE_CEP_OUTPUT_EXTENSION (picoos_uchar*)".cep" -#define PICODATA_PUTYPE_SIG_INPUT_EXTENSION PICODATA_PUTYPE_CEP_OUTPUT_EXTENSION /*PP 11.7.08*/ -#define PICODATA_PUTYPE_SIG_OUTPUT_EXTENSION (picoos_uchar*)".sig" -#define PICODATA_PUTYPE_SINK_INPUT_EXTENSION PICODATA_PUTYPE_SIG_OUTPUT_EXTENSION - -/*wav input is for play wav files in sig */ -#define PICODATA_PUTYPE_WAV_INPUT_EXTENSION (picoos_uchar*)".wav" /*PP 11.7.08*/ - -/*wav output is for saving wav (binary) files in sig*/ -#define PICODATA_PUTYPE_WAV_OUTPUT_EXTENSION (picoos_uchar*)".wav" /*PP 14.7.08*/ - -/* *************************************************************** - * auxiliary routines * - *****************************************************************/ - -picoos_uint8 picodata_getPuTypeFromExtension(picoos_uchar * filename, picoos_bool input); - -#define PICODATA_XSAMPA (picoos_uchar *)"xsampa" -#define PICODATA_SAMPA (picoos_uchar *)"sampa" -#define PICODATA_SVOXPA (picoos_uchar *)"svoxpa" - -/*----------------------------------------------------------*/ -/** @brief maps an input phone string to its internal representation - * - * @param transducer initialized SimpleTransducer - * @param xsampa_parser fst converting xsampa char input to xsampa ids - * @param svoxpa_parser - * @param xsampa2svoxpa_mapper - * @param inputPhones input phone string in alphabet 'alphabet' - * @param alphabet input alphabet - * @retval outputPhoneIds output phone string in internal representation - * @param maxOutputPhoneIds - * @return PICO_OK=mapping done, PICO_ERR_OTHER:unknown alphabet, unknown phones - */ -/*---------------------------------------------------------*/ -pico_status_t picodata_mapPAStrToPAIds( - picotrns_SimpleTransducer transducer, - picoos_Common common, - picokfst_FST xsampa_parser, - picokfst_FST svoxpa_parser, - picokfst_FST xsampa2svoxpa_mapper, - picoos_uchar * inputPhones, - picoos_uchar * alphabet, - picoos_uint8 * outputPhoneIds, - picoos_int32 maxOutputPhoneIds); - -/* number of binary digits after the comma for fixed-point calculation */ -#define PICODATA_PRECISION 10 -/* constant 0.5 in PICODATA_PRECISION */ -#define PICODATA_PREC_HALF 512 - -void picodata_transformDurations( - picoos_uint8 frame_duration_exp, - picoos_int8 array_length, - picoos_uint8 * inout, - const picoos_uint16 * weight, /* integer weights */ - picoos_int16 mintarget, /* minimum target duration in ms */ - picoos_int16 maxtarget, /* maximum target duration in ms */ - picoos_int16 facttarget, /* factor to be multiplied with original length to get the target - the factor is fixed-point with precision PRECISION, i.e. - the factor as float would be facttarget / PRECISION_FACT - if factor is 0, only min/max are considered */ - picoos_int16 * dur_rest /* in/out, rest in ms */ - ); - - - -/* *************************************************************** - * For Debugging only * - *****************************************************************/ - -#if defined (PICO_DEBUG) - -/* convert (pretty print) item head 'head' and put output in 'str', - strsize is the maximum length of 'str' in bytes */ -picoos_char * picodata_head_to_string(const picodata_itemhead_t *head, - picoos_char * str, picoos_uint16 strsize); - -/* put 'pref6ch' (max. 6 char prefix) and a pretty print output of - 'item' in 'str', strlenmax is the maximum length of 'str' in - bytes */ -void picodata_info_item(const picoknow_KnowledgeBase kb, - const picoos_uint8 *pref6ch, - const picoos_uint8 *item, - const picoos_uint16 itemlenmax, - const picoos_char *filterfn); - - -#define PICODATA_INFO_ITEM(kb, pref, item, itemlenmax) \ - PICODBG_INFO_CTX(); \ - picodata_info_item(kb, pref, item, itemlenmax, (picoos_char *)__FILE__) - - - -#else - -#define PICODATA_INFO_ITEM(kb, pref, item, itemlenmax) - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /*PICODATA_H_*/ diff --git a/lib/picodbg.c b/lib/picodbg.c deleted file mode 100644 index 8fa753b..0000000 --- a/lib/picodbg.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - * 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 picodbg.c - * - * Provides functions and macros to debug the Pico system and to trace - * the execution of its code. - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - */ - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -#if defined(PICO_DEBUG) - -/* Two variants of colored console output are implemented: - COLOR_MODE_WINDOWS - uses the Windows API function SetConsoleTextAttribute - COLOR_MODE_ANSI - uses ANSI escape codes */ -#if defined(_WIN32) -#define COLOR_MODE_WINDOWS -#else -#define COLOR_MODE_ANSI -#endif - - -#include -#include - -#include -#include - -#include "picodbg.h" - - -/* Maximum length of a formatted tracing message */ -#define MAX_MESSAGE_LEN 999 - -/* Maximum length of contextual information */ -#define MAX_CONTEXT_LEN 499 - -/* Maximum length of filename filter */ -#define MAX_FILTERFN_LEN 16 - -/* Delimiter used in debug messages */ -#define MSG_DELIM "|" - -/* Standard output file for debug messages */ -#define STDDBG stdout /* or stderr */ - -/* Default setup */ -#define PICODBG_DEFAULT_LEVEL PICODBG_LOG_LEVEL_WARN -#define PICODBG_DEFAULT_FILTERFN "" -#define PICODBG_DEFAULT_FORMAT \ - (PICODBG_SHOW_LEVEL | PICODBG_SHOW_SRCNAME | PICODBG_SHOW_FUNCTION) -#define PICODBG_DEFAULT_COLOR 1 - - -/* Current log level */ -static int logLevel = PICODBG_DEFAULT_LEVEL; - -/* Current log filter (filename) */ -static char logFilterFN[MAX_FILTERFN_LEN + 1]; - -/* Current log file or NULL if no log file is set */ -static FILE *logFile = NULL; - -/* Current output format */ -static int logFormat = PICODBG_DEFAULT_FORMAT; - -/* Color mode for console output (0 : disable colors, != 0 : enable colors */ -static int optColor = 0; - -/* Buffer for context information */ -static char ctxbuf[MAX_CONTEXT_LEN + 1]; - -/* Buffer to format tracing messages */ -static char msgbuf[MAX_MESSAGE_LEN + 1]; - - -/* *** Support for colored text output to console *****/ - - -/* Console text colors */ -enum color_t { - /* order matches Windows color codes */ - ColorBlack, - ColorBlue, - ColorGreen, - ColorCyan, - ColorRed, - ColorPurple, - ColorBrown, - ColorLightGray, - ColorDarkGray, - ColorLightBlue, - ColorLightGreen, - ColorLightCyan, - ColorLightRed, - ColorLightPurple, - ColorYellow, - ColorWhite -}; - - -static enum color_t picodbg_getLevelColor(int level) -{ - switch (level) { - case PICODBG_LOG_LEVEL_ERROR: return ColorLightRed; - case PICODBG_LOG_LEVEL_WARN : return ColorYellow; - case PICODBG_LOG_LEVEL_INFO : return ColorGreen; - case PICODBG_LOG_LEVEL_DEBUG: return ColorLightGray; - case PICODBG_LOG_LEVEL_TRACE: return ColorDarkGray; - } - return ColorWhite; -} - - -#if defined(COLOR_MODE_WINDOWS) - -#define WIN32_LEAN_AND_MEAN -#include - -static int picodbg_setTextAttr(FILE *stream, int attr) -{ - HANDLE hConsole; - - if (stream == stdout) { - hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - } else if (stream == stderr) { - hConsole = GetStdHandle(STD_ERROR_HANDLE); - } else { - hConsole = INVALID_HANDLE_VALUE; - } - - if (hConsole != INVALID_HANDLE_VALUE) { - /* do nothing if console output is redirected to a file */ - if (GetFileType(hConsole) == FILE_TYPE_CHAR) { - CONSOLE_SCREEN_BUFFER_INFO csbi; - GetConsoleScreenBufferInfo(hConsole, &csbi); - SetConsoleTextAttribute(hConsole, (WORD) attr); - return (int) csbi.wAttributes; - } - } - - return 0; -} - -#elif defined(COLOR_MODE_ANSI) - -static int picodbg_setTextAttr(FILE *stream, int attr) -{ - const char *c = ""; - - if (attr == -1) { - c = "0"; - } else switch (attr) { - case ColorBlack: c = "0;30"; break; - case ColorRed: c = "0;31"; break; - case ColorGreen: c = "0;32"; break; - case ColorBrown: c = "0;33"; break; - case ColorBlue: c = "0;34"; break; - case ColorPurple: c = "0;35"; break; - case ColorCyan: c = "0;36"; break; - case ColorLightGray: c = "0;37"; break; - case ColorDarkGray: c = "1;30"; break; - case ColorLightRed: c = "1;31"; break; - case ColorLightGreen: c = "1;32"; break; - case ColorYellow: c = "1;33"; break; - case ColorLightBlue: c = "1;34"; break; - case ColorLightPurple: c = "1;35"; break; - case ColorLightCyan: c = "1;36"; break; - case ColorWhite: c = "1;37"; break; - } - - fprintf(stream, "\x1b[%sm", c); - return -1; -} - -#else - -static int picodbg_setTextAttr(FILE *stream, int attr) -{ - /* avoid 'unreferenced formal parameter' */ - (void) stream; - (void) attr; - return 0; -} - -#endif - - -/* *** Auxiliary routines *****/ - - -static const char *picodbg_fileTitle(const char *file) -{ - const char *name = file, *str = file; - - /* try to extract file name without path in a platform independent - way, i.e., skip all chars preceding path separator chars like - '/' (Unix, MacOSX), '\' (Windows, DOS), and ':' (MacOS9) */ - while (*str) { - if ((*str == '\\') || (*str == '/') || (*str == ':')) { - name = str + 1; - } - str++; - } - - return name; -} - - -static void picodbg_logToStream(int level, int donewline, - const char *context, const char *msg) -{ - int oldAttr = 0; - - if (optColor) { - oldAttr = picodbg_setTextAttr(STDDBG, picodbg_getLevelColor(level)); - } - - fprintf(STDDBG, "%s%s", context, msg); - if (donewline) fprintf(STDDBG, "\n"); - if (logFile != NULL) { - fprintf(logFile, "%s%s", context, msg); - if (donewline) fprintf(logFile, "\n"); - } - - if (optColor) { - picodbg_setTextAttr(STDDBG, oldAttr); - } -} - - -/* *** Exported routines *****/ - - -void picodbg_initialize(int level) -{ - logLevel = level; - strcpy(logFilterFN, PICODBG_DEFAULT_FILTERFN); - logFile = NULL; - logFormat = PICODBG_DEFAULT_FORMAT; - optColor = PICODBG_DEFAULT_COLOR; - PICODBG_ASSERT_RANGE(level, 0, PICODBG_LOG_LEVEL_TRACE); -} - - -void picodbg_terminate() -{ - if (logFile != NULL) { - fclose(logFile); - } - - logLevel = 0; - logFile = NULL; -} - - -void picodbg_setLogLevel(int level) -{ - PICODBG_ASSERT_RANGE(level, 0, PICODBG_LOG_LEVEL_TRACE); - logLevel = level; -} - - -void picodbg_setLogFilterFN(const char *name) -{ - strcpy(logFilterFN, name); -} - - -void picodbg_setLogFile(const char *name) -{ - if (logFile != NULL) { - fclose(logFile); - } - - if ((name != NULL) && (strlen(name) > 0)) { - logFile = fopen(name, "wt"); - } else { - logFile = NULL; - } -} - - -void picodbg_enableColors(int flag) -{ - optColor = (flag != 0); -} - - -void picodbg_setOutputFormat(unsigned int format) -{ - logFormat = format; -} - - -const char *picodbg_varargs(const char *format, ...) -{ - int len; - - va_list argptr; - va_start(argptr, format); - - len = vsprintf(msgbuf, format, argptr); - PICODBG_ASSERT_RANGE(len, 0, MAX_MESSAGE_LEN); - - return msgbuf; -} - - -void picodbg_log(int level, int donewline, const char *file, int line, - const char *func, const char *msg) -{ - char cb[MAX_CONTEXT_LEN + 1]; - - PICODBG_ASSERT_RANGE(level, 0, PICODBG_LOG_LEVEL_TRACE); - - if ((level <= logLevel) && - ((strlen(logFilterFN) == 0) || !strcmp(logFilterFN, picodbg_fileTitle(file)))) { - /* compose output format string */ - strcpy(ctxbuf, "*** "); - if (logFormat & PICODBG_SHOW_LEVEL) { - switch (level) { - case PICODBG_LOG_LEVEL_ERROR: - strcat(ctxbuf, "error" MSG_DELIM); - break; - case PICODBG_LOG_LEVEL_WARN: - strcat(ctxbuf, "warn " MSG_DELIM); - break; - case PICODBG_LOG_LEVEL_INFO: - strcat(ctxbuf, "info " MSG_DELIM); - break; - case PICODBG_LOG_LEVEL_DEBUG: - strcat(ctxbuf, "debug" MSG_DELIM); - break; - case PICODBG_LOG_LEVEL_TRACE: - strcat(ctxbuf, "trace" MSG_DELIM); - break; - default: - break; - } - } - if (logFormat & PICODBG_SHOW_DATE) { - /* nyi */ - } - if (logFormat & PICODBG_SHOW_TIME) { - /* nyi */ - } - if (logFormat & PICODBG_SHOW_SRCNAME) { - sprintf(cb, "%-10s", picodbg_fileTitle(file)); - strcat(ctxbuf, cb); - if (logFormat & PICODBG_SHOW_SRCLINE) { - sprintf(cb, "(%d)", line); - strcat(ctxbuf, cb); - } - strcat(ctxbuf, MSG_DELIM); - } - if (logFormat & PICODBG_SHOW_FUNCTION) { - if (strlen(func) > 0) { - sprintf(cb, "%-18s", func); - strcat(ctxbuf, cb); - strcat(ctxbuf, MSG_DELIM); - } - } - - picodbg_logToStream(level, donewline, ctxbuf, msg); - } -} - - -void picodbg_log_msg(int level, const char *file, const char *msg) -{ - PICODBG_ASSERT_RANGE(level, 0, PICODBG_LOG_LEVEL_TRACE); - - if ((level <= logLevel) && - ((strlen(logFilterFN) == 0) || !strcmp(logFilterFN, picodbg_fileTitle(file)))) { - picodbg_logToStream(level, 0, "", msg); - } -} - - -void picodbg_assert(const char *file, int line, const char *func, const char *expr) -{ - if (strlen(func) > 0) { - fprintf(STDDBG, "assertion failed: %s, file %s, function %s, line %d", - expr, picodbg_fileTitle(file), func, line); - } else { - fprintf(STDDBG, "assertion failed: %s, file %s, line %d", - expr, picodbg_fileTitle(file), line); - } - picodbg_terminate(); - abort(); -} - - -#else - -/* To prevent warning about "translation unit is empty" when - diagnostic output is disabled. */ -static void picodbg_dummy(void) { - picodbg_dummy(); -} - -#endif /* defined(PICO_DEBUG) */ - -#ifdef __cplusplus -} -#endif - - -/* end */ diff --git a/lib/picodbg.h b/lib/picodbg.h deleted file mode 100644 index 490d3b5..0000000 --- a/lib/picodbg.h +++ /dev/null @@ -1,311 +0,0 @@ -/* - * 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 picodbg.h - * - * Provides functions and macros to debug the Pico system and to trace - * the execution of its code. - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - */ - -/** - * @addtogroup picodbg - * ---------------------------------------------------\n - * Pico Debug Support \n - * ---------------------------------------------------\n - * GENERAL REMARKS - * --------------- - * This module provides a set of macros to help debug the Pico system. - * The usage of macros allows for completely removing debug code from - * the binaries delivered to customers. To enable diagnostic output - * the preprocessor symbol PICO_DEBUG has to be defined. - * - * By using global variables (to store the current log level etc.) - * this module violates a basic Pico design principle! - * - * Justification:\n - * - going without global data would reduce the functionality - * of this module considerably (e.g., log level could not be - * changed at runtime etc.) - * - at the moment, the only known system interdicting global - * variables is Symbian; but even there global variables are - * possible by using thread-local storage - * - allocating global data on the heap would require to pass - * a handle to this memory block to all routines of this - * module which in turn implies that _every_ function in the - * Pico system would require a pointer to some global data; - * obviously, this would be very awkward - * - * Furthermore, this module uses the non-standardized but handy - * __FUNCTION__ macro. It expands to the name of the enclosing - * function. For compilers not supporting this macro simply - * define __FUNCTION__ as an empty string. - * - * - * INITIALIZATION/TERMINATION\n - * --------------------------\n - * Before using any debug macros, this module has to be initialized - * by calling PICODBG_INITIALIZE(). If the routines are not needed - * anymore, PICODBG_TERMINATE() has to be called to terminate the - * module (e.g., to close the log file). - * - * - * TRACING\n - * -------\n - * Each tracing message is associated with a log level which describes - * its severity. The following levels are supported: - * - Trace - Very detailed log messages, potentially of a high - * frequency and volume - * - Debug - Less detailed and/or less frequent debugging messages - * - Info - Informational messages - * - Warn - Warnings which don't appear to the Pico user - * - Error - Error messages - * - * Tracing messages can use the well-known printf format specification. - * But because variadic macros (macros with a variable no. arguments) - * are not commonly supported by compilers a little trick is used - * which requires the format string and its arguments to be enclosed - * in double parenthesis: - * - * - PICODBG_INFO(("hello, world!")); - * - PICODBG_TRACE(("argc=%d", argc)); - * ... - * - * Each tracing message is expected to be a single line of text. Some - * contextual information (e.g., log level, time and date, source file - * and line number) and a newline are automatically added. The output - * format can be customized by a call to PICODBG_SET_OUTPUT_FORMAT(). - * - * Sample output: - * - *** info|2008-04-03|14:51:36|dbgdemo.c(15)|hello world - * - *** trace|2008-04-03|14:51:36|dbgdemo.c(16)|argc=2 - * - ... - * - * To compose a tracing message line consisting of, e.g. the elements - * of an array, on the Info level two additional macros shown in the - * following example are provided: - * - * PICODBG_INFO_CTX();\n - * for (i = 0; i < len; i++)\n - * ...some calc with arr and i\n - * PICODBG_INFO_MSG((" %d", arr[i]));\n - * }\n - * PICODBG_INFO_MSG(("\n"));\n - * - * Colored output of tracing messages helps to capture severe problems - * quickly. This feature is supported on the Windows platform and on - * platforms supporting ANSI escape codes. PICODBG_ENABLE_COLORS() lets - * you turn on and off colored output. - * - * - * FILTERING\n - * ---------\n - * By calling PICODBG_SET_LOG_LEVEL() the log level may be changed at - * any time to increase/decrease the amount of debugging output. - * - * By calling PICODBG_SET_LOG_FILTERFN() the log filter may be changed - * at any time to change the source file name being used as filter for - * log messages (ie. only tracing info of the specified file will be - * logged). To disable the file name based filter set the filter file - * name to an empty string. - * - * Future version of this module might provide further filtering - * possibilities (e.g., filtering based on function names * etc.). - * - * - * LOGGING\n - * -------\n - * By default, tracing messages are output to the console (stderr). - * This allows for separating diagnostic output from other console - * output to stdout. In addition, tracing messages may be saved to - * a file by calling PICODBG_SET_LOG_FILE(). - * Currently, file output is the only additional output target; but - * on embedded systems, more output targets may be required (e.g., - * sending output to a serial port or over the network). - * - * - * ASSERTIONS\n - * ----------\n - * To support the 'design/programming by contract' paradigm, this - * module also provides assertions. PICODBG_ASSERT(expr) evualuates - * an expression and, when the result is false, prints a diagnostic - * message and aborts the program. - * - * - * FUTURE EXTENSIONS\n - * -----------------\n - * - advanced tracing functions to dump complex data - * - debug memory allocation that can be used to assist in - * finding memory problems - */ - - -#if !defined(__PICODBG_H__) -#define __PICODBG_H__ - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* Not all compilers support the __FUNCTION__ macro */ -#if !defined(__FUNCTION__) && !defined(__GNUC__) -#define __FUNCTION__ "" -#endif - - -/* Log levels sorted by severity */ -#define PICODBG_LOG_LEVEL_ERROR 1 -#define PICODBG_LOG_LEVEL_WARN 2 -#define PICODBG_LOG_LEVEL_INFO 3 -#define PICODBG_LOG_LEVEL_DEBUG 4 -#define PICODBG_LOG_LEVEL_TRACE 5 - -/* Output format flags */ -#define PICODBG_SHOW_LEVEL 0x0001 -#define PICODBG_SHOW_DATE 0x0002 -#define PICODBG_SHOW_TIME 0x0004 -#define PICODBG_SHOW_SRCNAME 0x0008 -#define PICODBG_SHOW_SRCLINE 0x0010 -#define PICODBG_SHOW_SRCALL (PICODBG_SHOW_SRCNAME | PICODBG_SHOW_SRCLINE) -#define PICODBG_SHOW_FUNCTION 0x0020 -#define PICODBG_SHOW_POS (PICODBG_SHOW_SRCALL | PICODBG_SHOW_FUNCTION) - -/* definition of PICO_DEBUG enables debugging code */ -#if defined(PICO_DEBUG) - -#define PICODBG_INITIALIZE(level) \ - picodbg_initialize(level) - -#define PICODBG_TERMINATE() \ - picodbg_terminate() - -#define PICODBG_SET_LOG_LEVEL(level) \ - picodbg_setLogLevel(level) - -#define PICODBG_SET_LOG_FILTERFN(name) \ - picodbg_setLogFilterFN(name) - -#define PICODBG_SET_LOG_FILE(name) \ - picodbg_setLogFile(name) - -#define PICODBG_ENABLE_COLORS(flag) \ - picodbg_enableColors(flag) - -#define PICODBG_SET_OUTPUT_FORMAT(format) \ - picodbg_setOutputFormat(format) - - -#define PICODBG_ASSERT(expr) \ - for (;!(expr);picodbg_assert(__FILE__, __LINE__, __FUNCTION__, #expr)) - -#define PICODBG_ASSERT_RANGE(val, min, max) \ - PICODBG_ASSERT(((val) >= (min)) && ((val) <= (max))) - - -#define PICODBG_LOG(level, msg) \ - picodbg_log(level, 1, __FILE__, __LINE__, __FUNCTION__, picodbg_varargs msg) - -#define PICODBG_ERROR(msg) \ - PICODBG_LOG(PICODBG_LOG_LEVEL_ERROR, msg) - -#define PICODBG_WARN(msg) \ - PICODBG_LOG(PICODBG_LOG_LEVEL_WARN, msg) - -#define PICODBG_INFO(msg) \ - PICODBG_LOG(PICODBG_LOG_LEVEL_INFO, msg) - -#define PICODBG_DEBUG(msg) \ - PICODBG_LOG(PICODBG_LOG_LEVEL_DEBUG, msg) - -#define PICODBG_TRACE(msg) \ - PICODBG_LOG(PICODBG_LOG_LEVEL_TRACE, msg) - - -#define PICODBG_INFO_CTX() \ - picodbg_log(PICODBG_LOG_LEVEL_INFO, 0, __FILE__, __LINE__, __FUNCTION__, "") - -#define PICODBG_INFO_MSG(msg) \ - picodbg_log_msg(PICODBG_LOG_LEVEL_INFO, __FILE__, picodbg_varargs msg) - -#define PICODBG_INFO_MSG_F(filterfn, msg) \ - picodbg_log_msg(PICODBG_LOG_LEVEL_INFO, (const char *)filterfn, picodbg_varargs msg) - - - -/* helper routines; should NOT be used directly! */ - -void picodbg_initialize(int level); -void picodbg_terminate(); - -void picodbg_setLogLevel(int level); -void picodbg_setLogFilterFN(const char *name); -void picodbg_setLogFile(const char *name); -void picodbg_enableColors(int flag); -void picodbg_setOutputFormat(unsigned int format); - -const char *picodbg_varargs(const char *format, ...); - -void picodbg_log(int level, int donewline, const char *file, int line, - const char *func, const char *msg); -void picodbg_assert(const char *file, int line, const char *func, - const char *expr); - -void picodbg_log_msg(int level, const char *file, const char *msg); - - -#else /* release version; omit debugging code */ - -#define PICODBG_INITIALIZE(level) -#define PICODBG_TERMINATE() -#define PICODBG_SET_LOG_LEVEL(level) -#define PICODBG_SET_LOG_FILTERFN(name) -#define PICODBG_SET_LOG_FILE(name) -#define PICODBG_ENABLE_COLORS(flag) -#define PICODBG_SET_OUTPUT_FORMAT(format) - -#define PICODBG_ASSERT(expr) -#define PICODBG_ASSERT_RANGE(val, min, max) - -#define PICODBG_LOG(level, msg) -#define PICODBG_ERROR(msg) -#define PICODBG_WARN(msg) -#define PICODBG_INFO(msg) -#define PICODBG_DEBUG(msg) -#define PICODBG_TRACE(msg) - -#define PICODBG_INFO_CTX() -#define PICODBG_INFO_MSG(msg) -#define PICODBG_INFO_MSG_F(filterfn, msg) - - -#endif /* defined(PICO_DEBUG) */ - -#ifdef __cplusplus -} -#endif - - -#endif /* !defined(__PICODBG_H__) */ diff --git a/lib/picodefs.h b/lib/picodefs.h deleted file mode 100644 index 6613e84..0000000 --- a/lib/picodefs.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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 picodefs.h - * - * SVOX Pico definitions - * (SVOX Pico version 1.0 and later) - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - */ - - -#ifndef PICODEFS_H_ -#define PICODEFS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - - -/* ********************************************************************/ -/* SVOX Pico limits */ -/* ********************************************************************/ -/* maximum size of a voice name, including the terminating null - character */ -#define PICO_MAX_VOICE_NAME_SIZE 32 - -/* maximum size of a resource name, incl. the terminating null - character */ -#define PICO_MAX_RESOURCE_NAME_SIZE 32 - -/* maximum size of a data path name, incl. the terminating null - character */ -#define PICO_MAX_DATAPATH_NAME_SIZE 128 - -/* maximum size of a file name, incl. the terminating null - character */ -#define PICO_MAX_FILE_NAME_SIZE 64 - -/* maximum number of resources */ -#define PICO_MAX_NUM_RESOURCES 64 - -/* maximum number of voice definitions */ -#define PICO_MAX_NUM_VOICE_DEFINITIONS 64 - -/* maximum number of resources per voice */ -#define PICO_MAX_NUM_RSRC_PER_VOICE 16 - -/* maximum length of foreign header prepended to PICO resource files - (header length must be a multiple of 4 bytes) */ -#define PICO_MAX_FOREIGN_HEADER_LEN 64 - - - -/* ********************************************************************/ -/* SVOX PICO status codes */ -/* ********************************************************************/ - -typedef signed int pico_Status; - - -/* Okay ***************************************************************/ -/* functions return PICO_OK if all is okay */ - -#define PICO_OK (pico_Status) 0 - - -/* Exceptions and error codes *****************************************/ - -/* in case of exceptional events and errors (e.g. unexpected user - input) that disrupt the normal flow of operation, PICO_EXC_* or - PICO_ERR_* are returned. */ - -#define PICO_EXC_NUMBER_FORMAT (pico_Status) -10 -#define PICO_EXC_MAX_NUM_EXCEED (pico_Status) -11 -#define PICO_EXC_NAME_CONFLICT (pico_Status) -12 -#define PICO_EXC_NAME_UNDEFINED (pico_Status) -13 -#define PICO_EXC_NAME_ILLEGAL (pico_Status) -14 - -/* buffer interaction */ -#define PICO_EXC_BUF_OVERFLOW (pico_Status) -20 -#define PICO_EXC_BUF_UNDERFLOW (pico_Status) -21 -#define PICO_EXC_BUF_IGNORE (pico_Status) -22 - -/* internal memory handling */ -#define PICO_EXC_OUT_OF_MEM (pico_Status) -30 - -/* files */ -#define PICO_EXC_CANT_OPEN_FILE (pico_Status) -40 -#define PICO_EXC_UNEXPECTED_FILE_TYPE (pico_Status) -41 -#define PICO_EXC_FILE_CORRUPT (pico_Status) -42 -#define PICO_EXC_FILE_NOT_FOUND (pico_Status) -43 - -/* resources */ -#define PICO_EXC_RESOURCE_BUSY (pico_Status) -50 -#define PICO_EXC_RESOURCE_MISSING (pico_Status) -51 - -/* knowledge bases */ -#define PICO_EXC_KB_MISSING (pico_Status) -60 - -/* runtime exceptions */ -#define PICO_ERR_NULLPTR_ACCESS (pico_Status) -100 -#define PICO_ERR_INVALID_HANDLE (pico_Status) -101 -#define PICO_ERR_INVALID_ARGUMENT (pico_Status) -102 -#define PICO_ERR_INDEX_OUT_OF_RANGE (pico_Status) -103 - -/* other errors ("external" errors, e.g. hardware failure). */ -#define PICO_ERR_OTHER (pico_Status) -999 - - -/* Warnings ***********************************************************/ - -/* general */ -#define PICO_WARN_INCOMPLETE (pico_Status) 10 -#define PICO_WARN_FALLBACK (pico_Status) 11 -#define PICO_WARN_OTHER (pico_Status) 19 - -/* resources */ -#define PICO_WARN_KB_OVERWRITE (pico_Status) 50 -#define PICO_WARN_RESOURCE_DOUBLE_LOAD (pico_Status) 51 - -/* classifiers */ -#define PICO_WARN_INVECTOR (pico_Status) 60 -#define PICO_WARN_CLASSIFICATION (pico_Status) 61 -#define PICO_WARN_OUTVECTOR (pico_Status) 62 - -/* processing units */ -#define PICO_WARN_PU_IRREG_ITEM (pico_Status) 70 -#define PICO_WARN_PU_DISCARD_BUF (pico_Status) 71 - - - -/* ********************************************************************/ -/* Engine getData return values */ -/* ********************************************************************/ - -#define PICO_STEP_IDLE (pico_Status) 200 -#define PICO_STEP_BUSY (pico_Status) 201 - -#define PICO_STEP_ERROR (pico_Status) -200 - - - -/* ********************************************************************/ -/* Engine getData outDataType values */ -/* ********************************************************************/ - -/* 16 bit PCM samples, native endianness of platform */ -#define PICO_DATA_PCM_16BIT (pico_Int16) 1 - -#ifdef __cplusplus -} -#endif - - -#endif /*PICODEFS_H_*/ diff --git a/lib/picodsp.h b/lib/picodsp.h deleted file mode 100644 index 67457f8..0000000 --- a/lib/picodsp.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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 picodsp.h - * - * Include file for DSP related data types and constants in Pico - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#ifndef PICODSP_H_ -#define PICODSP_H_ - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -/*----------------------------CONSTANTS ----------------------*/ -/*Normalization factors used at the start and at the end of the sig*/ -#define PICODSP_START_FLOAT_NORM 0.41f -#define PICODSP_ENVSPEC_K1 0.5f -#define PICODSP_ENVSPEC_K2 2 -#define PICODSP_GETEXC_K1 1024 -#define PICODSP_FIXRESP_NORM 4096.0f -#define PICODSP_END_FLOAT_NORM 1.5f*16.0f -#define PICODSP_FIX_SCALE1 0x4000000 -#define PICODSP_FIX_SCALE2 0x4000 -#define PICODSP_SHIFT_FACT1 10 -#define PICODSP_SHIFT_FACT2 16 -#define PICODSP_SHIFT_FACT3 12 -#define PICODSP_SHIFT_FACT4 1 -#define PICODSP_SHIFT_FACT5 18 -#define PICODSP_SHIFT_FACT6 9 -#define PICOSIG_NORM1 9.14f /100.0f /*normalization factor*/ -#define PICOSIG_MAXAMP (32767) -#define PICOSIG_MINAMP (-32768) -#define PICODSP_M_PI 3.14159265358979323846 -#define PICODSP_MAX_EX 32 -#define PICODSP_WGT_SHIFT (0x20000000) -#define PICODSP_N_RAND_TABLE (760) -#define PICODSP_COS_TABLE_LEN (512) -#define PICODSP_COS_TABLE_LEN2 (1024) -#define PICODSP_COS_TABLE_LEN4 (2048) -#define PICODSP_PI_SHIFT (4) /* -log2(PICODSP_COS_TABLE_LEN2/0x4000) */ - -#define PICODSP_V_CUTOFF_FREQ 4500 -#define PICODSP_UV_CUTOFF_FREQ 300 -#define PICODSP_SAMP_FREQ 16000 -#define PICODSP_FREQ_WARP_FACT 0.42f - -/*----------------------------CEP/PHASE CONSTANTS----------------------------*/ -#define PICODSP_CEPORDER 25 -#define PICODSP_PHASEORDER 72 -#define CEPST_BUFF_SIZE 3 -#define PHASE_BUFF_SIZE 5 -/*----------------------------FFT CONSTANTS----------------------------*/ -#define PICODSP_FFTSIZE (256) - -#define PICODSP_H_FFTSIZE (PICODSP_FFTSIZE/2) - -#define PICODSP_DISPLACE PICODSP_FFTSIZE/4 - -#define PICODSP_H_FFTSIZE (PICODSP_FFTSIZE/2) -#define PICODSP_HFFTSIZE_P1 (PICODSP_H_FFTSIZE+1) - -#define FAST_DEVICE(aCount, aAction) \ -{ \ - int count_ = (aCount); \ - int times_ = (count_ + 7) >> 3; \ - switch (count_ & 7){ \ - case 0: do { aAction; \ - case 7: aAction; \ - case 6: aAction; \ - case 5: aAction; \ - case 4: aAction; \ - case 3: aAction; \ - case 2: aAction; \ - case 1: aAction; \ - } while (--times_ > 0); \ -} \ -} -/*------------------------------------------------------------------------------------------ - Fast Exp Approximation now remapped to a function in picoos - -----------------------------------------------------------------------------------------*/ -#define EXP(y) picoos_quick_exp(y) - -#ifdef __cplusplus -} -#endif - -#endif /*PICODSP_H_*/ diff --git a/lib/picoextapi.c b/lib/picoextapi.c deleted file mode 100644 index 4c5d30c..0000000 --- a/lib/picoextapi.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * 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 picoextapi.c - * - * API extension for development use - * - * 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 "picoctrl.h" -#include "picodbg.h" -#include "picoapi.h" -#include "picoextapi.h" -#include "picoapid.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -/* this is not used anymore. For the picosh banner, set - * progv.progVers in picosh.c instead. */ -#define PICO_VERSION_INFO (picoos_char *)"invalid" - - -extern pico_Status pico_initialize_priv( - void *memory, - const pico_Uint32 size, - pico_Int16 enableMemProt, - pico_System *system); - - -/* System initialization and termination functions ****************************/ - - -PICO_FUNC picoext_initialize( - void *memory, - const pico_Uint32 size, - pico_Int16 enableMemProt, - pico_System *outSystem - ) -{ - return pico_initialize_priv(memory, size, enableMemProt, outSystem); -} - - -/* System and lingware inspection functions ***********************************/ - -/* @todo : not supported yet */ -PICO_FUNC picoext_getVersionInfo( - pico_Retstring outInfo, - const pico_Int16 outInfoMaxLen - ) -{ - if (outInfo == NULL) { - return PICO_ERR_NULLPTR_ACCESS; - } - picoos_strlcpy((picoos_char *) outInfo, PICO_VERSION_INFO, outInfoMaxLen); - return PICO_OK; -} - - -/* Debugging/testing support functions *****************************************/ - - -PICO_FUNC picoext_setTraceLevel( - pico_System system, - pico_Int32 level - ) -{ - if (NULL == system) { - return PICO_ERR_NULLPTR_ACCESS; - } - if (level < 0) { - level = 0; - } - if (level > PICODBG_LOG_LEVEL_TRACE) { - level = PICODBG_LOG_LEVEL_TRACE; - } - PICODBG_SET_LOG_LEVEL(level); - return PICO_OK; -} - - -PICO_FUNC picoext_setTraceFilterFN( - pico_System system, - const pico_Char *name - ) -{ - - if (NULL == system) { - return PICO_ERR_NULLPTR_ACCESS; - } - name = name; /*PP 13.10.08 : fix warning "var not used in this function"*/ - PICODBG_SET_LOG_FILTERFN((const char *)name); - return PICO_OK; -} - - -PICO_FUNC picoext_setLogFile( - pico_System system, - const pico_Char *name - ) -{ - if (NULL == system) { - return PICO_ERR_NULLPTR_ACCESS; - } - name = name; /*PP 13.10.08 : fix warning "var not used in this function"*/ - PICODBG_SET_LOG_FILE((const char *) name); - return PICO_OK; -} - - -/* Memory usage ***************************************************************/ - - -pico_Status getMemUsage( - picoos_Common common, - picoos_bool resetIncremental, - picoos_int32 *usedBytes, - picoos_int32 *incrUsedBytes, - picoos_int32 *maxUsedBytes - ) -{ - pico_Status status = PICO_OK; - - if (common == NULL) { - status = PICO_ERR_NULLPTR_ACCESS; - } else { - picoos_emReset(common->em); - picoos_getMemUsage(common->mm, resetIncremental, usedBytes, incrUsedBytes, maxUsedBytes); - status = picoos_emGetExceptionCode(common->em); - } - - return status; -} - - -PICO_FUNC picoext_getSystemMemUsage( - pico_System system, - pico_Int16 resetIncremental, - pico_Int32 *outUsedBytes, - pico_Int32 *outIncrUsedBytes, - pico_Int32 *outMaxUsedBytes - ) -{ - pico_Status status = PICO_OK; - - if (!is_valid_system_handle(system)) { - status = PICO_ERR_INVALID_HANDLE; - } else if ((outUsedBytes == NULL) || (outIncrUsedBytes == NULL) || (outMaxUsedBytes == NULL)) { - status = PICO_ERR_NULLPTR_ACCESS; - } else { - picoos_Common common = pico_sysGetCommon(system); - status = getMemUsage(common, resetIncremental != 0, outUsedBytes, outIncrUsedBytes, outMaxUsedBytes); - } - - return status; -} - - -PICO_FUNC picoext_getEngineMemUsage( - pico_Engine engine, - pico_Int16 resetIncremental, - pico_Int32 *outUsedBytes, - pico_Int32 *outIncrUsedBytes, - pico_Int32 *outMaxUsedBytes - ) -{ - pico_Status status = PICO_OK; - - if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) { - status = PICO_ERR_INVALID_HANDLE; - } else if ((outUsedBytes == NULL) || (outIncrUsedBytes == NULL) || (outMaxUsedBytes == NULL)) { - status = PICO_ERR_NULLPTR_ACCESS; - } else { - picoos_Common common = picoctrl_engGetCommon((picoctrl_Engine) engine); - status = getMemUsage(common, resetIncremental != 0, outUsedBytes, outIncrUsedBytes, outMaxUsedBytes); - } - - return status; -} - -PICO_FUNC picoext_getLastScheduledPU( - pico_Engine engine - ) -{ - pico_Status status = PICO_OK; - status = picoctrl_getLastScheduledPU((picoctrl_Engine) engine); - return status; -} - -PICO_FUNC picoext_getLastProducedItemType( - pico_Engine engine - ) -{ - pico_Status status = PICO_OK; - status = picoctrl_getLastProducedItemType((picoctrl_Engine) engine); - return status; -} - -#ifdef __cplusplus -} -#endif - -/* end */ diff --git a/lib/picoextapi.h b/lib/picoextapi.h deleted file mode 100644 index 1768394..0000000 --- a/lib/picoextapi.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * 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 picoextapi.h - * - * API extensions for development use - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#ifndef PICOEXTAPI_H_ -#define PICOEXTAPI_H_ - -#include "picodefs.h" -#include "picodbg.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* ****************************************************************************/ -/* Things that might be added to picoapi later but should not appear there */ -/* for the time being */ -/* ****************************************************************************/ - -/* String type for Unicode text input *****************************************/ - -/* Unicode encodings supported by PICO. */ - -#define PICO_STRENC_UTF8 0 -#define PICO_STRENC_UTF16 1 - -/* An UTF-8 string must point to a byte array, terminated by a null character - ('\0'). An UTF-16 string must point to a contiguous array of 16-bit units - (in native byte ordering), terminated by a 0. */ - -typedef char *PICO_STRING_UTF8; -typedef pico_Uint16 *PICO_STRING_UTF16; - -/* Generic pointer to a Unicode string, encoded either as UTF-8 or UTF-16. - The application must make sure that for each 'PICO_STRING_PTR' it provides - an argument of type 'PICO_STRING_UTF8' or 'PICO_STRING_UTF16' (or of a type - compatible to one of these types). */ - -typedef void *PICO_STRING_PTR; - - -/* ****************************************************************************/ -/* System-level API functions */ -/* ****************************************************************************/ - -/* System initialization and termination functions ****************************/ - -/* Same as pico_initialize, but allows to enable memory protection - functionality for testing purposes (enableMemProt != 0). */ - -PICO_FUNC picoext_initialize( - void *memory, - const pico_Uint32 size, - pico_Int16 enableMemProt, - pico_System *outSystem - ); - - -/* System and lingware inspection functions ***********************************/ - -/* Returns version information of the current Pico engine. */ - -PICO_FUNC picoext_getVersionInfo( - pico_Retstring outInfo, - const pico_Int16 outInfoMaxLen - ); - -/* Returns unique resource name */ - -/* -PICO_FUNC picoext_getResourceName( - pico_Resource resource, - pico_Retstring outInfo - ); -*/ - -/* Debugging/testing support functions *****************************************/ - -/* Sets tracing level. Increasing amounts of information is displayed - at each level. */ - -PICO_FUNC picoext_setTraceLevel( - pico_System system, - pico_Int32 level - ); - -/* Sets trace filtering. Limits tracing output to tracing information - resulting from the source file name being filtered. */ - -PICO_FUNC picoext_setTraceFilterFN( - pico_System system, - const pico_Char *name - ); - -/* Enables logging of debug output to log file 'name'. If 'name' is NULL - or an empty string, logging is disabled. */ - -PICO_FUNC picoext_setLogFile( - pico_System system, - const pico_Char *name - ); - - -/* Memory usage ***************************************************************/ - -PICO_FUNC picoext_getSystemMemUsage( - pico_System system, - pico_Int16 resetIncremental, - pico_Int32 *outUsedBytes, - pico_Int32 *outIncrUsedBytes, - pico_Int32 *outMaxUsedBytes - ); - -PICO_FUNC picoext_getEngineMemUsage( - pico_Engine engine, - pico_Int16 resetIncremental, - pico_Int32 *outUsedBytes, - pico_Int32 *outIncrUsedBytes, - pico_Int32 *outMaxUsedBytes - ); - -PICO_FUNC picoext_getLastScheduledPU( - pico_Engine engine - ); - -PICO_FUNC picoext_getLastProducedItemType( - pico_Engine engine - ); - -#ifdef __cplusplus -} -#endif - - -#endif /* PICOEXTAPI_H_ */ diff --git a/lib/picofftsg.c b/lib/picofftsg.c deleted file mode 100644 index dcca018..0000000 --- a/lib/picofftsg.c +++ /dev/null @@ -1,3274 +0,0 @@ -/* - * 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 picofftsg.c - * - * FFT/DCT related data types, constants and functions in Pico - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * -*/ - -#include "picoos.h" -#include "picofftsg.h" -#include "picodbg.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @addtogroup picofft - * ---------------------------------------------------\n - * Fast Fourier/Cosine/Sine Transform \n - * Adapted from http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html (Copyright Takuya OOURA, 1996-2001)\n - * ---------------------------------------------------\n - - Overall features - - dimension :one - - data length :power of 2 - - decimation :frequency - - radix :split-radix - - data :inplace - - table :not use - - functions - - cdft: Complex Discrete Fourier Transform - - rdft: Real Discrete Fourier Transform - - ddct: Discrete Cosine Transform - - ddst: Discrete Sine Transform - - dfct: Cosine Transform of RDFT (Real Symmetric DFT) - - dfst: Sine Transform of RDFT (Real Anti-symmetric DFT) - - function prototypes - - void cdft(picoos_int32, picoos_int32, PICOFFTSG_FFTTYPE *); - - void rdft(picoos_int32, picoos_int32, PICOFFTSG_FFTTYPE *); - - void ddct(picoos_int32, picoos_int32, PICOFFTSG_FFTTYPE *); - - void ddst(picoos_int32, picoos_int32, PICOFFTSG_FFTTYPE *); - - void dfct(picoos_int32, PICOFFTSG_FFTTYPE *); - - void dfst(picoos_int32, PICOFFTSG_FFTTYPE *); - - Complex DFT (Discrete Fourier Transform) - - [definition] - - - - X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k - - X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k - - cdft(2*n, 1, a); - - - - cdft(2*n, -1, a); - - [parameters] - - 2*n :data length (picoos_int32) - - n >= 1, n = power of 2 - - a[0...2*n-1] :input/output data (PICOFFTSG_FFTTYPE *) - - input data - - a[2*j] = Re(x[j]), - - a[2*j+1] = Im(x[j]), 0<=j Real DFT / Inverse of Real DFT - - [definition] - - RDFT - - R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2 - - I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0 IRDFT (excluding scale) - - a[k] = (R[0] + R[n/2]*cos(pi*k))/2 + - - sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) + - - sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k - - rdft(n, 1, a); - - - - rdft(n, -1, a); - - [parameters] - - n :data length (picoos_int32) - - n >= 2, n = power of 2 - - a[0...n-1] :input/output data (PICOFFTSG_FFTTYPE *) - - - - output data - - a[2*k] = R[k], 0<=k - - input data - - a[2*j] = R[j], 0<=j DCT (Discrete Cosine Transform) / Inverse of DCT - - [definition] - - IDCT (excluding scale) - - C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k DCT - - C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k - - ddct(n, 1, a); - - - - ddct(n, -1, a); - - [parameters] - - n :data length (picoos_int32) - - n >= 2, n = power of 2 - - a[0...n-1] :input/output data (PICOFFTSG_FFTTYPE *) - - output data - - a[k] = C[k], 0<=k DST (Discrete Sine Transform) / Inverse of DST - - [definition] - - IDST (excluding scale) - - S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k DST - - S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0 - - ddst(n, 1, a); - - - - ddst(n, -1, a); - - [parameters] - - n :data length (picoos_int32) - - n >= 2, n = power of 2 - - a[0...n-1] :input/output data (PICOFFTSG_FFTTYPE *) - - - - input data - - a[j] = A[j], 0 - - output data - - a[k] = S[k], 0 Cosine Transform of RDFT (Real Symmetric DFT) - - [definition] - - C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n - - [usage] - - dfct(n, a); - - [parameters] - - n :data length - 1 (picoos_int32) - - n >= 2, n = power of 2 - - a[0...n] :input/output data (PICOFFTSG_FFTTYPE *) - - - output data - - a[k] = C[k], 0<=k<=n - - [remark] - - Inverse of a[0] *= 0.5; a[n] *= 0.5; dfct(n, a); is - - a[0] *= 0.5; - - a[n] *= 0.5; - - dfct(n, a); - - for (j = 0; j <= n; j++) { - - a[j] *= 2.0 / n; - - } - - Sine Transform of RDFT (Real Anti-symmetric DFT) - - [definition] - - S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0= 2, n = power of 2 - - a[0...n-1] :input/output data (PICOFFTSG_FFTTYPE *) - - output data - - a[k] = S[k], 0=POW17?(x>=POW25?(x>=POW29?(x>=POW31?31:(x>=POW30?30:29)):(x>=POW27?(x>=POW28?28:27):(x>=POW26?26:25))):(x>=POW21?(x>=POW23?(x>=POW24?24:23):(x>=POW22?22:21)):(x>=POW19?(x>=POW20?20:19):(x>=POW18?18:17)))):(x>=POW9?(x>=POW13?(x>=POW15?(x>=POW16?16:15):(x>=POW14?14:13)):(x>=POW11?(x>=POW12?12:11):(x>=POW10?10:9))):(x>=POW5?(x>=POW7?(x>=POW8?8:7):(x>=POW6?6:5)):(x>=POW3?(x>=POW4?4:3):(x>=POW2?2:1)))))) -#define picofftsg_highestBit(x) (x==0?0:(x<0?(zz=-x,(zz>=POW17?(zz>=POW25?(zz>=POW29?(zz>=POW31?31:(zz>=POW30?30:29)):(zz>=POW27?(zz>=POW28?28:27):(zz>=POW26?26:25))):(zz>=POW21?(zz>=POW23?(zz>=POW24?24:23):(zz>=POW22?22:21)):(zz>=POW19?(zz>=POW20?20:19):(zz>=POW18?18:17)))):(zz>=POW9?(zz>=POW13?(zz>=POW15?(zz>=POW16?16:15):(zz>=POW14?14:13)):(zz>=POW11?(zz>=POW12?12:11):(zz>=POW10?10:9))):(zz>=POW5?(zz>=POW7?(zz>=POW8?8:7):(zz>=POW6?6:5)):(zz>=POW3?(zz>=POW4?4:3):(zz>=POW2?2:1)))))):(x>=POW17?(x>=POW25?(x>=POW29?(x>=POW31?31:(x>=POW30?30:29)):(x>=POW27?(x>=POW28?28:27):(x>=POW26?26:25))):(x>=POW21?(x>=POW23?(x>=POW24?24:23):(x>=POW22?22:21)):(x>=POW19?(x>=POW20?20:19):(x>=POW18?18:17)))):(x>=POW9?(x>=POW13?(x>=POW15?(x>=POW16?16:15):(x>=POW14?14:13)):(x>=POW11?(x>=POW12?12:11):(x>=POW10?10:9))):(x>=POW5?(x>=POW7?(x>=POW8?8:7):(x>=POW6?6:5)):(x>=POW3?(x>=POW4?4:3):(x>=POW2?2:1))))))) -#define Mult_W_W picofftsg_mult_w_w - - -/* ***********************************************************************************************/ -/* forward declarations */ -/* ***********************************************************************************************/ -static PICOFFTSG_FFTTYPE picofftsg_mult_w_w(PICOFFTSG_FFTTYPE x1, PICOFFTSG_FFTTYPE y1); -static PICOFFTSG_FFTTYPE picofftsg_mult_w_a(PICOFFTSG_FFTTYPE x1, PICOFFTSG_FFTTYPE y1); - - -static void cftfsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void cftbsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void rftfsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void rftbsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); - -static void cftfsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void cftbsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void rftfsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void rftbsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void dctsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void dctsub4(picoos_int32 n, PICOFFTSG_FFTTYPE *a); - -static void ddct(picoos_int32 n, picoos_int32 isgn, PICOFFTSG_FFTTYPE *a); -static void bitrv1(picoos_int32 n, PICOFFTSG_FFTTYPE *a); - -static void bitrv2(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void bitrv216(PICOFFTSG_FFTTYPE *a); -static void bitrv208(PICOFFTSG_FFTTYPE *a); -static void cftmdl1(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void cftrec4(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void cftleaf(picoos_int32 n, picoos_int32 isplt, PICOFFTSG_FFTTYPE *a); -static void cftfx41(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void cftf161(PICOFFTSG_FFTTYPE *a); -static void cftf081(PICOFFTSG_FFTTYPE *a); -static void cftf040(PICOFFTSG_FFTTYPE *a); -static void cftx020(PICOFFTSG_FFTTYPE *a); - -void bitrv2conj(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -void bitrv216neg(PICOFFTSG_FFTTYPE *a); -void bitrv208neg(PICOFFTSG_FFTTYPE *a); -void cftb1st(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -void cftrec4(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -void cftleaf(picoos_int32 n, picoos_int32 isplt, PICOFFTSG_FFTTYPE *a); -void cftfx41(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -void cftf161(PICOFFTSG_FFTTYPE *a); -void cftf081(PICOFFTSG_FFTTYPE *a); -void cftb040(PICOFFTSG_FFTTYPE *a); -void cftx020(PICOFFTSG_FFTTYPE *a); - -static picoos_int32 cfttree(picoos_int32 n, picoos_int32 j, picoos_int32 k, PICOFFTSG_FFTTYPE *a); -static void cftleaf(picoos_int32 n, picoos_int32 isplt, PICOFFTSG_FFTTYPE *a); -static void cftmdl1(picoos_int32 n, PICOFFTSG_FFTTYPE *a); - -static void cftmdl1(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void cftmdl2(picoos_int32 n, PICOFFTSG_FFTTYPE *a); - -static void cftmdl1(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void cftmdl2(picoos_int32 n, PICOFFTSG_FFTTYPE *a); -static void cftf161(PICOFFTSG_FFTTYPE *a); -static void cftf162(PICOFFTSG_FFTTYPE *a); -static void cftf081(PICOFFTSG_FFTTYPE *a); -static void cftf082(PICOFFTSG_FFTTYPE *a); - -static void cftf161(PICOFFTSG_FFTTYPE *a); -static void cftf162(PICOFFTSG_FFTTYPE *a); -static void cftf081(PICOFFTSG_FFTTYPE *a); -static void cftf082(PICOFFTSG_FFTTYPE *a); - -/* ***********************************************************************************************/ -/* Exported functions */ -/* ***********************************************************************************************/ -void rdft(picoos_int32 n, picoos_int32 isgn, PICOFFTSG_FFTTYPE *a) -{ - PICOFFTSG_FFTTYPE xi; - - if (isgn >= 0) { - if (n > 4) { - cftfsub(n, a); - rftfsub(n, a); - } else if (n == 4) { - cftfsub(n, a); - } - xi = a[0] - a[1]; - a[0] += a[1]; - a[1] = xi; - } else { - a[1] = (a[0] - a[1]) / 2; - a[0] -= a[1]; - if (n > 4) { - rftbsub(n, a); - cftbsub(n, a); - } else if (n == 4) { - cftbsub(n, a); - } - } - -} - - -picoos_single norm_result(picoos_int32 m2, PICOFFTSG_FFTTYPE *tmpX, PICOFFTSG_FFTTYPE *norm_window) -{ - picoos_int16 nI; - PICOFFTSG_FFTTYPE a,b, E; - - E = (picoos_int32)0; - for (nI=0; nI>18) * ((tmpX[nI]>0) ? tmpX[nI]>>11 : -((-tmpX[nI])>>11)); - tmpX[nI] = a; - b = (a>=0?a:-a) >> 18; - E += (b*b); - } - - if (E>0) { - return (picoos_single)sqrt((double)E/16.0)/m2; - } - else { - return 0.0; - } -} - -void ddct(picoos_int32 n, picoos_int32 isgn, PICOFFTSG_FFTTYPE *a) -{ - picoos_int32 j; - PICOFFTSG_FFTTYPE xr; - - if (isgn < 0) { - xr = a[n - 1]; - for (j = n - 2; j >= 2; j -= 2) { - a[j + 1] = a[j] - a[j - 1]; - a[j] += a[j - 1]; - } - a[1] = a[0] - xr; - a[0] += xr; - if (n > 4) { - rftbsub(n, a); - cftbsub(n, a); - } else if (n == 4) { - cftbsub(n, a); - } - } - if (n > 4) { - dctsub(n, a); - } else { - dctsub4(n, a); - } - if (isgn >= 0) { - if (n > 4) { - cftfsub(n, a); - rftfsub(n, a); - } else if (n == 4) { - cftfsub(n, a); - } - - - xr = a[0] - a[1]; - a[0] += a[1]; - for (j = 2; j < n; j += 2) { - a[j - 1] = a[j] - a[j + 1]; - a[j] += a[j + 1]; - } - a[n - 1] = xr; - } -} - -void dfct_nmf(picoos_int32 n, picoos_int32 *a) -{ - picoos_int32 j, k, m, mh; - PICOFFTSG_FFTTYPE xr, xi, yr, yi, an; - PICOFFTSG_FFTTYPE *aj, *ak, *amj, *amk; - - m = n >> 1; - for (j = 0; j < m; j++) { - k = n - j; - xr = a[j] + a[k]; - a[j] -= a[k]; - a[k] = xr; - } - an = a[n]; - while (m >= 2) { - ddct(m, 1, a); - if (m > 2) { - bitrv1(m, a); - } - mh = m >> 1; - xi = a[m]; - a[m] = a[0]; - a[0] = an - xi; - an += xi; - k = m-1; - aj = a + 1; ak = a + k; amj = aj + m; amk = ak + m; - for (j = 1; j < mh; j++, aj++, ak--, amj++, amk--) { - xr = *amk; - xi = *amj; - yr = *aj; - yi = *ak; - *amj = yr; - *amk = yi; - *aj = xr - xi; - *ak = xr + xi; - } - xr = *aj; - *aj = *amj; - *amj = xr; - - m = mh; - } - - xi = a[1]; - a[1] = a[0]; - a[0] = an + xi; - a[n] = an - xi; - if (n > 2) { - bitrv1(n, a); - } - -} - -/* ***********************************************************************************************/ -/* internal routines */ -/* ***********************************************************************************************/ -/* - mult two numbers which are guaranteed to be in the range -1..1 - shift right as little as possible before mult, and the rest after the mult - Also, shift bigger number more - lose less accuracy - */ -static PICOFFTSG_FFTTYPE picofftsg_mult_w_w(PICOFFTSG_FFTTYPE x1, PICOFFTSG_FFTTYPE y1) -{ - PICOFFTSG_FFTTYPE x, y; - x = x1>=0 ? x1>>15 : -((-x1)>>15); - y = y1>=0 ? y1>>14 : -((-y1)>>14); - return x * y; -} - -static PICOFFTSG_FFTTYPE picofftsg_mult_w_a(PICOFFTSG_FFTTYPE x1, PICOFFTSG_FFTTYPE y1) -{ - PICOFFTSG_FFTTYPE x, y; - - - x = x1>=0 ? x1>>15 : -((-x1)>>15); - y = y1>=0 ? y1>>14 : -((-y1)>>14); - return x * y; -} - -static void cftfsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a) -{ - - if (n > 8) { - if (n > 32) { - cftmdl1(n, a); - if (n > 512) { - cftrec4(n, a); - } else if (n > 128) { - cftleaf(n, 1, a); - } else { - cftfx41(n, a); - } - bitrv2(n, a); - } else if (n == 32) { - cftf161(a); - bitrv216(a); - } else { - cftf081(a); - bitrv208(a); - } - } else if (n == 8) { - cftf040(a); - } else if (n == 4) { - cftx020(a); - } -} - - -void cftbsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a) -{ - if (n > 8) { - if (n > 32) { - cftb1st(n, a); - if (n > 512) { - cftrec4(n, a); - } else if (n > 128) { - cftleaf(n, 1, a); - } else { - cftfx41(n, a); - } - bitrv2conj(n, a); - } else if (n == 32) { - cftf161(a); - bitrv216neg(a); - } else { - cftf081(a); - bitrv208neg(a); - } - } else if (n == 8) { - cftb040(a); - } else if (n == 4) { - cftx020(a); - } -} - -/* **************************************************************************************************/ - -/* **************************************************************************************************/ -void bitrv2(picoos_int32 n, PICOFFTSG_FFTTYPE *a) -{ - picoos_int32 j0, k0, j1, k1, l, m, i, j, k, nh, m2; - PICOFFTSG_FFTTYPE xr, xi, yr, yi; - - m = 4; - for (l = n >> 2; l > 8; l >>= 2) { - m <<= 1; - } - m2 = m + m; - nh = n >> 1; - if (l == 8) { - j0 = 0; - for (k0 = 0; k0 < m; k0 += 4) { - k = k0; - for (j = j0; j < j0 + k0; j += 4) { - xr = a[j]; - xi = a[j + 1]; - yr = a[k]; - yi = a[k + 1]; - a[j] = yr; - a[j + 1] = yi; - a[k] = xr; - a[k + 1] = xi; - j1 = j + m; - k1 = k + m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 -= m; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 += m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nh; - k1 += 2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 -= m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 += m; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 -= m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += 2; - k1 += nh; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 += m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 -= m; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 += m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nh; - k1 -= 2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 -= m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 += m; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 -= m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - for (i = nh >> 1; i > (k ^= i); i >>= 1) { - /* Avoid warning*/ - }; - } - k1 = j0 + k0; - j1 = k1 + 2; - k1 += nh; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 += m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 -= m; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= 2; - k1 -= nh; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nh + 2; - k1 += nh + 2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nh - m; - k1 += m2 - 2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - for (i = nh >> 1; i > (j0 ^= i); i >>= 1) { - /* Avoid warning */ - } - } - } else { - j0 = 0; - for (k0 = 0; k0 < m; k0 += 4) { - k = k0; - for (j = j0; j < j0 + k0; j += 4) { - xr = a[j]; - xi = a[j + 1]; - yr = a[k]; - yi = a[k + 1]; - a[j] = yr; - a[j + 1] = yi; - a[k] = xr; - a[k + 1] = xi; - j1 = j + m; - k1 = k + m; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nh; - k1 += 2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 -= m; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += 2; - k1 += nh; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 += m; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nh; - k1 -= 2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 -= m; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - for (i = nh >> 1; i > (k ^= i); i >>= 1){ - /* Avoid warning */ - } - } - k1 = j0 + k0; - j1 = k1 + 2; - k1 += nh; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 += m; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - for (i = nh >> 1; i > (j0 ^= i); i >>= 1){ - /* Avoid warning */ - } - } - } -} - - -void bitrv2conj(picoos_int32 n, PICOFFTSG_FFTTYPE *a) -{ - picoos_int32 j0, k0, j1, k1, l, m, i, j, k, nh, m2; - PICOFFTSG_FFTTYPE xr, xi, yr, yi; - - - m = 4; - for (l = n >> 2; l > 8; l >>= 2) { - m <<= 1; - } - m2 = m + m; - nh = n >> 1; - if (l == 8) { - j0 = 0; - for (k0 = 0; k0 < m; k0 += 4) { - k = k0; - for (j = j0; j < j0 + k0; j += 4) { - xr = a[j]; - xi = -a[j + 1]; - yr = a[k]; - yi = -a[k + 1]; - a[j] = yr; - a[j + 1] = yi; - a[k] = xr; - a[k + 1] = xi; - j1 = j + m; - k1 = k + m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 -= m; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 += m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nh; - k1 += 2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 -= m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 += m; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 -= m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += 2; - k1 += nh; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 += m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 -= m; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 += m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nh; - k1 -= 2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 -= m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 += m; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 -= m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - for (i = nh >> 1; i > (k ^= i); i >>= 1) { - /* Avoid warning */ - } - } - k1 = j0 + k0; - j1 = k1 + 2; - k1 += nh; - a[j1 - 1] = -a[j1 - 1]; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - a[k1 + 3] = -a[k1 + 3]; - j1 += m; - k1 += m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 -= m; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= 2; - k1 -= nh; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nh + 2; - k1 += nh + 2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nh - m; - k1 += m2 - 2; - a[j1 - 1] = -a[j1 - 1]; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - a[k1 + 3] = -a[k1 + 3]; - for (i = nh >> 1; i > (j0 ^= i); i >>= 1) { /* Avoid warning*/ - - } - } - } else { - j0 = 0; - for (k0 = 0; k0 < m; k0 += 4) { - k = k0; - for (j = j0; j < j0 + k0; j += 4) { - xr = a[j]; - xi = -a[j + 1]; - yr = a[k]; - yi = -a[k + 1]; - a[j] = yr; - a[j + 1] = yi; - a[k] = xr; - a[k + 1] = xi; - j1 = j + m; - k1 = k + m; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += nh; - k1 += 2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 -= m; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += 2; - k1 += nh; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m; - k1 += m; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= nh; - k1 -= 2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 -= m; - k1 -= m; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - for (i = nh >> 1; i > (k ^= i); i >>= 1) { - /* Avoid warning*/ - } - } - k1 = j0 + k0; - j1 = k1 + 2; - k1 += nh; - a[j1 - 1] = -a[j1 - 1]; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - a[k1 + 3] = -a[k1 + 3]; - j1 += m; - k1 += m; - a[j1 - 1] = -a[j1 - 1]; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - a[k1 + 3] = -a[k1 + 3]; - for (i = nh >> 1; i > (j0 ^= i); i >>= 1) { - /* Avoid warning*/ - } - } - } -} - - -void bitrv216(PICOFFTSG_FFTTYPE *a) -{ - PICOFFTSG_FFTTYPE x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, - x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i, - x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i; - - x1r = a[2]; - x1i = a[3]; - x2r = a[4]; - x2i = a[5]; - x3r = a[6]; - x3i = a[7]; - x4r = a[8]; - x4i = a[9]; - x5r = a[10]; - x5i = a[11]; - x7r = a[14]; - x7i = a[15]; - x8r = a[16]; - x8i = a[17]; - x10r = a[20]; - x10i = a[21]; - x11r = a[22]; - x11i = a[23]; - x12r = a[24]; - x12i = a[25]; - x13r = a[26]; - x13i = a[27]; - x14r = a[28]; - x14i = a[29]; - a[2] = x8r; - a[3] = x8i; - a[4] = x4r; - a[5] = x4i; - a[6] = x12r; - a[7] = x12i; - a[8] = x2r; - a[9] = x2i; - a[10] = x10r; - a[11] = x10i; - a[14] = x14r; - a[15] = x14i; - a[16] = x1r; - a[17] = x1i; - a[20] = x5r; - a[21] = x5i; - a[22] = x13r; - a[23] = x13i; - a[24] = x3r; - a[25] = x3i; - a[26] = x11r; - a[27] = x11i; - a[28] = x7r; - a[29] = x7i; -} - - -void bitrv216neg(PICOFFTSG_FFTTYPE *a) -{ - PICOFFTSG_FFTTYPE x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, - x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i, - x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, - x13r, x13i, x14r, x14i, x15r, x15i; - - x1r = a[2]; - x1i = a[3]; - x2r = a[4]; - x2i = a[5]; - x3r = a[6]; - x3i = a[7]; - x4r = a[8]; - x4i = a[9]; - x5r = a[10]; - x5i = a[11]; - x6r = a[12]; - x6i = a[13]; - x7r = a[14]; - x7i = a[15]; - x8r = a[16]; - x8i = a[17]; - x9r = a[18]; - x9i = a[19]; - x10r = a[20]; - x10i = a[21]; - x11r = a[22]; - x11i = a[23]; - x12r = a[24]; - x12i = a[25]; - x13r = a[26]; - x13i = a[27]; - x14r = a[28]; - x14i = a[29]; - x15r = a[30]; - x15i = a[31]; - a[2] = x15r; - a[3] = x15i; - a[4] = x7r; - a[5] = x7i; - a[6] = x11r; - a[7] = x11i; - a[8] = x3r; - a[9] = x3i; - a[10] = x13r; - a[11] = x13i; - a[12] = x5r; - a[13] = x5i; - a[14] = x9r; - a[15] = x9i; - a[16] = x1r; - a[17] = x1i; - a[18] = x14r; - a[19] = x14i; - a[20] = x6r; - a[21] = x6i; - a[22] = x10r; - a[23] = x10i; - a[24] = x2r; - a[25] = x2i; - a[26] = x12r; - a[27] = x12i; - a[28] = x4r; - a[29] = x4i; - a[30] = x8r; - a[31] = x8i; -} - - -void bitrv208(PICOFFTSG_FFTTYPE *a) -{ - PICOFFTSG_FFTTYPE x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i; - - x1r = a[2]; - x1i = a[3]; - x3r = a[6]; - x3i = a[7]; - x4r = a[8]; - x4i = a[9]; - x6r = a[12]; - x6i = a[13]; - a[2] = x4r; - a[3] = x4i; - a[6] = x6r; - a[7] = x6i; - a[8] = x1r; - a[9] = x1i; - a[12] = x3r; - a[13] = x3i; -} - - -void bitrv208neg(PICOFFTSG_FFTTYPE *a) -{ - PICOFFTSG_FFTTYPE x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, - x5r, x5i, x6r, x6i, x7r, x7i; - - x1r = a[2]; - x1i = a[3]; - x2r = a[4]; - x2i = a[5]; - x3r = a[6]; - x3i = a[7]; - x4r = a[8]; - x4i = a[9]; - x5r = a[10]; - x5i = a[11]; - x6r = a[12]; - x6i = a[13]; - x7r = a[14]; - x7i = a[15]; - a[2] = x7r; - a[3] = x7i; - a[4] = x3r; - a[5] = x3i; - a[6] = x5r; - a[7] = x5i; - a[8] = x1r; - a[9] = x1i; - a[10] = x6r; - a[11] = x6i; - a[12] = x2r; - a[13] = x2i; - a[14] = x4r; - a[15] = x4i; -} - - -void bitrv1(picoos_int32 n, PICOFFTSG_FFTTYPE *a) -{ - picoos_int32 j0, k0, j1, k1, l, m, i, j, k, nh; - PICOFFTSG_FFTTYPE x; - nh = n >> 1; - x = a[1]; - a[1] = a[nh]; - a[nh] = x; - m = 2; - for (l = n >> 2; l > 2; l >>= 2) { - m <<= 1; - } - if (l == 2) { - j1 = m + 1; - k1 = m + nh; - x = a[j1]; - a[j1] = a[k1]; - a[k1] = x; - j0 = 0; - for (k0 = 2; k0 < m; k0 += 2) { - for (i = nh >> 1; i > (j0 ^= i); i >>= 1) { - /* Avoid warning*/ - } - k = k0; - for (j = j0; j < j0 + k0; j += 2) { - x = a[j]; - a[j] = a[k]; - a[k] = x; - j1 = j + m; - k1 = k + m; - x = a[j1]; - a[j1] = a[k1]; - a[k1] = x; - j1 += nh; - k1++; - x = a[j1]; - a[j1] = a[k1]; - a[k1] = x; - j1 -= m; - k1 -= m; - x = a[j1]; - a[j1] = a[k1]; - a[k1] = x; - j1++; - k1 += nh; - x = a[j1]; - a[j1] = a[k1]; - a[k1] = x; - j1 += m; - k1 += m; - x = a[j1]; - a[j1] = a[k1]; - a[k1] = x; - j1 -= nh; - k1--; - x = a[j1]; - a[j1] = a[k1]; - a[k1] = x; - j1 -= m; - k1 -= m; - x = a[j1]; - a[j1] = a[k1]; - a[k1] = x; - for (i = nh >> 1; i > (k ^= i); i >>= 1) { - /* Avoid warning*/ - } - } - k1 = j0 + k0; - j1 = k1 + 1; - k1 += nh; - x = a[j1]; - a[j1] = a[k1]; - a[k1] = x; - j1 += m; - k1 += m; - x = a[j1]; - a[j1] = a[k1]; - a[k1] = x; - } - } else { - j0 = 0; - for (k0 = 2; k0 < m; k0 += 2) { - for (i = nh >> 1; i > (j0 ^= i); i >>= 1) { - /* Avoid warning*/ - } - k = k0; - for (j = j0; j < j0 + k0; j += 2) { - x = a[j]; - a[j] = a[k]; - a[k] = x; - j1 = j + nh; - k1 = k + 1; - x = a[j1]; - a[j1] = a[k1]; - a[k1] = x; - j1++; - k1 += nh; - x = a[j1]; - a[j1] = a[k1]; - a[k1] = x; - j1 -= nh; - k1--; - x = a[j1]; - a[j1] = a[k1]; - a[k1] = x; - for (i = nh >> 1; i > (k ^= i); i >>= 1) { - /* Avoid warning*/ - } - } - k1 = j0 + k0; - j1 = k1 + 1; - k1 += nh; - x = a[j1]; - a[j1] = a[k1]; - a[k1] = x; - } - } -} - - -/* **************************************************************************************************/ - -/* **************************************************************************************************/ - -void cftb1st(picoos_int32 n, PICOFFTSG_FFTTYPE *a) -{ - picoos_int32 i, i0, j, j0, j1, j2, j3, m, mh; - PICOFFTSG_FFTTYPE wk1r, wk1i, wk3r, wk3i, - wd1r, wd1i, wd3r, wd3i, ss1, ss3; - PICOFFTSG_FFTTYPE x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - mh = n >> 3; - m = 2 * mh; - j1 = m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[0] + a[j2]; - x0i = -a[1] - a[j2 + 1]; - x1r = a[0] - a[j2]; - x1i = -a[1] + a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[0] = x0r + x2r; - a[1] = x0i - x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i + x2i; - a[j2] = x1r + x3i; - a[j2 + 1] = x1i + x3r; - a[j3] = x1r - x3i; - a[j3 + 1] = x1i - x3r; - wd1r = PICODSP_WGT_SHIFT; - wd1i = 0; - wd3r = PICODSP_WGT_SHIFT; - wd3i = 0; - - wk1r = (PICOFFTSG_FFTTYPE) (0.998795449734 *PICODSP_WGT_SHIFT); - wk1i = (PICOFFTSG_FFTTYPE) (0.049067676067 *PICODSP_WGT_SHIFT); - ss1 = (PICOFFTSG_FFTTYPE) (0.098135352135 *PICODSP_WGT_SHIFT); - wk3i = (PICOFFTSG_FFTTYPE) (-0.146730467677 *PICODSP_WGT_SHIFT); - wk3r = (PICOFFTSG_FFTTYPE) (0.989176511765 *PICODSP_WGT_SHIFT); - ss3 = (PICOFFTSG_FFTTYPE) (-0.293460935354 *PICODSP_WGT_SHIFT); - - i = 0; - for (;;) { - i0 = i + CDFT_LOOP_DIV_4; - if (i0 > mh - 4) { - i0 = mh - 4; - } - for (j = i + 2; j < i0; j += 4) { - - wd1r -= Mult_W_W(ss1, wk1i); - wd1i += Mult_W_W(ss1, wk1r); - wd3r -= Mult_W_W(ss3, wk3i); - wd3i += Mult_W_W(ss3, wk3r); - - j1 = j + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j] + a[j2]; - x0i = -a[j + 1] - a[j2 + 1]; - x1r = a[j] - a[j2]; - x1i = -a[j + 1] + a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i - x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i + x2i; - x0r = x1r + x3i; - x0i = x1i + x3r; - a[j2] = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); - a[j2 + 1] = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); - x0r = x1r - x3i; - x0i = x1i - x3r; - a[j3] = Mult_W_W(wk3r, x0r) + Mult_W_W(wk3i, x0i); - a[j3 + 1] = Mult_W_W(wk3r, x0i) - Mult_W_W(wk3i, x0r); - x0r = a[j + 2] + a[j2 + 2]; - x0i = -a[j + 3] - a[j2 + 3]; - x1r = a[j + 2] - a[j2 + 2]; - x1i = -a[j + 3] + a[j2 + 3]; - x2r = a[j1 + 2] + a[j3 + 2]; - x2i = a[j1 + 3] + a[j3 + 3]; - x3r = a[j1 + 2] - a[j3 + 2]; - x3i = a[j1 + 3] - a[j3 + 3]; - a[j + 2] = x0r + x2r; - a[j + 3] = x0i - x2i; - a[j1 + 2] = x0r - x2r; - a[j1 + 3] = x0i + x2i; - x0r = x1r + x3i; - x0i = x1i + x3r; - a[j2 + 2] = Mult_W_W(wd1r, x0r) - Mult_W_W(wd1i, x0i); - a[j2 + 3] = Mult_W_W(wd1r, x0i) + Mult_W_W(wd1i, x0r); - x0r = x1r - x3i; - x0i = x1i - x3r; - a[j3 + 2] = Mult_W_W(wd3r, x0r) + Mult_W_W(wd3i, x0i); - a[j3 + 3] = Mult_W_W(wd3r, x0i) - Mult_W_W(wd3i, x0r); - j0 = m - j; - j1 = j0 + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j0] + a[j2]; - x0i = -a[j0 + 1] - a[j2 + 1]; - x1r = a[j0] - a[j2]; - x1i = -a[j0 + 1] + a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[j0] = x0r + x2r; - a[j0 + 1] = x0i - x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i + x2i; - x0r = x1r + x3i; - x0i = x1i + x3r; - a[j2] = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); - a[j2 + 1] = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); - x0r = x1r - x3i; - x0i = x1i - x3r; - a[j3] = Mult_W_W(wk3i, x0r) + Mult_W_W(wk3r, x0i); - a[j3 + 1] = Mult_W_W(wk3i, x0i) - Mult_W_W(wk3r, x0r); - x0r = a[j0 - 2] + a[j2 - 2]; - x0i = -a[j0 - 1] - a[j2 - 1]; - x1r = a[j0 - 2] - a[j2 - 2]; - x1i = -a[j0 - 1] + a[j2 - 1]; - x2r = a[j1 - 2] + a[j3 - 2]; - x2i = a[j1 - 1] + a[j3 - 1]; - x3r = a[j1 - 2] - a[j3 - 2]; - x3i = a[j1 - 1] - a[j3 - 1]; - a[j0 - 2] = x0r + x2r; - a[j0 - 1] = x0i - x2i; - a[j1 - 2] = x0r - x2r; - a[j1 - 1] = x0i + x2i; - x0r = x1r + x3i; - x0i = x1i + x3r; - a[j2 - 2] = Mult_W_W(wd1i, x0r) - Mult_W_W(wd1r, x0i); - a[j2 - 1] = Mult_W_W(wd1i, x0i) + Mult_W_W(wd1r, x0r); - x0r = x1r - x3i; - x0i = x1i - x3r; - a[j3 - 2] = Mult_W_W(wd3i, x0r) + Mult_W_W(wd3r, x0i); - a[j3 - 1] = Mult_W_W(wd3i, x0i) - Mult_W_W(wd3r, x0r); - wk1r -= Mult_W_W(ss1, wd1i); - wk1i += Mult_W_W(ss1, wd1r); - wk3r -= Mult_W_W(ss3, wd3i); - wk3i += Mult_W_W(ss3, wd3r); - } - if (i0 == mh - 4) { - break; - } - } - wd1r = WR5000; - j0 = mh; - j1 = j0 + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j0 - 2] + a[j2 - 2]; - x0i = -a[j0 - 1] - a[j2 - 1]; - x1r = a[j0 - 2] - a[j2 - 2]; - x1i = -a[j0 - 1] + a[j2 - 1]; - x2r = a[j1 - 2] + a[j3 - 2]; - x2i = a[j1 - 1] + a[j3 - 1]; - x3r = a[j1 - 2] - a[j3 - 2]; - x3i = a[j1 - 1] - a[j3 - 1]; - a[j0 - 2] = x0r + x2r; - a[j0 - 1] = x0i - x2i; - a[j1 - 2] = x0r - x2r; - a[j1 - 1] = x0i + x2i; - x0r = x1r + x3i; - x0i = x1i + x3r; - a[j2 - 2] = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); - a[j2 - 1] = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); - x0r = x1r - x3i; - x0i = x1i - x3r; - a[j3 - 2] = Mult_W_W(wk3r, x0r) + Mult_W_W(wk3i, x0i); - a[j3 - 1] = Mult_W_W(wk3r, x0i) - Mult_W_W(wk3i, x0r); - x0r = a[j0] + a[j2]; - x0i = -a[j0 + 1] - a[j2 + 1]; - x1r = a[j0] - a[j2]; - x1i = -a[j0 + 1] + a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[j0] = x0r + x2r; - a[j0 + 1] = x0i - x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i + x2i; - x0r = x1r + x3i; - x0i = x1i + x3r; - a[j2] = picofftsg_mult_w_a(wd1r, (x0r - x0i)); - a[j2 + 1] = picofftsg_mult_w_a(wd1r, (x0i + x0r)); - x0r = x1r - x3i; - x0i = x1i - x3r; - a[j3] = -picofftsg_mult_w_a(wd1r, (x0r + x0i)); - a[j3 + 1] = -picofftsg_mult_w_a(wd1r, (x0i - x0r)); - x0r = a[j0 + 2] + a[j2 + 2]; - x0i = -a[j0 + 3] - a[j2 + 3]; - x1r = a[j0 + 2] - a[j2 + 2]; - x1i = -a[j0 + 3] + a[j2 + 3]; - x2r = a[j1 + 2] + a[j3 + 2]; - x2i = a[j1 + 3] + a[j3 + 3]; - x3r = a[j1 + 2] - a[j3 + 2]; - x3i = a[j1 + 3] - a[j3 + 3]; - a[j0 + 2] = x0r + x2r; - a[j0 + 3] = x0i - x2i; - a[j1 + 2] = x0r - x2r; - a[j1 + 3] = x0i + x2i; - x0r = x1r + x3i; - x0i = x1i + x3r; - a[j2 + 2] = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); - a[j2 + 3] = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); - x0r = x1r - x3i; - x0i = x1i - x3r; - a[j3 + 2] = Mult_W_W(wk3i, x0r) + Mult_W_W(wk3r, x0i); - a[j3 + 3] = Mult_W_W(wk3i, x0i) - Mult_W_W(wk3r, x0r); -} - -void cftrec4(picoos_int32 n, PICOFFTSG_FFTTYPE *a) -{ - picoos_int32 isplt, j, k, m; - - m = n; - while (m > 512) { - m >>= 2; - cftmdl1(m, &a[n - m]); - } - cftleaf(m, 1, &a[n - m]); - k = 0; - for (j = n - m; j > 0; j -= m) { - k++; - isplt = cfttree(m, j, k, a); - cftleaf(m, isplt, &a[j - m]); - } -} - - -picoos_int32 cfttree(picoos_int32 n, picoos_int32 j, picoos_int32 k, PICOFFTSG_FFTTYPE *a) -{ - picoos_int32 i, isplt, m; - - if ((k & 3) != 0) { - isplt = k & 1; - if (isplt != 0) { - cftmdl1(n, &a[j - n]); - } else { - cftmdl2(n, &a[j - n]); - } - } else { - m = n; - for (i = k; (i & 3) == 0; i >>= 2) { - m <<= 2; - } - isplt = i & 1; - if (isplt != 0) { - while (m > 128) { - cftmdl1(m, &a[j - m]); - m >>= 2; - } - } else { - while (m > 128) { - cftmdl2(m, &a[j - m]); - m >>= 2; - } - } - } - return isplt; -} - - -void cftleaf(picoos_int32 n, picoos_int32 isplt, PICOFFTSG_FFTTYPE *a) -{ - - if (n == 512) { - cftmdl1(128, a); - cftf161(a); - cftf162(&a[32]); - cftf161(&a[64]); - cftf161(&a[96]); - cftmdl2(128, &a[128]); - cftf161(&a[128]); - cftf162(&a[160]); - cftf161(&a[192]); - cftf162(&a[224]); - cftmdl1(128, &a[256]); - cftf161(&a[256]); - cftf162(&a[288]); - cftf161(&a[320]); - cftf161(&a[352]); - if (isplt != 0) { - cftmdl1(128, &a[384]); - cftf161(&a[480]); - } else { - cftmdl2(128, &a[384]); - cftf162(&a[480]); - } - cftf161(&a[384]); - cftf162(&a[416]); - cftf161(&a[448]); - } else { - cftmdl1(64, a); - cftf081(a); - cftf082(&a[16]); - cftf081(&a[32]); - cftf081(&a[48]); - cftmdl2(64, &a[64]); - cftf081(&a[64]); - cftf082(&a[80]); - cftf081(&a[96]); - cftf082(&a[112]); - cftmdl1(64, &a[128]); - cftf081(&a[128]); - cftf082(&a[144]); - cftf081(&a[160]); - cftf081(&a[176]); - if (isplt != 0) { - cftmdl1(64, &a[192]); - cftf081(&a[240]); - } else { - cftmdl2(64, &a[192]); - cftf082(&a[240]); - } - cftf081(&a[192]); - cftf082(&a[208]); - cftf081(&a[224]); - } -} - - -void cftmdl1(picoos_int32 n, PICOFFTSG_FFTTYPE *a) -{ - picoos_int32 i, i0, j, j0, j1, j2, j3, m, mh; - PICOFFTSG_FFTTYPE wk1r, wk1i, wk3r, wk3i, - wd1r, wd1i, wd3r, wd3i, ss1, ss3; - PICOFFTSG_FFTTYPE x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - mh = n >> 3; - m = 2 * mh; - j1 = m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[0] + a[j2]; - x0i = a[1] + a[j2 + 1]; - x1r = a[0] - a[j2]; - x1i = a[1] - a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[0] = x0r + x2r; - a[1] = x0i + x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i - x2i; - a[j2] = x1r - x3i; - a[j2 + 1] = x1i + x3r; - a[j3] = x1r + x3i; - a[j3 + 1] = x1i - x3r; - wd1r = (PICOFFTSG_FFTTYPE)(PICODSP_WGT_SHIFT); - wd1i = 0; - wd3r = (PICOFFTSG_FFTTYPE)(PICODSP_WGT_SHIFT); - wd3i = 0; - wk1r = (PICOFFTSG_FFTTYPE) (0.980785250664 *PICODSP_WGT_SHIFT); - wk1i = (PICOFFTSG_FFTTYPE) (0.195090323687 *PICODSP_WGT_SHIFT); - ss1 = (PICOFFTSG_FFTTYPE) (0.390180647373 *PICODSP_WGT_SHIFT); - wk3i = (PICOFFTSG_FFTTYPE) (-0.555570185184 *PICODSP_WGT_SHIFT); - wk3r = (PICOFFTSG_FFTTYPE) (0.831469595432 *PICODSP_WGT_SHIFT); - ss3 = (PICOFFTSG_FFTTYPE) (-1.111140370369 *PICODSP_WGT_SHIFT); - - i = 0; - for (;;) { - i0 = i + CDFT_LOOP_DIV_4; - if (i0 > mh - 4) { - i0 = mh - 4; - } - for (j = i + 2; j < i0; j += 4) { - wd1r -= Mult_W_W(ss1, wk1i); - wd1i += Mult_W_W(ss1, wk1r); - wd3r -= Mult_W_W(ss3, wk3i); - wd3i += Mult_W_W(ss3, wk3r); - j1 = j + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j] + a[j2]; - x0i = a[j + 1] + a[j2 + 1]; - x1r = a[j] - a[j2]; - x1i = a[j + 1] - a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2] = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); - a[j2 + 1] = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = Mult_W_W(wk3r, x0r) + Mult_W_W(wk3i, x0i); - a[j3 + 1] = Mult_W_W(wk3r, x0i) - Mult_W_W(wk3i, x0r); - x0r = a[j + 2] + a[j2 + 2]; - x0i = a[j + 3] + a[j2 + 3]; - x1r = a[j + 2] - a[j2 + 2]; - x1i = a[j + 3] - a[j2 + 3]; - x2r = a[j1 + 2] + a[j3 + 2]; - x2i = a[j1 + 3] + a[j3 + 3]; - x3r = a[j1 + 2] - a[j3 + 2]; - x3i = a[j1 + 3] - a[j3 + 3]; - a[j + 2] = x0r + x2r; - a[j + 3] = x0i + x2i; - a[j1 + 2] = x0r - x2r; - a[j1 + 3] = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2 + 2] = Mult_W_W(wd1r, x0r) - Mult_W_W(wd1i, x0i); - a[j2 + 3] = Mult_W_W(wd1r, x0i) + Mult_W_W(wd1i, x0r); - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3 + 2] = Mult_W_W(wd3r, x0r) + Mult_W_W(wd3i, x0i); - a[j3 + 3] = Mult_W_W(wd3r, x0i) - Mult_W_W(wd3i, x0r); - j0 = m - j; - j1 = j0 + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j0] + a[j2]; - x0i = a[j0 + 1] + a[j2 + 1]; - x1r = a[j0] - a[j2]; - x1i = a[j0 + 1] - a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[j0] = x0r + x2r; - a[j0 + 1] = x0i + x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2] = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); - a[j2 + 1] = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = Mult_W_W(wk3i, x0r) + Mult_W_W(wk3r, x0i); - a[j3 + 1] = Mult_W_W(wk3i, x0i) - Mult_W_W(wk3r, x0r); - x0r = a[j0 - 2] + a[j2 - 2]; - x0i = a[j0 - 1] + a[j2 - 1]; - x1r = a[j0 - 2] - a[j2 - 2]; - x1i = a[j0 - 1] - a[j2 - 1]; - x2r = a[j1 - 2] + a[j3 - 2]; - x2i = a[j1 - 1] + a[j3 - 1]; - x3r = a[j1 - 2] - a[j3 - 2]; - x3i = a[j1 - 1] - a[j3 - 1]; - a[j0 - 2] = x0r + x2r; - a[j0 - 1] = x0i + x2i; - a[j1 - 2] = x0r - x2r; - a[j1 - 1] = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2 - 2] = Mult_W_W(wd1i, x0r) - Mult_W_W(wd1r, x0i); - a[j2 - 1] = Mult_W_W(wd1i, x0i) + Mult_W_W(wd1r, x0r); - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3 - 2] = Mult_W_W(wd3i, x0r) + Mult_W_W(wd3r, x0i); - a[j3 - 1] = Mult_W_W(wd3i, x0i) - Mult_W_W(wd3r, x0r); - wk1r -= Mult_W_W(ss1, wd1i); - wk1i += Mult_W_W(ss1, wd1r); - wk3r -= Mult_W_W(ss3, wd3i); - wk3i += Mult_W_W(ss3, wd3r); - } - if (i0 == mh - 4) { - break; - } - } - wd1r = WR5000; - j0 = mh; - j1 = j0 + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j0 - 2] + a[j2 - 2]; - x0i = a[j0 - 1] + a[j2 - 1]; - x1r = a[j0 - 2] - a[j2 - 2]; - x1i = a[j0 - 1] - a[j2 - 1]; - x2r = a[j1 - 2] + a[j3 - 2]; - x2i = a[j1 - 1] + a[j3 - 1]; - x3r = a[j1 - 2] - a[j3 - 2]; - x3i = a[j1 - 1] - a[j3 - 1]; - a[j0 - 2] = x0r + x2r; - a[j0 - 1] = x0i + x2i; - a[j1 - 2] = x0r - x2r; - a[j1 - 1] = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2 - 2] = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); - a[j2 - 1] = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3 - 2] = Mult_W_W(wk3r, x0r) + Mult_W_W(wk3i, x0i); - a[j3 - 1] = Mult_W_W(wk3r, x0i) - Mult_W_W(wk3i, x0r); - x0r = a[j0] + a[j2]; - x0i = a[j0 + 1] + a[j2 + 1]; - x1r = a[j0] - a[j2]; - x1i = a[j0 + 1] - a[j2 + 1]; - x2r = a[j1] + a[j3]; - x2i = a[j1 + 1] + a[j3 + 1]; - x3r = a[j1] - a[j3]; - x3i = a[j1 + 1] - a[j3 + 1]; - a[j0] = x0r + x2r; - a[j0 + 1] = x0i + x2i; - a[j1] = x0r - x2r; - a[j1 + 1] = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2] = picofftsg_mult_w_a(wd1r, (x0r - x0i)); - a[j2 + 1] = picofftsg_mult_w_a(wd1r, (x0i + x0r)); - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = -picofftsg_mult_w_a(wd1r, (x0r + x0i)); - a[j3 + 1] = -picofftsg_mult_w_a(wd1r, (x0i - x0r)); - x0r = a[j0 + 2] + a[j2 + 2]; - x0i = a[j0 + 3] + a[j2 + 3]; - x1r = a[j0 + 2] - a[j2 + 2]; - x1i = a[j0 + 3] - a[j2 + 3]; - x2r = a[j1 + 2] + a[j3 + 2]; - x2i = a[j1 + 3] + a[j3 + 3]; - x3r = a[j1 + 2] - a[j3 + 2]; - x3i = a[j1 + 3] - a[j3 + 3]; - a[j0 + 2] = x0r + x2r; - a[j0 + 3] = x0i + x2i; - a[j1 + 2] = x0r - x2r; - a[j1 + 3] = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j2 + 2] = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); - a[j2 + 3] = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3 + 2] = Mult_W_W(wk3i, x0r) + Mult_W_W(wk3r, x0i); - a[j3 + 3] = Mult_W_W(wk3i, x0i) - Mult_W_W(wk3r, x0r); -} - - -void cftmdl2(picoos_int32 n, PICOFFTSG_FFTTYPE *a) -{ - picoos_int32 i, i0, j, j0, j1, j2, j3, m, mh; - PICOFFTSG_FFTTYPE wn4r, wk1r, wk1i, wk3r, wk3i, - wl1r, wl1i, wl3r, wl3i, wd1r, wd1i, wd3r, wd3i, - we1r, we1i, we3r, we3i, ss1, ss3; - PICOFFTSG_FFTTYPE x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y2r, y2i; - - mh = n >> 3; - m = 2 * mh; - wn4r = WR5000; - j1 = m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[0] - a[j2 + 1]; - x0i = a[1] + a[j2]; - x1r = a[0] + a[j2 + 1]; - x1i = a[1] - a[j2]; - x2r = a[j1] - a[j3 + 1]; - x2i = a[j1 + 1] + a[j3]; - x3r = a[j1] + a[j3 + 1]; - x3i = a[j1 + 1] - a[j3]; - y0r = picofftsg_mult_w_a(wn4r, (x2r - x2i)); - y0i = picofftsg_mult_w_a(wn4r, (x2i + x2r)); - a[0] = x0r + y0r; - a[1] = x0i + y0i; - a[j1] = x0r - y0r; - a[j1 + 1] = x0i - y0i; - y0r = picofftsg_mult_w_a(wn4r, (x3r - x3i)); - y0i = picofftsg_mult_w_a(wn4r, (x3i + x3r)); - a[j2] = x1r - y0i; - a[j2 + 1] = x1i + y0r; - a[j3] = x1r + y0i; - a[j3 + 1] = x1i - y0r; - wl1r = PICODSP_WGT_SHIFT; - wl1i = 0; - wl3r = PICODSP_WGT_SHIFT; - wl3i = 0; - we1r = wn4r; - we1i = wn4r; - we3r = -wn4r; - we3i = -wn4r; - - wk1r = (PICOFFTSG_FFTTYPE)(0.995184719563 *PICODSP_WGT_SHIFT); - wk1i = (PICOFFTSG_FFTTYPE)(0.098017141223 *PICODSP_WGT_SHIFT); - wd1r = (PICOFFTSG_FFTTYPE)(0.634393274784 *PICODSP_WGT_SHIFT); - wd1i = (PICOFFTSG_FFTTYPE)(0.773010432720 *PICODSP_WGT_SHIFT); - ss1 = (PICOFFTSG_FFTTYPE)(0.196034282446 *PICODSP_WGT_SHIFT); - wk3i = (PICOFFTSG_FFTTYPE)(-0.290284663439 *PICODSP_WGT_SHIFT); - wk3r = (PICOFFTSG_FFTTYPE)(0.956940352917 *PICODSP_WGT_SHIFT); - ss3 = (PICOFFTSG_FFTTYPE)(-0.580569326878 *PICODSP_WGT_SHIFT); - wd3r = (PICOFFTSG_FFTTYPE)(-0.881921231747 *PICODSP_WGT_SHIFT); - wd3i = (PICOFFTSG_FFTTYPE)(-0.471396744251 *PICODSP_WGT_SHIFT); - - i = 0; - for (;;) { - i0 = i + 4 * CDFT_LOOP_DIV; - if (i0 > mh - 4) { - i0 = mh - 4; - } - for (j = i + 2; j < i0; j += 4) { - wl1r -= Mult_W_W(ss1, wk1i); - wl1i += Mult_W_W(ss1, wk1r); - wl3r -= Mult_W_W(ss3, wk3i); - wl3i += Mult_W_W(ss3, wk3r); - we1r -= Mult_W_W(ss1, wd1i); - we1i += Mult_W_W(ss1, wd1r); - we3r -= Mult_W_W(ss3, wd3i); - we3i += Mult_W_W(ss3, wd3r); - j1 = j + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j] - a[j2 + 1]; - x0i = a[j + 1] + a[j2]; - x1r = a[j] + a[j2 + 1]; - x1i = a[j + 1] - a[j2]; - x2r = a[j1] - a[j3 + 1]; - x2i = a[j1 + 1] + a[j3]; - x3r = a[j1] + a[j3 + 1]; - x3i = a[j1 + 1] - a[j3]; - y0r = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); - y0i = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); - y2r = Mult_W_W(wd1r, x2r) - Mult_W_W(wd1i, x2i); - y2i = Mult_W_W(wd1r, x2i) + Mult_W_W(wd1i, x2r); - a[j] = y0r + y2r; - a[j + 1] = y0i + y2i; - a[j1] = y0r - y2r; - a[j1 + 1] = y0i - y2i; - y0r = Mult_W_W(wk3r, x1r) + Mult_W_W(wk3i, x1i); - y0i = Mult_W_W(wk3r, x1i) - Mult_W_W(wk3i, x1r); - y2r = Mult_W_W(wd3r, x3r) + Mult_W_W(wd3i, x3i); - y2i = Mult_W_W(wd3r, x3i) - Mult_W_W(wd3i, x3r); - a[j2] = y0r + y2r; - a[j2 + 1] = y0i + y2i; - a[j3] = y0r - y2r; - a[j3 + 1] = y0i - y2i; - x0r = a[j + 2] - a[j2 + 3]; - x0i = a[j + 3] + a[j2 + 2]; - x1r = a[j + 2] + a[j2 + 3]; - x1i = a[j + 3] - a[j2 + 2]; - x2r = a[j1 + 2] - a[j3 + 3]; - x2i = a[j1 + 3] + a[j3 + 2]; - x3r = a[j1 + 2] + a[j3 + 3]; - x3i = a[j1 + 3] - a[j3 + 2]; - y0r = Mult_W_W(wl1r, x0r) - Mult_W_W(wl1i, x0i); - y0i = Mult_W_W(wl1r, x0i) + Mult_W_W(wl1i, x0r); - y2r = Mult_W_W(we1r, x2r) - Mult_W_W(we1i, x2i); - y2i = Mult_W_W(we1r, x2i) + Mult_W_W(we1i, x2r); - a[j + 2] = y0r + y2r; - a[j + 3] = y0i + y2i; - a[j1 + 2] = y0r - y2r; - a[j1 + 3] = y0i - y2i; - y0r = Mult_W_W(wl3r, x1r) + Mult_W_W(wl3i, x1i); - y0i = Mult_W_W(wl3r, x1i) - Mult_W_W(wl3i, x1r); - y2r = Mult_W_W(we3r, x3r) + Mult_W_W(we3i, x3i); - y2i = Mult_W_W(we3r, x3i) - Mult_W_W(we3i, x3r); - a[j2 + 2] = y0r + y2r; - a[j2 + 3] = y0i + y2i; - a[j3 + 2] = y0r - y2r; - a[j3 + 3] = y0i - y2i; - j0 = m - j; - j1 = j0 + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j0] - a[j2 + 1]; - x0i = a[j0 + 1] + a[j2]; - x1r = a[j0] + a[j2 + 1]; - x1i = a[j0 + 1] - a[j2]; - x2r = a[j1] - a[j3 + 1]; - x2i = a[j1 + 1] + a[j3]; - x3r = a[j1] + a[j3 + 1]; - x3i = a[j1 + 1] - a[j3]; - y0r = Mult_W_W(wd1i, x0r) - Mult_W_W(wd1r, x0i); - y0i = Mult_W_W(wd1i, x0i) + Mult_W_W(wd1r, x0r); - y2r = Mult_W_W(wk1i, x2r) - Mult_W_W(wk1r, x2i); - y2i = Mult_W_W(wk1i, x2i) + Mult_W_W(wk1r, x2r); - a[j0] = y0r + y2r; - a[j0 + 1] = y0i + y2i; - a[j1] = y0r - y2r; - a[j1 + 1] = y0i - y2i; - y0r = Mult_W_W(wd3i, x1r) + Mult_W_W(wd3r, x1i); - y0i = Mult_W_W(wd3i, x1i) - Mult_W_W(wd3r, x1r); - y2r = Mult_W_W(wk3i, x3r) + Mult_W_W(wk3r, x3i); - y2i = Mult_W_W(wk3i, x3i) - Mult_W_W(wk3r, x3r); - a[j2] = y0r + y2r; - a[j2 + 1] = y0i + y2i; - a[j3] = y0r - y2r; - a[j3 + 1] = y0i - y2i; - x0r = a[j0 - 2] - a[j2 - 1]; - x0i = a[j0 - 1] + a[j2 - 2]; - x1r = a[j0 - 2] + a[j2 - 1]; - x1i = a[j0 - 1] - a[j2 - 2]; - x2r = a[j1 - 2] - a[j3 - 1]; - x2i = a[j1 - 1] + a[j3 - 2]; - x3r = a[j1 - 2] + a[j3 - 1]; - x3i = a[j1 - 1] - a[j3 - 2]; - y0r = Mult_W_W(we1i, x0r) - Mult_W_W(we1r, x0i); - y0i = Mult_W_W(we1i, x0i) + Mult_W_W(we1r, x0r); - y2r = Mult_W_W(wl1i, x2r) - Mult_W_W(wl1r, x2i); - y2i = Mult_W_W(wl1i, x2i) + Mult_W_W(wl1r, x2r); - a[j0 - 2] = y0r + y2r; - a[j0 - 1] = y0i + y2i; - a[j1 - 2] = y0r - y2r; - a[j1 - 1] = y0i - y2i; - y0r = Mult_W_W(we3i, x1r) + Mult_W_W(we3r, x1i); - y0i = Mult_W_W(we3i, x1i) - Mult_W_W(we3r, x1r); - y2r = Mult_W_W(wl3i, x3r) + Mult_W_W(wl3r, x3i); - y2i = Mult_W_W(wl3i, x3i) - Mult_W_W(wl3r, x3r); - a[j2 - 2] = y0r + y2r; - a[j2 - 1] = y0i + y2i; - a[j3 - 2] = y0r - y2r; - a[j3 - 1] = y0i - y2i; - wk1r -= Mult_W_W(ss1, wl1i); - wk1i += Mult_W_W(ss1, wl1r); - wk3r -= Mult_W_W(ss3, wl3i); - wk3i += Mult_W_W(ss3, wl3r); - wd1r -= Mult_W_W(ss1, we1i); - wd1i += Mult_W_W(ss1, we1r); - wd3r -= Mult_W_W(ss3, we3i); - wd3i += Mult_W_W(ss3, we3r); - } - if (i0 == mh - 4) { - break; - } - } - wl1r = WR2500; - wl1i = WI2500; - j0 = mh; - j1 = j0 + m; - j2 = j1 + m; - j3 = j2 + m; - x0r = a[j0 - 2] - a[j2 - 1]; - x0i = a[j0 - 1] + a[j2 - 2]; - x1r = a[j0 - 2] + a[j2 - 1]; - x1i = a[j0 - 1] - a[j2 - 2]; - x2r = a[j1 - 2] - a[j3 - 1]; - x2i = a[j1 - 1] + a[j3 - 2]; - x3r = a[j1 - 2] + a[j3 - 1]; - x3i = a[j1 - 1] - a[j3 - 2]; - y0r = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); - y0i = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); - y2r = Mult_W_W(wd1r, x2r) - Mult_W_W(wd1i, x2i); - y2i = Mult_W_W(wd1r, x2i) + Mult_W_W(wd1i, x2r); - a[j0 - 2] = y0r + y2r; - a[j0 - 1] = y0i + y2i; - a[j1 - 2] = y0r - y2r; - a[j1 - 1] = y0i - y2i; - y0r = Mult_W_W(wk3r, x1r) + Mult_W_W(wk3i, x1i); - y0i = Mult_W_W(wk3r, x1i) - Mult_W_W(wk3i, x1r); - y2r = Mult_W_W(wd3r, x3r) + Mult_W_W(wd3i, x3i); - y2i = Mult_W_W(wd3r, x3i) - Mult_W_W(wd3i, x3r); - a[j2 - 2] = y0r + y2r; - a[j2 - 1] = y0i + y2i; - a[j3 - 2] = y0r - y2r; - a[j3 - 1] = y0i - y2i; - x0r = a[j0] - a[j2 + 1]; - x0i = a[j0 + 1] + a[j2]; - x1r = a[j0] + a[j2 + 1]; - x1i = a[j0 + 1] - a[j2]; - x2r = a[j1] - a[j3 + 1]; - x2i = a[j1 + 1] + a[j3]; - x3r = a[j1] + a[j3 + 1]; - x3i = a[j1 + 1] - a[j3]; - y0r = Mult_W_W(wl1r, x0r) - Mult_W_W(wl1i, x0i); - y0i = Mult_W_W(wl1r, x0i) + Mult_W_W(wl1i, x0r); - y2r = Mult_W_W(wl1i, x2r) - Mult_W_W(wl1r, x2i); - y2i = Mult_W_W(wl1i, x2i) + Mult_W_W(wl1r, x2r); - a[j0] = y0r + y2r; - a[j0 + 1] = y0i + y2i; - a[j1] = y0r - y2r; - a[j1 + 1] = y0i - y2i; - y0r = Mult_W_W(wl1i, x1r) - Mult_W_W(wl1r, x1i); - y0i = Mult_W_W(wl1i, x1i) + Mult_W_W(wl1r, x1r); - y2r = Mult_W_W(wl1r, x3r) - Mult_W_W(wl1i, x3i); - y2i = Mult_W_W(wl1r, x3i) + Mult_W_W(wl1i, x3r); - a[j2] = y0r - y2r; - a[j2 + 1] = y0i - y2i; - a[j3] = y0r + y2r; - a[j3 + 1] = y0i + y2i; - x0r = a[j0 + 2] - a[j2 + 3]; - x0i = a[j0 + 3] + a[j2 + 2]; - x1r = a[j0 + 2] + a[j2 + 3]; - x1i = a[j0 + 3] - a[j2 + 2]; - x2r = a[j1 + 2] - a[j3 + 3]; - x2i = a[j1 + 3] + a[j3 + 2]; - x3r = a[j1 + 2] + a[j3 + 3]; - x3i = a[j1 + 3] - a[j3 + 2]; - y0r = Mult_W_W(wd1i, x0r) - Mult_W_W(wd1r, x0i); - y0i = Mult_W_W(wd1i, x0i) + Mult_W_W(wd1r, x0r); - y2r = Mult_W_W(wk1i, x2r) - Mult_W_W(wk1r, x2i); - y2i = Mult_W_W(wk1i, x2i) + Mult_W_W(wk1r, x2r); - a[j0 + 2] = y0r + y2r; - a[j0 + 3] = y0i + y2i; - a[j1 + 2] = y0r - y2r; - a[j1 + 3] = y0i - y2i; - y0r = Mult_W_W(wd3i, x1r) + Mult_W_W(wd3r, x1i); - y0i = Mult_W_W(wd3i, x1i) - Mult_W_W(wd3r, x1r); - y2r = Mult_W_W(wk3i, x3r) + Mult_W_W(wk3r, x3i); - y2i = Mult_W_W(wk3i, x3i) - Mult_W_W(wk3r, x3r); - a[j2 + 2] = y0r + y2r; - a[j2 + 3] = y0i + y2i; - a[j3 + 2] = y0r - y2r; - a[j3 + 3] = y0i - y2i; -} - - -void cftfx41(picoos_int32 n, PICOFFTSG_FFTTYPE *a) -{ - - if (n == 128) { - cftf161(a); - cftf162(&a[32]); - cftf161(&a[64]); - cftf161(&a[96]); - } else { - cftf081(a); - cftf082(&a[16]); - cftf081(&a[32]); - cftf081(&a[48]); - } -} - - -void cftf161(PICOFFTSG_FFTTYPE *a) -{ - PICOFFTSG_FFTTYPE wn4r, wk1r, wk1i, - x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, - y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, - y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, - y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, - y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; - - wn4r = WR5000; - wk1r = WR2500; - wk1i = WI2500; - x0r = a[0] + a[16]; - x0i = a[1] + a[17]; - x1r = a[0] - a[16]; - x1i = a[1] - a[17]; - x2r = a[8] + a[24]; - x2i = a[9] + a[25]; - x3r = a[8] - a[24]; - x3i = a[9] - a[25]; - y0r = x0r + x2r; - y0i = x0i + x2i; - y4r = x0r - x2r; - y4i = x0i - x2i; - y8r = x1r - x3i; - y8i = x1i + x3r; - y12r = x1r + x3i; - y12i = x1i - x3r; - x0r = a[2] + a[18]; - x0i = a[3] + a[19]; - x1r = a[2] - a[18]; - x1i = a[3] - a[19]; - x2r = a[10] + a[26]; - x2i = a[11] + a[27]; - x3r = a[10] - a[26]; - x3i = a[11] - a[27]; - y1r = x0r + x2r; - y1i = x0i + x2i; - y5r = x0r - x2r; - y5i = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - y9r = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); - y9i = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); - x0r = x1r + x3i; - x0i = x1i - x3r; - y13r = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); - y13i = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); - x0r = a[4] + a[20]; - x0i = a[5] + a[21]; - x1r = a[4] - a[20]; - x1i = a[5] - a[21]; - x2r = a[12] + a[28]; - x2i = a[13] + a[29]; - x3r = a[12] - a[28]; - x3i = a[13] - a[29]; - y2r = x0r + x2r; - y2i = x0i + x2i; - y6r = x0r - x2r; - y6i = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - y10r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); - y10i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); - x0r = x1r + x3i; - x0i = x1i - x3r; - y14r = picofftsg_mult_w_a(wn4r, (x0r + x0i)); - y14i = picofftsg_mult_w_a(wn4r, (x0i - x0r)); - x0r = a[6] + a[22]; - x0i = a[7] + a[23]; - x1r = a[6] - a[22]; - x1i = a[7] - a[23]; - x2r = a[14] + a[30]; - x2i = a[15] + a[31]; - x3r = a[14] - a[30]; - x3i = a[15] - a[31]; - y3r = x0r + x2r; - y3i = x0i + x2i; - y7r = x0r - x2r; - y7i = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - y11r = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); - y11i = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); - x0r = x1r + x3i; - x0i = x1i - x3r; - y15r = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); - y15i = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); - x0r = y12r - y14r; - x0i = y12i - y14i; - x1r = y12r + y14r; - x1i = y12i + y14i; - x2r = y13r - y15r; - x2i = y13i - y15i; - x3r = y13r + y15r; - x3i = y13i + y15i; - a[24] = x0r + x2r; - a[25] = x0i + x2i; - a[26] = x0r - x2r; - a[27] = x0i - x2i; - a[28] = x1r - x3i; - a[29] = x1i + x3r; - a[30] = x1r + x3i; - a[31] = x1i - x3r; - x0r = y8r + y10r; - x0i = y8i + y10i; - x1r = y8r - y10r; - x1i = y8i - y10i; - x2r = y9r + y11r; - x2i = y9i + y11i; - x3r = y9r - y11r; - x3i = y9i - y11i; - a[16] = x0r + x2r; - a[17] = x0i + x2i; - a[18] = x0r - x2r; - a[19] = x0i - x2i; - a[20] = x1r - x3i; - a[21] = x1i + x3r; - a[22] = x1r + x3i; - a[23] = x1i - x3r; - x0r = y5r - y7i; - x0i = y5i + y7r; - x2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); - x2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); - x0r = y5r + y7i; - x0i = y5i - y7r; - x3r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); - x3i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); - x0r = y4r - y6i; - x0i = y4i + y6r; - x1r = y4r + y6i; - x1i = y4i - y6r; - a[8] = x0r + x2r; - a[9] = x0i + x2i; - a[10] = x0r - x2r; - a[11] = x0i - x2i; - a[12] = x1r - x3i; - a[13] = x1i + x3r; - a[14] = x1r + x3i; - a[15] = x1i - x3r; - x0r = y0r + y2r; - x0i = y0i + y2i; - x1r = y0r - y2r; - x1i = y0i - y2i; - x2r = y1r + y3r; - x2i = y1i + y3i; - x3r = y1r - y3r; - x3i = y1i - y3i; - a[0] = x0r + x2r; - a[1] = x0i + x2i; - a[2] = x0r - x2r; - a[3] = x0i - x2i; - a[4] = x1r - x3i; - a[5] = x1i + x3r; - a[6] = x1r + x3i; - a[7] = x1i - x3r; -} - - -void cftf162(PICOFFTSG_FFTTYPE *a) -{ - PICOFFTSG_FFTTYPE wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, - x0r, x0i, x1r, x1i, x2r, x2i, - y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, - y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, - y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, - y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; - - wn4r = WR5000; - wk1r = WR1250; - wk1i = WI1250; - wk2r = WR2500; - wk2i = WI2500; - wk3r = WR3750; - wk3i = WI3750; - x1r = a[0] - a[17]; - x1i = a[1] + a[16]; - x0r = a[8] - a[25]; - x0i = a[9] + a[24]; - x2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); - x2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); - y0r = x1r + x2r; - y0i = x1i + x2i; - y4r = x1r - x2r; - y4i = x1i - x2i; - x1r = a[0] + a[17]; - x1i = a[1] - a[16]; - x0r = a[8] + a[25]; - x0i = a[9] - a[24]; - x2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); - x2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); - y8r = x1r - x2i; - y8i = x1i + x2r; - y12r = x1r + x2i; - y12i = x1i - x2r; - x0r = a[2] - a[19]; - x0i = a[3] + a[18]; - x1r = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); - x1i = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); - x0r = a[10] - a[27]; - x0i = a[11] + a[26]; - x2r = Mult_W_W(wk3i, x0r) - Mult_W_W(wk3r, x0i); - x2i = Mult_W_W(wk3i, x0i) + Mult_W_W(wk3r, x0r); - y1r = x1r + x2r; - y1i = x1i + x2i; - y5r = x1r - x2r; - y5i = x1i - x2i; - x0r = a[2] + a[19]; - x0i = a[3] - a[18]; - x1r = Mult_W_W(wk3r, x0r) - Mult_W_W(wk3i, x0i); - x1i = Mult_W_W(wk3r, x0i) + Mult_W_W(wk3i, x0r); - x0r = a[10] + a[27]; - x0i = a[11] - a[26]; - x2r = Mult_W_W(wk1r, x0r) + Mult_W_W(wk1i, x0i); - x2i = Mult_W_W(wk1r, x0i) - Mult_W_W(wk1i, x0r); - y9r = x1r - x2r; - y9i = x1i - x2i; - y13r = x1r + x2r; - y13i = x1i + x2i; - x0r = a[4] - a[21]; - x0i = a[5] + a[20]; - x1r = Mult_W_W(wk2r, x0r) - Mult_W_W(wk2i, x0i); - x1i = Mult_W_W(wk2r, x0i) + Mult_W_W(wk2i, x0r); - x0r = a[12] - a[29]; - x0i = a[13] + a[28]; - x2r = Mult_W_W(wk2i, x0r) - Mult_W_W(wk2r, x0i); - x2i = Mult_W_W(wk2i, x0i) + Mult_W_W(wk2r, x0r); - y2r = x1r + x2r; - y2i = x1i + x2i; - y6r = x1r - x2r; - y6i = x1i - x2i; - x0r = a[4] + a[21]; - x0i = a[5] - a[20]; - x1r = Mult_W_W(wk2i, x0r) - Mult_W_W(wk2r, x0i); - x1i = Mult_W_W(wk2i, x0i) + Mult_W_W(wk2r, x0r); - x0r = a[12] + a[29]; - x0i = a[13] - a[28]; - x2r = Mult_W_W(wk2r, x0r) - Mult_W_W(wk2i, x0i); - x2i = Mult_W_W(wk2r, x0i) + Mult_W_W(wk2i, x0r); - y10r = x1r - x2r; - y10i = x1i - x2i; - y14r = x1r + x2r; - y14i = x1i + x2i; - x0r = a[6] - a[23]; - x0i = a[7] + a[22]; - x1r = Mult_W_W(wk3r, x0r) - Mult_W_W(wk3i, x0i); - x1i = Mult_W_W(wk3r, x0i) + Mult_W_W(wk3i, x0r); - x0r = a[14] - a[31]; - x0i = a[15] + a[30]; - x2r = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); - x2i = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); - y3r = x1r + x2r; - y3i = x1i + x2i; - y7r = x1r - x2r; - y7i = x1i - x2i; - x0r = a[6] + a[23]; - x0i = a[7] - a[22]; - x1r = Mult_W_W(wk1i, x0r) + Mult_W_W(wk1r, x0i); - x1i = Mult_W_W(wk1i, x0i) - Mult_W_W(wk1r, x0r); - x0r = a[14] + a[31]; - x0i = a[15] - a[30]; - x2r = Mult_W_W(wk3i, x0r) - Mult_W_W(wk3r, x0i); - x2i = Mult_W_W(wk3i, x0i) + Mult_W_W(wk3r, x0r); - y11r = x1r + x2r; - y11i = x1i + x2i; - y15r = x1r - x2r; - y15i = x1i - x2i; - x1r = y0r + y2r; - x1i = y0i + y2i; - x2r = y1r + y3r; - x2i = y1i + y3i; - a[0] = x1r + x2r; - a[1] = x1i + x2i; - a[2] = x1r - x2r; - a[3] = x1i - x2i; - x1r = y0r - y2r; - x1i = y0i - y2i; - x2r = y1r - y3r; - x2i = y1i - y3i; - a[4] = x1r - x2i; - a[5] = x1i + x2r; - a[6] = x1r + x2i; - a[7] = x1i - x2r; - x1r = y4r - y6i; - x1i = y4i + y6r; - x0r = y5r - y7i; - x0i = y5i + y7r; - x2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); - x2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); - a[8] = x1r + x2r; - a[9] = x1i + x2i; - a[10] = x1r - x2r; - a[11] = x1i - x2i; - x1r = y4r + y6i; - x1i = y4i - y6r; - x0r = y5r + y7i; - x0i = y5i - y7r; - x2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); - x2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); - a[12] = x1r - x2i; - a[13] = x1i + x2r; - a[14] = x1r + x2i; - a[15] = x1i - x2r; - x1r = y8r + y10r; - x1i = y8i + y10i; - x2r = y9r - y11r; - x2i = y9i - y11i; - a[16] = x1r + x2r; - a[17] = x1i + x2i; - a[18] = x1r - x2r; - a[19] = x1i - x2i; - x1r = y8r - y10r; - x1i = y8i - y10i; - x2r = y9r + y11r; - x2i = y9i + y11i; - a[20] = x1r - x2i; - a[21] = x1i + x2r; - a[22] = x1r + x2i; - a[23] = x1i - x2r; - x1r = y12r - y14i; - x1i = y12i + y14r; - x0r = y13r + y15i; - x0i = y13i - y15r; - x2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); - x2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); - a[24] = x1r + x2r; - a[25] = x1i + x2i; - a[26] = x1r - x2r; - a[27] = x1i - x2i; - x1r = y12r + y14i; - x1i = y12i - y14r; - x0r = y13r - y15i; - x0i = y13i + y15r; - x2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); - x2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); - a[28] = x1r - x2i; - a[29] = x1i + x2r; - a[30] = x1r + x2i; - a[31] = x1i - x2r; -} - - -void cftf081(PICOFFTSG_FFTTYPE *a) -{ - PICOFFTSG_FFTTYPE wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, - y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, - y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; - - wn4r = WR5000; - x0r = a[0] + a[8]; - x0i = a[1] + a[9]; - x1r = a[0] - a[8]; - x1i = a[1] - a[9]; - x2r = a[4] + a[12]; - x2i = a[5] + a[13]; - x3r = a[4] - a[12]; - x3i = a[5] - a[13]; - y0r = x0r + x2r; - y0i = x0i + x2i; - y2r = x0r - x2r; - y2i = x0i - x2i; - y1r = x1r - x3i; - y1i = x1i + x3r; - y3r = x1r + x3i; - y3i = x1i - x3r; - x0r = a[2] + a[10]; - x0i = a[3] + a[11]; - x1r = a[2] - a[10]; - x1i = a[3] - a[11]; - x2r = a[6] + a[14]; - x2i = a[7] + a[15]; - x3r = a[6] - a[14]; - x3i = a[7] - a[15]; - y4r = x0r + x2r; - y4i = x0i + x2i; - y6r = x0r - x2r; - y6i = x0i - x2i; - x0r = x1r - x3i; - x0i = x1i + x3r; - x2r = x1r + x3i; - x2i = x1i - x3r; - y5r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); - y5i = picofftsg_mult_w_a(wn4r, (x0r + x0i)); - y7r = picofftsg_mult_w_a(wn4r, (x2r - x2i)); - y7i = picofftsg_mult_w_a(wn4r, (x2r + x2i)); - a[8] = y1r + y5r; - a[9] = y1i + y5i; - a[10] = y1r - y5r; - a[11] = y1i - y5i; - a[12] = y3r - y7i; - a[13] = y3i + y7r; - a[14] = y3r + y7i; - a[15] = y3i - y7r; - a[0] = y0r + y4r; - a[1] = y0i + y4i; - a[2] = y0r - y4r; - a[3] = y0i - y4i; - a[4] = y2r - y6i; - a[5] = y2i + y6r; - a[6] = y2r + y6i; - a[7] = y2i - y6r; -} - - -void cftf082(PICOFFTSG_FFTTYPE *a) -{ - PICOFFTSG_FFTTYPE wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, - y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, - y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; - - wn4r = WR5000; - wk1r = WR2500; - wk1i = WI2500; - y0r = a[0] - a[9]; - y0i = a[1] + a[8]; - y1r = a[0] + a[9]; - y1i = a[1] - a[8]; - x0r = a[4] - a[13]; - x0i = a[5] + a[12]; - y2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); - y2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); - x0r = a[4] + a[13]; - x0i = a[5] - a[12]; - y3r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); - y3i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); - x0r = a[2] - a[11]; - x0i = a[3] + a[10]; - y4r = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); - y4i = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); - x0r = a[2] + a[11]; - x0i = a[3] - a[10]; - y5r = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); - y5i = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); - x0r = a[6] - a[15]; - x0i = a[7] + a[14]; - y6r = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); - y6i = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); - x0r = a[6] + a[15]; - x0i = a[7] - a[14]; - y7r = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); - y7i = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); - x0r = y0r + y2r; - x0i = y0i + y2i; - x1r = y4r + y6r; - x1i = y4i + y6i; - a[0] = x0r + x1r; - a[1] = x0i + x1i; - a[2] = x0r - x1r; - a[3] = x0i - x1i; - x0r = y0r - y2r; - x0i = y0i - y2i; - x1r = y4r - y6r; - x1i = y4i - y6i; - a[4] = x0r - x1i; - a[5] = x0i + x1r; - a[6] = x0r + x1i; - a[7] = x0i - x1r; - x0r = y1r - y3i; - x0i = y1i + y3r; - x1r = y5r - y7r; - x1i = y5i - y7i; - a[8] = x0r + x1r; - a[9] = x0i + x1i; - a[10] = x0r - x1r; - a[11] = x0i - x1i; - x0r = y1r + y3i; - x0i = y1i - y3r; - x1r = y5r + y7r; - x1i = y5i + y7i; - a[12] = x0r - x1i; - a[13] = x0i + x1r; - a[14] = x0r + x1i; - a[15] = x0i - x1r; -} - - -void cftf040(PICOFFTSG_FFTTYPE *a) -{ - PICOFFTSG_FFTTYPE x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - x0r = a[0] + a[4]; - x0i = a[1] + a[5]; - x1r = a[0] - a[4]; - x1i = a[1] - a[5]; - x2r = a[2] + a[6]; - x2i = a[3] + a[7]; - x3r = a[2] - a[6]; - x3i = a[3] - a[7]; - a[0] = x0r + x2r; - a[1] = x0i + x2i; - a[2] = x1r - x3i; - a[3] = x1i + x3r; - a[4] = x0r - x2r; - a[5] = x0i - x2i; - a[6] = x1r + x3i; - a[7] = x1i - x3r; -} - - -void cftb040(PICOFFTSG_FFTTYPE *a) -{ - PICOFFTSG_FFTTYPE x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - x0r = a[0] + a[4]; - x0i = a[1] + a[5]; - x1r = a[0] - a[4]; - x1i = a[1] - a[5]; - x2r = a[2] + a[6]; - x2i = a[3] + a[7]; - x3r = a[2] - a[6]; - x3i = a[3] - a[7]; - a[0] = x0r + x2r; - a[1] = x0i + x2i; - a[2] = x1r + x3i; - a[3] = x1i - x3r; - a[4] = x0r - x2r; - a[5] = x0i - x2i; - a[6] = x1r - x3i; - a[7] = x1i + x3r; -} - - -void cftx020(PICOFFTSG_FFTTYPE *a) -{ - PICOFFTSG_FFTTYPE x0r, x0i; - - x0r = a[0] - a[2]; - x0i = a[1] - a[3]; - a[0] += a[2]; - a[1] += a[3]; - a[2] = x0r; - a[3] = x0i; -} - - -void rftfsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a) -{ - picoos_int32 i, i0, j, k; - PICOFFTSG_FFTTYPE w1r, w1i, wkr, wki, wdr, wdi, ss, xr, xi, yr, yi; - - wkr = 0; - wki = 0; - - switch (n) { - case 8 : - wdi=(PICOFFTSG_FFTTYPE)(0.353553414345*PICODSP_WGT_SHIFT); wdr=(PICOFFTSG_FFTTYPE)(0.146446630359*PICODSP_WGT_SHIFT); - w1r=(PICOFFTSG_FFTTYPE)(0.707106709480*PICODSP_WGT_SHIFT); w1i=(PICOFFTSG_FFTTYPE)(0.707106828690*PICODSP_WGT_SHIFT); - ss =(PICOFFTSG_FFTTYPE)(1.414213657379*PICODSP_WGT_SHIFT); break; - case 16 : - wdi=(PICOFFTSG_FFTTYPE)(0.191341713071*PICODSP_WGT_SHIFT); wdr=(PICOFFTSG_FFTTYPE)(0.038060232997*PICODSP_WGT_SHIFT); - w1r=(PICOFFTSG_FFTTYPE)(0.923879504204*PICODSP_WGT_SHIFT); w1i=(PICOFFTSG_FFTTYPE)(0.382683426142*PICODSP_WGT_SHIFT); - ss =(PICOFFTSG_FFTTYPE)(0.765366852283*PICODSP_WGT_SHIFT); break; - case 32 : - wdi=(PICOFFTSG_FFTTYPE)(0.097545161843*PICODSP_WGT_SHIFT); wdr=(PICOFFTSG_FFTTYPE)(0.009607359767*PICODSP_WGT_SHIFT); - w1r=(PICOFFTSG_FFTTYPE)(0.980785250664*PICODSP_WGT_SHIFT); w1i=(PICOFFTSG_FFTTYPE)(0.195090323687*PICODSP_WGT_SHIFT); - ss =(PICOFFTSG_FFTTYPE)(0.390180647373*PICODSP_WGT_SHIFT); break; - case 64 : - wdi=(PICOFFTSG_FFTTYPE)(0.049008570611*PICODSP_WGT_SHIFT); wdr=(PICOFFTSG_FFTTYPE)(0.002407636726*PICODSP_WGT_SHIFT); - w1r=(PICOFFTSG_FFTTYPE)(0.995184719563*PICODSP_WGT_SHIFT); w1i=(PICOFFTSG_FFTTYPE)(0.098017141223*PICODSP_WGT_SHIFT); - ss =(PICOFFTSG_FFTTYPE)(0.196034282446*PICODSP_WGT_SHIFT); break; - default : - wdr = 0; wdi = 0; ss = 0; - break; - } - - i = n >> 1; - for (;;) { - i0 = i - RDFT_LOOP_DIV_4; - if (i0 < 4) { - i0 = 4; - } - for (j = i - 4; j >= i0; j -= 4) { - k = n - j; - xr = a[j + 2] - a[k - 2]; - xi = a[j + 3] + a[k - 1]; - yr = Mult_W_W(wdr, xr) - Mult_W_W(wdi, xi); - yi = Mult_W_W(wdr, xi) + Mult_W_W(wdi, xr); - a[j + 2] -= yr; - a[j + 3] -= yi; - a[k - 2] += yr; - a[k - 1] -= yi; - wkr += Mult_W_W(ss, wdi); - wki += picofftsg_mult_w_w(ss, (PICOFFTSG_WGT_SHIFT2 - wdr)); - xr = a[j] - a[k]; - xi = a[j + 1] + a[k + 1]; - yr = Mult_W_W(wkr, xr) - Mult_W_W(wki, xi); - yi = Mult_W_W(wkr, xi) + Mult_W_W(wki, xr); - a[j] -= yr; - a[j + 1] -= yi; - a[k] += yr; - a[k + 1] -= yi; - wdr += Mult_W_W(ss, wki); - wdi += picofftsg_mult_w_w(ss, (PICOFFTSG_WGT_SHIFT2 - wkr)); - } - if (i0 == 4) { - break; - } - } - - xr = a[2] - a[n - 2]; - xi = a[3] + a[n - 1]; - yr = Mult_W_W(wdr, xr) - Mult_W_W(wdi, xi); - yi = Mult_W_W(wdr, xi) + Mult_W_W(wdi, xr); - - a[2] -= yr; - a[3] -= yi; - a[n - 2] += yr; - a[n - 1] -= yi; - - -} - - -void rftbsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a) -{ - picoos_int32 i, i0, j, k; - PICOFFTSG_FFTTYPE w1r, w1i, wkr, wki, wdr, wdi, ss, xr, xi, yr, yi; - wkr = 0; - wki = 0; - wdi=(PICOFFTSG_FFTTYPE)(0.012270614505*PICODSP_WGT_SHIFT); - wdr=(PICOFFTSG_FFTTYPE)(0.000150590655*PICODSP_WGT_SHIFT); - w1r=(PICOFFTSG_FFTTYPE)(0.999698817730*PICODSP_WGT_SHIFT); - w1i=(PICOFFTSG_FFTTYPE)(0.024541229010*PICODSP_WGT_SHIFT); - ss=(PICOFFTSG_FFTTYPE)(0.049082458019*PICODSP_WGT_SHIFT); - - i = n >> 1; - for (;;) { - i0 = i - RDFT_LOOP_DIV4; - if (i0 < 4) { - i0 = 4; - } - for (j = i - 4; j >= i0; j -= 4) { - k = n - j; - xr = a[j + 2] - a[k - 2]; - xi = a[j + 3] + a[k - 1]; - yr = Mult_W_W(wdr, xr) + Mult_W_W(wdi, xi); - yi = Mult_W_W(wdr, xi) - Mult_W_W(wdi, xr); - a[j + 2] -= yr; - a[j + 3] -= yi; - a[k - 2] += yr; - a[k - 1] -= yi; - wkr += Mult_W_W(ss, wdi); - wki += picofftsg_mult_w_w(ss, (PICOFFTSG_WGT_SHIFT2 - wdr)); - xr = a[j] - a[k]; - xi = a[j + 1] + a[k + 1]; - yr = Mult_W_W(wkr, xr) + Mult_W_W(wki, xi); - yi = Mult_W_W(wkr, xi) - Mult_W_W(wki, xr); - a[j] -= yr; - a[j + 1] -= yi; - a[k] += yr; - a[k + 1] -= yi; - wdr += Mult_W_W(ss, wki); - wdi += picofftsg_mult_w_w(ss, (PICOFFTSG_WGT_SHIFT2 - wkr)); - } - if (i0 == 4) { - break; - } - } - xr = a[2] - a[n - 2]; - xi = a[3] + a[n - 1]; - yr = Mult_W_W(wdr, xr) + Mult_W_W(wdi, xi); - yi = Mult_W_W(wdr, xi) - Mult_W_W(wdi, xr); - a[2] -= yr; - a[3] -= yi; - a[n - 2] += yr; - a[n - 1] -= yi; -} - - -void dctsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a) -{ - picoos_int32 i, i0, j, k, m; - PICOFFTSG_FFTTYPE w1r, w1i, wkr, wki, wdr, wdi, ss, xr, xi, yr, yi; - wkr = (PICOFFTSG_FFTTYPE)(0.5*PICODSP_WGT_SHIFT); - wki = (PICOFFTSG_FFTTYPE)(0.5*PICODSP_WGT_SHIFT); - - switch (n) { - case 8 : wdi=(PICOFFTSG_FFTTYPE)(0.587937772274*PICODSP_WGT_SHIFT); - wdr=(PICOFFTSG_FFTTYPE)(0.392847478390*PICODSP_WGT_SHIFT); w1r=(PICOFFTSG_FFTTYPE)(0.980785250664*PICODSP_WGT_SHIFT); - w1i=(PICOFFTSG_FFTTYPE)(0.195090323687*PICODSP_WGT_SHIFT); ss =(PICOFFTSG_FFTTYPE)(0.390180647373*PICODSP_WGT_SHIFT); break; - case 16 : wdi=(PICOFFTSG_FFTTYPE)(0.546600937843*PICODSP_WGT_SHIFT); - wdr=(PICOFFTSG_FFTTYPE)(0.448583781719*PICODSP_WGT_SHIFT); w1r=(PICOFFTSG_FFTTYPE)(0.995184719563*PICODSP_WGT_SHIFT); - w1i=(PICOFFTSG_FFTTYPE)(0.098017141223*PICODSP_WGT_SHIFT); ss =(PICOFFTSG_FFTTYPE)(0.196034282446*PICODSP_WGT_SHIFT); break; - case 32 : wdi=(PICOFFTSG_FFTTYPE)(0.523931562901*PICODSP_WGT_SHIFT); - wdr=(PICOFFTSG_FFTTYPE)(0.474863886833*PICODSP_WGT_SHIFT); w1r=(PICOFFTSG_FFTTYPE)(0.998795449734*PICODSP_WGT_SHIFT); - w1i=(PICOFFTSG_FFTTYPE)(0.049067676067*PICODSP_WGT_SHIFT); ss =(PICOFFTSG_FFTTYPE)(0.098135352135*PICODSP_WGT_SHIFT); break; - case 64 : wdi=(PICOFFTSG_FFTTYPE)(0.512120008469*PICODSP_WGT_SHIFT); - wdr=(PICOFFTSG_FFTTYPE)(0.487578809261*PICODSP_WGT_SHIFT); w1r=(PICOFFTSG_FFTTYPE)(0.999698817730*PICODSP_WGT_SHIFT); - w1i=(PICOFFTSG_FFTTYPE)(0.024541229010*PICODSP_WGT_SHIFT); ss =(PICOFFTSG_FFTTYPE)(0.049082458019*PICODSP_WGT_SHIFT); break; - default: - wdr = 0; wdi = 0; ss = 0; break; - } - - m = n >> 1; - i = 0; - for (;;) { - i0 = i + DCST_LOOP_DIV2; - if (i0 > m - 2) { - i0 = m - 2; - } - for (j = i + 2; j <= i0; j += 2) { - k = n - j; - xr = picofftsg_mult_w_a(wdi, a[j - 1]) - picofftsg_mult_w_a(wdr, a[k + 1]); - xi = picofftsg_mult_w_a(wdr, a[j - 1]) + picofftsg_mult_w_a(wdi, a[k + 1]); - wkr -= Mult_W_W(ss, wdi); - wki += Mult_W_W(ss, wdr); - yr = Mult_W_W(wki, a[j]) - Mult_W_W(wkr, a[k]); - yi = Mult_W_W(wkr, a[j]) + Mult_W_W(wki, a[k]); - wdr -= Mult_W_W(ss, wki); - wdi += Mult_W_W(ss, wkr); - a[k + 1] = xr; - a[k] = yr; - a[j - 1] = xi; - a[j] = yi; - } - if (i0 == m - 2) { - break; - } - } - xr = picofftsg_mult_w_a(wdi, a[m - 1]) - picofftsg_mult_w_a(wdr, a[m + 1]); - a[m - 1] = picofftsg_mult_w_a(wdr, a[m - 1]) + picofftsg_mult_w_a(wdi, a[m + 1]); - a[m + 1] = xr; - a[m] = Mult_W_W(WR5000, a[m]); -} - - -void dctsub4(picoos_int32 n, PICOFFTSG_FFTTYPE *a) -{ - picoos_int32 m; - PICOFFTSG_FFTTYPE wki, wdr, wdi, xr; - - wki = WR5000; - m = n >> 1; - if (m == 2) { - wdr = Mult_W_W(wki, WI2500); - wdi = Mult_W_W(wki, WR2500); - xr = Mult_W_W(wdi, a[1]) - Mult_W_W(wdr, a[3]); - a[1] = Mult_W_W(wdr, a[1]) + Mult_W_W(wdi, a[3]); - a[3] = xr; - } - a[m] = Mult_W_W(wki, a[m]); -} - -#ifdef __cplusplus -} -#endif diff --git a/lib/picofftsg.h b/lib/picofftsg.h deleted file mode 100644 index d9c6a1a..0000000 --- a/lib/picofftsg.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 picofftsg.h - * - * include file for FFT/DCT related data types, constants and functions in Pico - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * -*/ -#ifndef PICOFFTSG_H_ -#define PCOFFTSG_H_ - -#include "picoos.h" -#include "picodsp.h" - - -#ifdef __cplusplus -extern "C" { - -#endif -#if 0 -} -#endif - -#define PICOFFTSG_FFTTYPE picoos_int32 - -extern void rdft(int n, int isgn, PICOFFTSG_FFTTYPE *a); -extern void dfct(int n, float *a, int VAL_SHIFT); -extern void dfct_nmf(int n, int *a); -extern float norm_result(int m2, PICOFFTSG_FFTTYPE *tmpX, PICOFFTSG_FFTTYPE *norm_window); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/picokdbg.c b/lib/picokdbg.c deleted file mode 100644 index c0336ba..0000000 --- a/lib/picokdbg.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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 picokdbg.c - * - * debug support knowledge base - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#include "picoos.h" -#include "picoknow.h" -#include "picodbg.h" -#include "picokdbg.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -#if defined(PICO_DEBUG) - -/** - * @addtogroup picokdbg - - * Pico Debug Support for knowledge base \n - * - - * @b Phones - - * overview of binary file format for dbg kb: - - dbg-kb = phonesyms - - phonesyms = {PHONESYM8}=256 - - PHONESYM6: 8 bytes, symbol name (must be 0 terminated), the - corresponding ID corresponds to the offset in the - phonesyms array -*/ - -/* maximum length of phonesym string including terminating 0 */ -#define KDBG_PHONESYMLEN_MAX 8 - - -typedef struct kdbg_subobj *kdbg_SubObj; - -typedef struct kdbg_subobj { - picoos_uint8 *phonesyms; -} kdbg_subobj_t; - - -static pico_status_t kdbgInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) { - kdbg_subobj_t *kdbg; - - PICODBG_DEBUG(("start")); - - if (NULL == this || NULL == this->subObj) { - PICODBG_DEBUG(("2nd check failed")); - return picoos_emRaiseException(common->em, PICO_ERR_OTHER, NULL, NULL); - } - kdbg = (kdbg_subobj_t *)this->subObj; - kdbg->phonesyms = this->base; - return PICO_OK; -} - - -static pico_status_t kdbgSubObjDeallocate(register picoknow_KnowledgeBase this, - picoos_MemoryManager mm) { - if (NULL != this) { - picoos_deallocate(mm, (void *) &this->subObj); - } - return PICO_OK; -} - - -pico_status_t picokdbg_specializeDbgKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common) { - if (NULL == this) { - PICODBG_INFO(("no debug symbols loaded")); - return PICO_OK; - } - this->subDeallocate = kdbgSubObjDeallocate; - this->subObj = picoos_allocate(common->mm, sizeof(kdbg_subobj_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - return kdbgInitialize(this, common); -} - - -picokdbg_Dbg picokdbg_getDbg(picoknow_KnowledgeBase this) { - if (NULL == this) { - return NULL; - } else { - return (picokdbg_Dbg)this->subObj; - } -} - - -/* Dbg methods */ - -picoos_uint8 picokdbg_getPhoneId(const picokdbg_Dbg this, - const picoos_char *phsym) { - kdbg_subobj_t *kdbg; - picoos_uint16 i; - - if (this == NULL) - return 0; - - kdbg = (kdbg_subobj_t *)this; - /* sequential search */ - for (i = 0; i < 256; i++) { - if (!picoos_strcmp(phsym, - (picoos_char *)&(kdbg->phonesyms[i * KDBG_PHONESYMLEN_MAX]))) - return (picoos_uint8)i; - } - return 0; -} - - -picoos_char *picokdbg_getPhoneSym(const picokdbg_Dbg this, - const picoos_uint8 phid) { - kdbg_subobj_t *kdbg; - - if (this == NULL) - return NULL; - - kdbg = (kdbg_subobj_t *)this; - return (picoos_char *)&(kdbg->phonesyms[phid * KDBG_PHONESYMLEN_MAX]); -} - - - -#else - -/* To prevent warning about "translation unit is empty" when - diagnostic output is disabled. */ -static void picokdbg_dummy(void) { - picokdbg_dummy(); -} - - -#endif /* defined(PICO_DEBUG) */ - -#ifdef __cplusplus -} -#endif - - -/* end */ diff --git a/lib/picokdbg.h b/lib/picokdbg.h deleted file mode 100644 index c17942f..0000000 --- a/lib/picokdbg.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 picokdbg.h - * - * debug support knowledge base - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - *- 0.1, 08.05.2008, MRi - initial version - * - */ - -#ifndef PICOKDBG_H_ -#define PICOKDBG_H_ - - -#include "picoos.h" -#include "picoknow.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* ************************************************************/ -/* Dbg type and functions */ -/* ************************************************************/ - -/** - * to be used by picorsrc only - */ -pico_status_t picokdbg_specializeDbgKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common); - -typedef struct picokdbg_dbg *picokdbg_Dbg; - -/** - * return kb Phones for usage in PU - */ -picokdbg_Dbg picokdbg_getDbg(picoknow_KnowledgeBase this); - - -/* phone ID - phone symbol conversion functions */ - -/** - * return phone ID for phone symbol 'phsym' which must be 0 terminated - */ -picoos_uint8 picokdbg_getPhoneId(const picokdbg_Dbg dbg, - const picoos_char *phsym); - -/** - * return pointer to phone symbol for phone ID phid - */ -picoos_char *picokdbg_getPhoneSym(const picokdbg_Dbg dbg, - const picoos_uint8 phid); - -#ifdef __cplusplus -} -#endif - - -#endif /*PICOKDBG_H_*/ diff --git a/lib/picokdt.c b/lib/picokdt.c deleted file mode 100644 index 54e36ac..0000000 --- a/lib/picokdt.c +++ /dev/null @@ -1,2642 +0,0 @@ -/* - * 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 picokdt.c - * - * knowledge handling for decision trees - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#include "picoos.h" -#include "picodbg.h" -#include "picobase.h" -#include "picoknow.h" -#include "picodata.h" -#include "picokdt.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* ************************************************************/ -/* decision tree */ -/* ************************************************************/ - -/** - * @addtogroup picokdt - * ---------------------------------------------------\n - * Pico KDT support \n - * ---------------------------------------------------\n - overview extended binary tree file: - - dt consists of optional attribute mapping tables and a non-empty - tree part - - using the attribute mapping tables an attribute value as used - throughout the TTS can be mapped to its smaller representation - used in the tree - - multi-byte values always little endian - - ------------------------------------------------------------------- - - bin-file, decision tree knowledge base in binary form - - - dt-kb = header inputmaptables outputmaptables tree - - - - header = INPMAPTABLEPOS2 OUTMAPTABLEPOS2 TREEPOS2 - - - INPMAPTABLEPOS2: two bytes, equals offest in number of bytes from - the start of kb to the start of input map tables, - may not be 0 - - OUTMAPTABLEPOS2: two bytes, equals offest in number of bytes from - the start of kb to the start of outtables, - may not be 0 - - TREEPOS2: two bytes, equals offest in number of bytes from the - start of kb to the start of the tree - - - - inputmaptables = maptables - - outputmaptables = maptables - - maptables = NRMAPTABLES1 {maptable}=NRMAPTABLES1 - - maptable = LENTABLE2 TABLETYPE1 ( bytemaptable - | wordmaptable - | graphinmaptable - | bytetovarmaptable ) - - bytemaptable (in or out, usage varies) = NRBYTES2 {BYTE1}=NRBYTES2 - - wordmaptable (in or out, usage varies) = NRWORDS2 {WORD2}=NRWORDS2 - - graphinmaptable (in only) = NRGRAPHS2 {GRAPH1:4}=NRGRAPHS2 - - bytetovarmaptable (out only) = NRINBYTES2 outvarsearchind - outvaroutputs - - outvarsearchind = {OUTVAROFFSET2}=NRINBYTES2 - - outvaroutputs = {VARVALID1:}=NRINBYTES2 - - - bytemaptable: fixed size, *Map*Fixed \n - - wordmaptable: fixed size, *Map*Fixed \n - - graphinmaptable: search value is variable size (UTF8 grapheme), \n - value to be mapped to is fixed size, one byte \n - - bytetovarmaptable: search value is fixed size, one byte, values \n - to be mapped to are of variable size (e.g. several \n - phones) \n - - - NRMAPTABLES1: one byte representing the number of map tables - - LENTABLE2: two bytes, equals offset to the next table (or next - part of kb, e.g. tree), - if LENTABLE2 = 3, and - TABLETYPE1 = EMPTY -> empty table, no mapping to be done - - TABLETYPE1: one byte, type of map table (byte, word, or graph=utf8) - - NRBYTES2: two bytes, number of bytes following in the table (one - would be okay, to simplify some implementation also set - to 2) - - BYTE1: one btye, the sequence is used to determine the values - being mapped to, starting with 0 - - NRWORDS2: two bytes, number of words (two btyes) following in the table - - WORD2: two bytes, the sequence is used to determine the values - being mapped to, starting with 0 - - NRGRAPHS2: two bytes, number of graphemes encoded in UTF8 following - in table - - GRAPH1:4: one to four bytes, UTF8 representation of a grapheme, the - sequence of graphemes is used to determine the value being - mapped to, starting with 0, the length information is - encoded in UTF8, no need for extra length info - - NRINBYTES2: two bytes, number of single byte IDs the tree can produce - - OUTVAROFFSET2: two bytes, offset from the start of the - outvaroutputs to the start of the following output - phone ID group, ie. the first outvaroffset is the - offset to the start of the second PHONEID - group. Using the previous outvaroffset (or the start - of the outvaroutputs) the start and lenth of the - PHONEID group can be determined and we can get the - sequence of output values we map the chunk value to - - VARVALID1:: one to several bytes, one byte each for an output phone ID - - - tree = treenodeinfos TREEBODYSIZE4 treebody - - treenodeinfos = NRVFIELDS1 vfields NRATTRIBUTES1 NRQFIELDS1 qfields - - vfields = {VFIELD1}=NRVFIELDS1 - - qfields = {QFIELD1}=NRATTRIBUTES1xNRQFIELDS1 - - treebody = "cf. code" - - - TREEBODYSIZE4: four bytes, size of treebody in number of bytes - - NRVFIELDS1: one byte, number of node properties in the following - vector (predefined and fixed sequence of properties) - - VFIELD1: number of bits used to represent a node property - - NRATTRIBUTES1: one byte, number of attributes (rows) in the - following matrix - - NRQFIELDS1: one byte, number (columns) of question-dependent node - properties per attribute in the following matrix - (predefined and fixed sequence of properties) - - QFIELD1: number of bits used to represent a question-dependent - property in the matrix - - - - Currently, - - NRVFIELDS1 is fixed at 2 for all trees, ie. - - vfields = 2 aVFIELD1 bVFIELD1 - - aVFIELD1: nr of bits for questions - - bVFIELD1: nr of bits for decisions - - - NRQFIELDS1 is fixed at 5 for all trees, ie. \n - - qfields = NRATTRIBUTES1 5 aQFIELD1 bQFIELD1 cQFIELD1 dQFIELD1 eQFIELD1 \n - - aQFIELD1: nr of bits for fork count \n - - bQFIELD1: nr of bits for start position for subsets \n - - cQFIELD1: nr of bits for group size \n - - dQFIELD1: nr of bits for offset to reach output \n - - eQFIELD1: nr of bits for threshold (if continuous node) \n -*/ - - -/* ************************************************************/ -/* decision tree data defines */ -/* may not be changed with current implementation */ -/* ************************************************************/ - -/* maptables fields */ -#define PICOKDT_MTSPOS_NRMAPTABLES 0 - -/* position of first byte of first maptable (for omt the only table */ -#define PICOKDT_MTPOS_START 1 - -/* maptable fields */ -#define PICOKDT_MTPOS_LENTABLE 0 -#define PICOKDT_MTPOS_TABLETYPE 2 -#define PICOKDT_MTPOS_NUMBER 3 -#define PICOKDT_MTPOS_MAPSTART 5 - -/* treenodeinfos fields */ -#define PICOKDT_NIPOS_NRVFIELDS 0 -#define PICOKDT_NIPOS_NRATTS 3 -#define PICOKDT_NIPOS_NRQFIELDS 4 - -/* fixed treenodeinfos number of fields */ -#define PICOKDT_NODEINFO_NRVFIELDS 2 -#define PICOKDT_NODEINFO_NRQFIELDS 5 - -/* fixed number of bits used */ -#define PICOKDT_NODETYPE_NRBITS 2 -#define PICOKDT_SUBSETTYPE_NRBITS 2 -#define PICOKDT_ISDECIDE_NRBITS 1 - -/* number of inpmaptables for each tree. Since we have a possibly - empty input map table for each att, currently these values must be - equal to PICOKDT_NRATT* */ -typedef enum { - PICOKDT_NRINPMT_POSP = 12, - PICOKDT_NRINPMT_POSD = 7, - PICOKDT_NRINPMT_G2P = 16, - PICOKDT_NRINPMT_PHR = 8, - PICOKDT_NRINPMT_ACC = 13, - PICOKDT_NRINPMT_PAM = 60 -} kdt_nrinpmaptables_t; - -/* number of outmaptables for each tree, at least one, possibly empty, - output map table for each tree */ -typedef enum { - PICOKDT_NROUTMT_POSP = 1, - PICOKDT_NROUTMT_POSD = 1, - PICOKDT_NROUTMT_G2P = 1, - PICOKDT_NROUTMT_PHR = 1, - PICOKDT_NROUTMT_ACC = 1, - PICOKDT_NROUTMT_PAM = 1 -} kdt_nroutmaptables_t; - -/* maptable types */ -typedef enum { - PICOKDT_MTTYPE_EMPTY = 0, - PICOKDT_MTTYPE_BYTE = 1, - PICOKDT_MTTYPE_WORD = 2, - PICOKDT_MTTYPE_GRAPH = 3, - PICOKDT_MTTYPE_BYTETOVAR = 4 -} kdt_mttype_t; - - -/* ************************************************************/ -/* decision tree types and loading */ -/* ************************************************************/ -/* object : Dt*KnowledgeBase - * shortcut : kdt* - * derived from : picoknow_KnowledgeBase - */ - -/* subobj shared by all decision trees */ -typedef struct { - picokdt_kdttype_t type; - picoos_uint8 *inpmaptable; - picoos_uint8 *outmaptable; - picoos_uint8 *tree; - picoos_uint32 beg_offset[128]; /* for efficiency */ - - /* tree-internal details for faster processing */ - picoos_uint8 *vfields; - picoos_uint8 *qfields; - picoos_uint8 nrattributes; - picoos_uint8 *treebody; - /*picoos_uint8 nrvfields;*/ /* fix PICOKDT_NODEINFO_NRVFIELDS */ - /*picoos_uint8 nrqfields;*/ /* fix PICOKDT_NODEINFO_NRQFIELDS */ - - /* direct output vector (no output mapping) */ - picoos_uint8 dset; /* TRUE if class set, FALSE otherwise */ - picoos_uint16 dclass; -} kdt_subobj_t; - -/* subobj specific for each decision tree type */ -typedef struct { - kdt_subobj_t dt; - picoos_uint16 invec[PICOKDT_NRATT_POSP]; /* input vector */ - picoos_uint8 inveclen; /* nr of ele set in invec; must be =nrattributes */ -} kdtposp_subobj_t; - -typedef struct { - kdt_subobj_t dt; - picoos_uint16 invec[PICOKDT_NRATT_POSD]; /* input vector */ - picoos_uint8 inveclen; /* nr of ele set in invec; must be =nrattributes */ -} kdtposd_subobj_t; - -typedef struct { - kdt_subobj_t dt; - picoos_uint16 invec[PICOKDT_NRATT_G2P]; /* input vector */ - picoos_uint8 inveclen; /* nr of ele set in invec; must be =nrattributes */ -} kdtg2p_subobj_t; - -typedef struct { - kdt_subobj_t dt; - picoos_uint16 invec[PICOKDT_NRATT_PHR]; /* input vector */ - picoos_uint8 inveclen; /* nr of ele set in invec; must be =nrattributes */ -} kdtphr_subobj_t; - -typedef struct { - kdt_subobj_t dt; - picoos_uint16 invec[PICOKDT_NRATT_ACC]; /* input vector */ - picoos_uint8 inveclen; /* nr of ele set in invec; must be =nrattributes */ -} kdtacc_subobj_t; - -typedef struct { - kdt_subobj_t dt; - picoos_uint16 invec[PICOKDT_NRATT_PAM]; /* input vector */ - picoos_uint8 inveclen; /* nr of ele set in invec; must be =nrattributes */ -} kdtpam_subobj_t; - - -static pico_status_t kdtDtInitialize(register picoknow_KnowledgeBase this, - picoos_Common common, - kdt_subobj_t *dtp) { - picoos_uint16 inppos; - picoos_uint16 outpos; - picoos_uint16 treepos; - picoos_uint32 curpos = 0, pos; - picoos_uint16 lentable; - picoos_uint16 i; - picoos_uint8 imtnr; - - PICODBG_DEBUG(("start")); - - /* get inmap, outmap, tree offsets */ - if ((PICO_OK == picoos_read_mem_pi_uint16(this->base, &curpos, &inppos)) - && (PICO_OK == picoos_read_mem_pi_uint16(this->base, &curpos, &outpos)) - && (PICO_OK == picoos_read_mem_pi_uint16(this->base, &curpos, - &treepos))) { - - /* all pos are mandatory, verify */ - if (inppos && outpos && treepos) { - dtp->inpmaptable = this->base + inppos; - dtp->outmaptable = this->base + outpos; - dtp->tree = this->base + treepos; - /* precalc beg offset table */ - imtnr=dtp->inpmaptable[0]; - pos=1; - dtp->beg_offset[0] = 1; - for (i = 0; i < imtnr; i++) { - lentable = ((picoos_uint16)(dtp->inpmaptable[pos+1])) << 8 | - dtp->inpmaptable[pos]; - pos += lentable; - dtp->beg_offset[i+1] = pos; - } - } else { - dtp->inpmaptable = NULL; - dtp->outmaptable = NULL; - dtp->tree = NULL; - PICODBG_ERROR(("invalid kb position info")); - return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, - NULL, NULL); - } - - /* nr of outmaptables is equal 1 for all trees, verify */ - if (dtp->outmaptable[PICOKDT_MTSPOS_NRMAPTABLES] != 1) { - PICODBG_ERROR(("wrong number of outmaptables")); - return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, - NULL, NULL); - } - - /* check if this is an empty table, ie. len == 3 */ - if ((dtp->outmaptable[PICOKDT_MTPOS_START + PICOKDT_MTPOS_LENTABLE] - == 3) - && (dtp->outmaptable[PICOKDT_MTPOS_START + PICOKDT_MTPOS_LENTABLE - + 1] == 0)) { - /* verify that this is supposed to be an empty table and - set outmaptable to NULL if so */ - if (dtp->outmaptable[PICOKDT_MTPOS_START + PICOKDT_MTPOS_TABLETYPE] - == PICOKDT_MTTYPE_EMPTY) { - dtp->outmaptable = NULL; - } else { - PICODBG_ERROR(("table length vs. type problem")); - return picoos_emRaiseException(common->em, - PICO_EXC_FILE_CORRUPT, - NULL, NULL); - } - } - - dtp->vfields = dtp->tree + 1; - dtp->qfields = dtp->tree + PICOKDT_NODEINFO_NRVFIELDS + 3; - dtp->nrattributes = dtp->tree[PICOKDT_NIPOS_NRATTS]; - dtp->treebody = dtp->qfields + 4 + - (dtp->nrattributes * PICOKDT_NODEINFO_NRQFIELDS); /* TREEBODYSIZE4*/ - - /*dtp->nrvfields = dtp->tree[PICOKDT_NIPOS_NRVFIELDS]; <- is fix */ - /*dtp->nrqfields = dtp->tree[PICOKDT_NIPOS_NRQFIELDS]; <- is fix */ - /* verify that nrvfields ad nrqfields are correct */ - if ((PICOKDT_NODEINFO_NRVFIELDS != dtp->tree[PICOKDT_NIPOS_NRVFIELDS]) || - (PICOKDT_NODEINFO_NRQFIELDS != dtp->tree[PICOKDT_NIPOS_NRQFIELDS])) { - PICODBG_ERROR(("problem with nr of vfields (%d) or qfields (%d)", - dtp->tree[PICOKDT_NIPOS_NRVFIELDS], - dtp->tree[PICOKDT_NIPOS_NRQFIELDS])); - return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, - NULL, NULL); - } - dtp->dset = 0; - dtp->dclass = 0; - PICODBG_DEBUG(("tree init: nratt: %d, posomt: %d, postree: %d", - dtp->nrattributes, (dtp->outmaptable - dtp->inpmaptable), - (dtp->tree - dtp->inpmaptable))); - return PICO_OK; - } else { - PICODBG_ERROR(("problem reading kb in memory")); - return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, - NULL, NULL); - } -} - - -static pico_status_t kdtDtCheck(register picoknow_KnowledgeBase this, - picoos_Common common, - kdt_subobj_t *dtp, - kdt_nratt_t nratt, - kdt_nrinpmaptables_t nrinpmt, - kdt_nroutmaptables_t nroutmt, - kdt_mttype_t mttype) { - /* check nr attributes */ - /* check nr inpmaptables */ - /* check nr outmaptables */ - /* check outmaptable is word type */ - if ((nratt != dtp->nrattributes) - || (dtp->inpmaptable == NULL) - || (dtp->outmaptable == NULL) - || (dtp->inpmaptable[PICOKDT_MTSPOS_NRMAPTABLES] != nrinpmt) - || (dtp->outmaptable[PICOKDT_MTSPOS_NRMAPTABLES] != nroutmt) - || (dtp->outmaptable[PICOKDT_MTPOS_START+PICOKDT_MTPOS_TABLETYPE] - != mttype)) { - PICODBG_ERROR(("check failed, nratt %d, nrimt %d, nromt %d, omttype %d", - dtp->nrattributes, - dtp->inpmaptable[PICOKDT_MTSPOS_NRMAPTABLES], - dtp->outmaptable[PICOKDT_MTSPOS_NRMAPTABLES], - dtp->outmaptable[PICOKDT_MTPOS_START + - PICOKDT_MTPOS_TABLETYPE])); - return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, - NULL, NULL); - } - return PICO_OK; -} - - - -static pico_status_t kdtPosPInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) { - pico_status_t status; - kdtposp_subobj_t *dtposp; - kdt_subobj_t *dt; - picoos_uint8 i; - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - dtposp = (kdtposp_subobj_t *)this->subObj; - dt = &(dtposp->dt); - dt->type = PICOKDT_KDTTYPE_POSP; - if ((status = kdtDtInitialize(this, common, dt)) != PICO_OK) { - return status; - } - if ((status = kdtDtCheck(this, common, dt, PICOKDT_NRATT_POSP, - PICOKDT_NRINPMT_POSP, PICOKDT_NROUTMT_POSP, - PICOKDT_MTTYPE_WORD)) != PICO_OK) { - return status; - } - - /* init specialized subobj part */ - for (i = 0; i < PICOKDT_NRATT_POSP; i++) { - dtposp->invec[i] = 0; - } - dtposp->inveclen = 0; - PICODBG_DEBUG(("posp tree initialized")); - return PICO_OK; -} - - -static pico_status_t kdtPosDInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) { - pico_status_t status; - kdtposd_subobj_t *dtposd; - kdt_subobj_t *dt; - picoos_uint8 i; - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - dtposd = (kdtposd_subobj_t *)this->subObj; - dt = &(dtposd->dt); - dt->type = PICOKDT_KDTTYPE_POSD; - if ((status = kdtDtInitialize(this, common, dt)) != PICO_OK) { - return status; - } - if ((status = kdtDtCheck(this, common, dt, PICOKDT_NRATT_POSD, - PICOKDT_NRINPMT_POSD, PICOKDT_NROUTMT_POSD, - PICOKDT_MTTYPE_WORD)) != PICO_OK) { - return status; - } - - /* init spezialized subobj part */ - for (i = 0; i < PICOKDT_NRATT_POSD; i++) { - dtposd->invec[i] = 0; - } - dtposd->inveclen = 0; - PICODBG_DEBUG(("posd tree initialized")); - return PICO_OK; -} - - -static pico_status_t kdtG2PInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) { - pico_status_t status; - kdtg2p_subobj_t *dtg2p; - kdt_subobj_t *dt; - picoos_uint8 i; - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - dtg2p = (kdtg2p_subobj_t *)this->subObj; - dt = &(dtg2p->dt); - dt->type = PICOKDT_KDTTYPE_G2P; - if ((status = kdtDtInitialize(this, common, dt)) != PICO_OK) { - return status; - } - - if ((status = kdtDtCheck(this, common, dt, PICOKDT_NRATT_G2P, - PICOKDT_NRINPMT_G2P, PICOKDT_NROUTMT_G2P, - PICOKDT_MTTYPE_BYTETOVAR)) != PICO_OK) { - return status; - } - - /* init spezialized subobj part */ - for (i = 0; i < PICOKDT_NRATT_G2P; i++) { - dtg2p->invec[i] = 0; - } - dtg2p->inveclen = 0; - PICODBG_DEBUG(("g2p tree initialized")); - return PICO_OK; -} - - -static pico_status_t kdtPhrInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) { - pico_status_t status; - kdtphr_subobj_t *dtphr; - kdt_subobj_t *dt; - picoos_uint8 i; - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - dtphr = (kdtphr_subobj_t *)this->subObj; - dt = &(dtphr->dt); - dt->type = PICOKDT_KDTTYPE_PHR; - if ((status = kdtDtInitialize(this, common,dt)) != PICO_OK) { - return status; - } - - if ((status = kdtDtCheck(this, common, dt, PICOKDT_NRATT_PHR, - PICOKDT_NRINPMT_PHR, PICOKDT_NROUTMT_PHR, - PICOKDT_MTTYPE_WORD)) != PICO_OK) { - return status; - } - - /* init spezialized subobj part */ - for (i = 0; i < PICOKDT_NRATT_PHR; i++) { - dtphr->invec[i] = 0; - } - dtphr->inveclen = 0; - PICODBG_DEBUG(("phr tree initialized")); - return PICO_OK; -} - - -static pico_status_t kdtAccInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) { - pico_status_t status; - kdtacc_subobj_t *dtacc; - kdt_subobj_t *dt; - picoos_uint8 i; - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - dtacc = (kdtacc_subobj_t *)this->subObj; - dt = &(dtacc->dt); - dt->type = PICOKDT_KDTTYPE_ACC; - if ((status = kdtDtInitialize(this, common, dt)) != PICO_OK) { - return status; - } - - if ((status = kdtDtCheck(this, common, dt, PICOKDT_NRATT_ACC, - PICOKDT_NRINPMT_ACC, PICOKDT_NROUTMT_ACC, - PICOKDT_MTTYPE_WORD)) != PICO_OK) { - return status; - } - - /* init spezialized subobj part */ - for (i = 0; i < PICOKDT_NRATT_ACC; i++) { - dtacc->invec[i] = 0; - } - dtacc->inveclen = 0; - PICODBG_DEBUG(("acc tree initialized")); - return PICO_OK; -} - - -static pico_status_t kdtPamInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) { - pico_status_t status; - kdtpam_subobj_t *dtpam; - kdt_subobj_t *dt; - picoos_uint8 i; - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - dtpam = (kdtpam_subobj_t *)this->subObj; - dt = &(dtpam->dt); - dt->type = PICOKDT_KDTTYPE_PAM; - if ((status = kdtDtInitialize(this, common, dt)) != PICO_OK) { - return status; - } - - if ((status = kdtDtCheck(this, common, dt, PICOKDT_NRATT_PAM, - PICOKDT_NRINPMT_PAM, PICOKDT_NROUTMT_PAM, - PICOKDT_MTTYPE_WORD)) != PICO_OK) { - return status; - } - - /* init spezialized subobj part */ - for (i = 0; i < PICOKDT_NRATT_PAM; i++) { - dtpam->invec[i] = 0; - } - dtpam->inveclen = 0; - PICODBG_DEBUG(("pam tree initialized")); - return PICO_OK; -} - - -static pico_status_t kdtSubObjDeallocate(register picoknow_KnowledgeBase this, - picoos_MemoryManager mm) { - if (NULL != this) { - picoos_deallocate(mm, (void *) &this->subObj); - } - return PICO_OK; -} - - -/* we don't offer a specialized constructor for a *KnowledgeBase but - * instead a "specializer" of an allready existing generic - * picoknow_KnowledgeBase */ - -pico_status_t picokdt_specializeDtKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common, - const picokdt_kdttype_t kdttype) { - pico_status_t status; - - if (NULL == this) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - this->subDeallocate = kdtSubObjDeallocate; - switch (kdttype) { - case PICOKDT_KDTTYPE_POSP: - this->subObj = picoos_allocate(common->mm,sizeof(kdtposp_subobj_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - status = kdtPosPInitialize(this, common); - break; - case PICOKDT_KDTTYPE_POSD: - this->subObj = picoos_allocate(common->mm,sizeof(kdtposd_subobj_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - status = kdtPosDInitialize(this, common); - break; - case PICOKDT_KDTTYPE_G2P: - this->subObj = picoos_allocate(common->mm,sizeof(kdtg2p_subobj_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - status = kdtG2PInitialize(this, common); - break; - case PICOKDT_KDTTYPE_PHR: - this->subObj = picoos_allocate(common->mm,sizeof(kdtphr_subobj_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - status = kdtPhrInitialize(this, common); - break; - case PICOKDT_KDTTYPE_ACC: - this->subObj = picoos_allocate(common->mm,sizeof(kdtacc_subobj_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - status = kdtAccInitialize(this, common); - break; - case PICOKDT_KDTTYPE_PAM: - this->subObj = picoos_allocate(common->mm,sizeof(kdtpam_subobj_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - status = kdtPamInitialize(this, common); - break; - default: - return picoos_emRaiseException(common->em, PICO_ERR_OTHER, - NULL, NULL); - } - - if (status != PICO_OK) { - picoos_deallocate(common->mm, (void *) &this->subObj); - return picoos_emRaiseException(common->em, status, NULL, NULL); - } - return PICO_OK; -} - - -/* ************************************************************/ -/* decision tree getDt* */ -/* ************************************************************/ - -picokdt_DtPosP picokdt_getDtPosP(picoknow_KnowledgeBase this) { - return ((NULL == this) ? NULL : ((picokdt_DtPosP) this->subObj)); -} - -picokdt_DtPosD picokdt_getDtPosD(picoknow_KnowledgeBase this) { - return ((NULL == this) ? NULL : ((picokdt_DtPosD) this->subObj)); -} - -picokdt_DtG2P picokdt_getDtG2P (picoknow_KnowledgeBase this) { - return ((NULL == this) ? NULL : ((picokdt_DtG2P) this->subObj)); -} - -picokdt_DtPHR picokdt_getDtPHR (picoknow_KnowledgeBase this) { - return ((NULL == this) ? NULL : ((picokdt_DtPHR) this->subObj)); -} - -picokdt_DtACC picokdt_getDtACC (picoknow_KnowledgeBase this) { - return ((NULL == this) ? NULL : ((picokdt_DtACC) this->subObj)); -} - -picokdt_DtPAM picokdt_getDtPAM (picoknow_KnowledgeBase this) { - return ((NULL == this) ? NULL : ((picokdt_DtPAM) this->subObj)); -} - - - -/* ************************************************************/ -/* decision tree support functions, tree */ -/* ************************************************************/ - - -typedef enum { - eQuestion = 0, /* index to #bits to identify question */ - eDecide = 1 /* index to #bits to identify decision */ -} kdt_vfields_ind_t; - -typedef enum { - eForkCount = 0, /* index to #bits for number of forks */ - eBitNo = 1, /* index to #bits for index of 1st element */ - eBitCount = 2, /* index to #bits for size of the group */ - eJump = 3, /* index to #bits for offset to reach output node */ - eCut = 4 /* for contin. node: #bits for threshold checked */ -} kdt_qfields_ind_t; - -typedef enum { - eNTerminal = 0, - eNBinary = 1, - eNContinuous = 2, - eNDiscrete = 3 -} kdt_nodetypes_t; - -typedef enum { - eOneValue = 0, - eTwoValues = 1, - eWithoutBitMask = 2, - eBitMask = 3 -} kdt_subsettypes_t; - - -/* Name : kdt_jump - Function: maps the iJump offset to byte + bit coordinates - Input : iJump absolute bit offset (0..(nr-bytes-treebody)*8) - Output : iByteNo the first byte containing the bits to extract - (0..(nr-bytes-treebody)) - iBitNo the first bit to be extracted (0..7) - Returns : void - Notes : updates the iByteNo + iBitNo fields -*/ -static void kdt_jump(const picoos_uint32 iJump, - picoos_uint32 *iByteNo, - picoos_int8 *iBitNo) { - picoos_uint32 iByteSize; - - iByteSize = (iJump / 8 ); - *iBitNo = (iJump - (iByteSize * 8)) + (7 - *iBitNo); - *iByteNo += iByteSize; - if (*iBitNo >= 8) { - (*iByteNo)++; - *iBitNo = 15 - *iBitNo; - } else { - *iBitNo = 7 - *iBitNo; - } -} - - -/* replaced inline for speedup */ -/* Name : kdtIsVal - Function: Returns the binary value of the bit pointed to by iByteNo, iBitNo - Input : iByteNo ofsset to the byte containing the bits to extract - (0..sizeof(treebody)) - iBitNo ofsset to the first bit to be extracted (0..7) - Returns : 0/1 depending on the bit pointed to -*/ -/* -static picoos_uint8 kdtIsVal(register kdt_subobj_t *this, - picoos_uint32 iByteNo, - picoos_int8 iBitNo) { - return ((this->treebody[iByteNo] & ((1)< 0); -} -*/ - - -/* @todo : consider replacing inline for speedup */ - -/* Name : kdtGetQFieldsVal (was: m_QuestDependentFields) - Function: gets a byte from qfields - Input : this handle to a dt subobj - attind index of the attribute - qind index of the byte to be read - Returns : the requested byte - Notes : check that attind < this->nrattributes needed before calling - this function! -*/ -static picoos_uint8 kdtGetQFieldsVal(register kdt_subobj_t *this, - const picoos_uint8 attind, - const kdt_qfields_ind_t qind) { - /* check of qind done in initialize and (for some compilers) with typing */ - /* check of attind needed before calling this function */ - return this->qfields[(attind * PICOKDT_NODEINFO_NRQFIELDS) + qind]; -} - - -/* Name : kdtGetShiftVal (was: get_shift_value) - Function: returns the (treebody) value pointed to by iByteNo, iBitNo, - and with size iSize - Input : this reference to the processing unit struct - iSize number of bits to be extracted (0..N) - iByteNo ofsset to the byte containing the bits to extract - (0..sizeof(treebody)) - iBitNo ofsset to the first bit to be extracted (0..7) - Returns : the value requested (if size==0 --> 0 is returned) -*/ -/* -static picoos_uint32 orig_kdtGetShiftVal(register kdt_subobj_t *this, - const picoos_int16 iSize, - picoos_uint32 *iByteNo, - picoos_int8 *iBitNo) { - picoos_uint32 iVal; - picoos_int16 i; - - iVal = 0; - for (i = iSize-1; i >= 0; i--) { - if ( (this->treebody[*iByteNo] & ((1)<<(*iBitNo))) > 0) { - iVal |= ( (1) << i ); - } - (*iBitNo)--; - if (*iBitNo < 0) { - *iBitNo = 7; - (*iByteNo)++; - } - } - return iVal; -} -*/ -/* refactor */ -static picoos_uint32 kdtGetShiftVal(register kdt_subobj_t *this, - const picoos_int16 iSize, picoos_uint32 *iByteNo, picoos_int8 *iBitNo) -{ - picoos_uint32 v, b, iVal; - picoos_int16 i, j, len; - picoos_uint8 val; - - if (iSize < 4) { - iVal = 0; - for (i = iSize - 1; i >= 0; i--) { - /* no check that *iByteNo is within valid treebody range */ - if ((this->treebody[*iByteNo] & ((1) << (*iBitNo))) > 0) { - iVal |= ((1) << i); - } - (*iBitNo)--; - if (*iBitNo < 0) { - *iBitNo = 7; - (*iByteNo)++; - } - } - return iVal; - } - - b = *iByteNo; - j = *iBitNo; - len = iSize; - *iBitNo = j - iSize; - v = 0; - while (*iBitNo < 0) { - *iBitNo += 8; - (*iByteNo)++; - } - - val = this->treebody[b++]; - if (j < 7) { - switch (j) { - case 0: - val &= 0x01; - break; - case 1: - val &= 0x03; - break; - case 2: - val &= 0x07; - break; - case 3: - val &= 0x0f; - break; - case 4: - val &= 0x1f; - break; - case 5: - val &= 0x3f; - break; - case 6: - val &= 0x7f; - break; - } - } - len -= j + 1; - if (len < 0) { - val >>= -len; - } - v = val; - while (len > 0) { - if (len >= 8) { - j = 8; - } else { - j = len; - } - v <<= j; - val = this->treebody[b++]; - if (j < 8) { - switch (j) { - case 1: - val &= 0x80; - val >>= 7; - break; - case 2: - val &= 0xc0; - val >>= 6; - break; - case 3: - val &= 0xe0; - val >>= 5; - break; - case 4: - val &= 0xf0; - val >>= 4; - break; - case 5: - val &= 0xf8; - val >>= 3; - break; - case 6: - val &= 0xfc; - val >>= 2; - break; - case 7: - val &= 0xfe; - val >>= 1; - break; - } - } - v |= val; - len -= j; - } - return v; -} - - -/* Name : kdtAskTree - Function: Tree Traversal routine - Input : iByteNo ofsset to the first byte containing the bits - to extract (0..sizeof(treebody)) - iBitNo ofsset to the first bit to be extracted (0..7) - Returns : >0 continue, no solution yet found - =0 solution found - <0 error, no solution found - Notes : -*/ -static picoos_int8 kdtAskTree(register kdt_subobj_t *this, - picoos_uint16 *invec, - const kdt_nratt_t invecmax, - picoos_uint32 *iByteNo, - picoos_int8 *iBitNo) { - picoos_uint32 iNodeType; - picoos_uint8 iQuestion; - picoos_int32 iVal; - picoos_int32 iForks; - picoos_int32 iID; - - picoos_int32 iCut, iSubsetType, iBitPos, iBitCount, iPos, iJump, iDecision; - picoos_int32 i; - picoos_char iIsDecide; - - PICODBG_TRACE(("start")); - - /* get node type, value should be in kdt_nodetype_t range */ - iNodeType = kdtGetShiftVal(this, PICOKDT_NODETYPE_NRBITS, iByteNo, iBitNo); - PICODBG_TRACE(("iNodeType: %d", iNodeType)); - - /* get attribute to be used in question, check if in range, and get val */ - /* check of vfields argument done in initialize */ - iQuestion = kdtGetShiftVal(this, this->vfields[eQuestion], iByteNo, iBitNo); - if ((iQuestion < this->nrattributes) && (iQuestion < invecmax)) { - iVal = invec[iQuestion]; - } else { - this->dset = FALSE; - PICODBG_TRACE(("invalid question")); - return -1; /* iQuestion invalid */ - } - iForks = 0; - iID = -1; - PICODBG_TRACE(("iQuestion: %d", iQuestion)); - - switch (iNodeType) { - case eNBinary: { - iForks = 2; - iID = iVal; - break; - } - case eNContinuous: { - iForks = 2; - iID = 1; - iCut = kdtGetShiftVal(this, kdtGetQFieldsVal(this, iQuestion, eCut), - iByteNo, iBitNo); /*read the threshold*/ - if (iVal <= iCut) { - iID = 0; - } - break; - } - case eNDiscrete: { - iForks = - kdtGetShiftVal(this, - kdtGetQFieldsVal(this, iQuestion, eForkCount), - iByteNo, iBitNo); - - for (i = 0; i < iForks-1; i++) { - iSubsetType = - kdtGetShiftVal(this, PICOKDT_SUBSETTYPE_NRBITS, - iByteNo, iBitNo); - - switch (iSubsetType) { - case eOneValue: { - if (iID > -1) { - kdt_jump(kdtGetQFieldsVal(this, iQuestion, eBitNo), - iByteNo, iBitNo); - break; - } - iBitPos = - kdtGetShiftVal(this, - kdtGetQFieldsVal(this, iQuestion, - eBitNo), - iByteNo, iBitNo); - if (iVal == iBitPos) { - iID = i; - } - break; - } - case eTwoValues: { - if (iID > -1) { - kdt_jump((kdtGetQFieldsVal(this, iQuestion, eBitNo) + - kdtGetQFieldsVal(this, iQuestion, eBitCount)), - iByteNo, iBitNo); - break; - } - - iBitPos = - kdtGetShiftVal(this, kdtGetQFieldsVal(this, iQuestion, - eBitNo), - iByteNo, iBitNo); - iBitCount = - kdtGetShiftVal(this, kdtGetQFieldsVal(this, iQuestion, - eBitCount), - iByteNo, iBitNo); - if ((iVal == iBitPos) || (iVal == iBitCount)) { - iID = i; - } - break; - } - case eWithoutBitMask: { - if (iID > -1) { - kdt_jump((kdtGetQFieldsVal(this, iQuestion, eBitNo) + - kdtGetQFieldsVal(this, iQuestion, eBitCount)), - iByteNo, iBitNo); - break; - } - - iBitPos = - kdtGetShiftVal(this, kdtGetQFieldsVal(this, iQuestion, - eBitNo), - iByteNo, iBitNo); - iBitCount = - kdtGetShiftVal(this, kdtGetQFieldsVal(this, iQuestion, - eBitCount), - iByteNo, iBitNo); - if ((iVal >= iBitPos) && (iVal < (iBitPos + iBitCount))) { - iID = i; - } - break; - } - case eBitMask: { - iBitPos = 0; - if (iID > -1) { - kdt_jump(kdtGetQFieldsVal(this, iQuestion, eBitNo), - iByteNo, iBitNo); - } else { - iBitPos = - kdtGetShiftVal(this, - kdtGetQFieldsVal(this, iQuestion, - eBitNo), - iByteNo, iBitNo); - } - - iBitCount = - kdtGetShiftVal(this, - kdtGetQFieldsVal(this, iQuestion, - eBitCount), - iByteNo, iBitNo); - if (iID > -1) { - kdt_jump(iBitCount, iByteNo, iBitNo); - break; - } - - if ((iVal >= iBitPos) && (iVal < (iBitPos + iBitCount))) { - iPos = iVal - iBitPos; - kdt_jump((iVal - iBitPos), iByteNo, iBitNo); - /* if (kdtIsVal(this, *iByteNo, *iBitNo))*/ - if ((this->treebody[*iByteNo] & ((1)<<(*iBitNo))) > 0) { - iID = i; - } - kdt_jump((iBitCount - (iVal-iBitPos)), iByteNo, iBitNo); - } else { - kdt_jump(iBitCount, iByteNo, iBitNo); - } - break; - }/*end case eBitMask*/ - }/*end switch (iSubsetType)*/ - }/*end for ( i = 0; i < iForks-1; i++ ) */ - - /*default tree branch*/ - if (-1 == iID) { - iID = iForks-1; - } - break; - }/*end case eNDiscrete*/ - }/*end switch (iNodeType)*/ - - for (i = 0; i < iForks; i++) { - iIsDecide = kdtGetShiftVal(this, PICOKDT_ISDECIDE_NRBITS, iByteNo, iBitNo); - - PICODBG_TRACE(("doing forks: %d", i)); - - if (!iIsDecide) { - if (iID == i) { - iJump = - kdtGetShiftVal(this, kdtGetQFieldsVal(this, iQuestion, eJump), - iByteNo, iBitNo); - kdt_jump(iJump, iByteNo, iBitNo); - this->dset = FALSE; - return 1; /* to be continued, no solution yet found */ - } else { - kdt_jump(kdtGetQFieldsVal(this, iQuestion, eJump), - iByteNo, iBitNo); - } - } else { - if (iID == i) { - /* check of vfields argument done in initialize */ - iDecision = kdtGetShiftVal(this, this->vfields[eDecide], - iByteNo, iBitNo); - this->dclass = iDecision; - this->dset = TRUE; - return 0; /* solution found */ - } else { - /* check of vfields argument done in initialize */ - kdt_jump(this->vfields[eDecide], iByteNo, iBitNo); - } - }/*end if (!iIsDecide)*/ - }/*end for (i = 0; i < iForks; i++ )*/ - - this->dset = FALSE; - PICODBG_TRACE(("problem determining class")); - return -1; /* solution not found, problem determining a class */ -} - - - -/* ************************************************************/ -/* decision tree support functions, mappings */ -/* ************************************************************/ - - -/* size==1 -> MapInByte, size==2 -> MapInWord, - size determined from table type contained in kb. - if the inmaptable is empty, outval = inval */ - -static picoos_uint8 kdtMapInFixed(const kdt_subobj_t *dt, - const picoos_uint8 imtnr, - const picoos_uint16 inval, - picoos_uint16 *outval, - picoos_uint16 *outfallbackval) { - picoos_uint8 size; - picoos_uint32 pos; - picoos_uint16 lentable; - picoos_uint16 posbound; - picoos_uint16 i; - - *outval = 0; - *outfallbackval = 0; - - size = 0; - pos = 0; - - /* check what can be checked */ - if (imtnr >= dt->inpmaptable[pos++]) { /* outside tablenr range? */ - PICODBG_ERROR(("check failed: nrtab: %d, imtnr: %d", - dt->inpmaptable[pos-1], imtnr)); - return FALSE; - } - - /* go forward to the needed tablenr */ - if (imtnr > 0) { - pos = dt->beg_offset[imtnr]; - } - - /* get length */ - lentable = ((picoos_uint16)(dt->inpmaptable[pos+1])) << 8 | - dt->inpmaptable[pos]; - posbound = pos + lentable; - pos += 2; - - /* check type of table and set size */ - if (dt->inpmaptable[pos] == PICOKDT_MTTYPE_EMPTY) { - /* empty table no mapping needed */ - PICODBG_TRACE(("empty table: %d", imtnr)); - *outval = inval; - return TRUE; - } else if (dt->inpmaptable[pos] == PICOKDT_MTTYPE_BYTE) { - size = 1; - } else if (dt->inpmaptable[pos] == PICOKDT_MTTYPE_WORD) { - size = 2; - } else { - /* wrong table type */ - PICODBG_ERROR(("wrong table type %d", dt->inpmaptable[pos])); - return FALSE; - } - pos++; - - /* set fallback value in case of failed mapping, and set upper bound pos */ - *outfallbackval = ((picoos_uint16)(dt->inpmaptable[pos+1])) << 8 | - dt->inpmaptable[pos]; - pos += 2; - - /* size must be 1 or 2 here, keep 'redundant' so save time */ - if (size == 1) { - for (i = 0; (i < *outfallbackval) && (pos < posbound); i++) { - if (inval == dt->inpmaptable[pos]) { - *outval = i; - PICODBG_TRACE(("s1 %d in %d -> out %d", imtnr, inval, *outval)); - return TRUE; - } - pos++; - } - } else if (size == 2) { - posbound--; - for (i = 0; (i < *outfallbackval) && (pos < posbound); i++) { - if (inval == (((picoos_uint16)(dt->inpmaptable[pos+1])) << 8 | - dt->inpmaptable[pos])) { - *outval = i; - PICODBG_TRACE(("s2 %d in %d -> out %d", imtnr, inval, *outval)); - return TRUE; - } - pos += 2; - } - } else { - /* impossible size */ - PICODBG_ERROR(("wrong size %d", size)); - return FALSE; - } - - PICODBG_DEBUG(("no mapping found, fallback: %d", *outfallbackval)); - return FALSE; -} - - -static picoos_uint8 kdtMapInGraph(const kdt_subobj_t *dt, - const picoos_uint8 imtnr, - const picoos_uint8 *inval, - const picoos_uint8 invalmaxlen, - picoos_uint16 *outval, - picoos_uint16 *outfallbackval) { - picoos_uint8 ilen; - picoos_uint8 tlen; - picoos_uint8 cont; - picoos_uint32 pos; - picoos_uint16 lentable; - picoos_uint16 posbound; - picoos_uint16 i; - picoos_uint8 j; - - *outfallbackval = 0; - - pos = 0; - /* check what can be checked */ - if ((imtnr >= dt->inpmaptable[pos++]) || /* outside tablenr range? */ - (invalmaxlen == 0) || /* too short? */ - ((ilen = picobase_det_utf8_length(inval[0])) == 0) || /* invalid? */ - (ilen > invalmaxlen)) { /* not accessible? */ - PICODBG_ERROR(("check failed: nrtab: %d, imtnr: %d, invalmaxlen: %d, " - "ilen: %d", - dt->inpmaptable[pos-1], imtnr, invalmaxlen, ilen)); - return FALSE; - } - - /* go forward to the needed tablenr */ - for (i = 0; i < imtnr; i++) { - lentable = ((picoos_uint16)(dt->inpmaptable[pos+1])) << 8 | - dt->inpmaptable[pos]; - pos += lentable; - } - - /* get length and check type of inpmaptable */ - lentable = ((picoos_uint16)(dt->inpmaptable[pos+1])) << 8 | - dt->inpmaptable[pos]; - posbound = pos + lentable; - pos += 2; - -#if defined(PICO_DEBUG) - if (1) { - int id; - PICODBG_TRACE(("imtnr %d", imtnr)); - for (id = pos-2; id < posbound; id++) { - PICODBG_TRACE(("imtbyte pos %d, %c %d", id - (pos-2), - dt->inpmaptable[id], dt->inpmaptable[id])); - } - } -#endif - - /* check type of table */ - if (dt->inpmaptable[pos] != PICOKDT_MTTYPE_GRAPH) { - /* empty table does not make sense for graph */ - /* wrong table type */ - PICODBG_ERROR(("wrong table type")); - return FALSE; - } - pos++; - - /* set fallback value in case of failed mapping, and set upper bound pos */ - *outfallbackval = ((picoos_uint16)(dt->inpmaptable[pos+1])) << 8 | - dt->inpmaptable[pos]; - pos += 2; - - /* sequential search */ - for (i = 0; (i < *outfallbackval) && (pos < posbound); i++) { - tlen = picobase_det_utf8_length(dt->inpmaptable[pos]); - if ((pos + tlen) > posbound) { - PICODBG_ERROR(("trying outside imt, posb: %d, pos: %d, tlen: %d", - posbound, pos, tlen)); - return FALSE; - } - if (ilen == tlen) { - cont = TRUE; - for (j = 0; cont && (j < ilen); j++) { - if (dt->inpmaptable[pos + j] != inval[j]) { - cont = FALSE; - } - } - if (cont && (j == ilen)) { /* match found */ - *outval = i; - PICODBG_TRACE(("found mapval, posb %d, pos %d, i %d, tlen %d", - posbound, pos, i, tlen)); - return TRUE; - } - } - pos += tlen; - } - PICODBG_DEBUG(("outside imt %d, posb/pos/i: %d/%d/%d, fallback: %d", - imtnr, posbound, pos, i, *outfallbackval)); - return FALSE; -} - - -/* size==1 -> MapOutByte, size==2 -> MapOutWord */ -static picoos_uint8 kdtMapOutFixed(const kdt_subobj_t *dt, - const picoos_uint16 inval, - picoos_uint16 *outval) { - picoos_uint8 size; - picoos_uint16 nr; - - /* no check of lentable vs. nr in initialize done */ - - size = 0; - - /* type */ - nr = dt->outmaptable[PICOKDT_MTPOS_START + PICOKDT_MTPOS_TABLETYPE]; - - /* check type of table and set size */ - if (nr == PICOKDT_MTTYPE_EMPTY) { - /* empty table no mapping needed */ - PICODBG_TRACE(("empty table")); - *outval = inval; - return TRUE; - } else if (nr == PICOKDT_MTTYPE_BYTE) { - size = 1; - } else if (nr == PICOKDT_MTTYPE_WORD) { - size = 2; - } else { - /* wrong table type */ - PICODBG_ERROR(("wrong table type %d", nr)); - return FALSE; - } - - /* number of mapvalues */ - nr = ((picoos_uint16)(dt->outmaptable[PICOKDT_MTPOS_START + - PICOKDT_MTPOS_NUMBER + 1])) << 8 - | dt->outmaptable[PICOKDT_MTPOS_START + PICOKDT_MTPOS_NUMBER]; - - if (inval < nr) { - if (size == 1) { - *outval = dt->outmaptable[PICOKDT_MTPOS_START + - PICOKDT_MTPOS_MAPSTART + (size * inval)]; - } else { - *outval = ((picoos_uint16)(dt->outmaptable[PICOKDT_MTPOS_START + - PICOKDT_MTPOS_MAPSTART + (size * inval) + 1])) << 8 - | dt->outmaptable[PICOKDT_MTPOS_START + - PICOKDT_MTPOS_MAPSTART + (size * inval)]; - } - return TRUE; - } else { - *outval = 0; - return FALSE; - } -} - - -/* size==1 -> ReverseMapOutByte, size==2 -> ReverseMapOutWord */ -/* outmaptable also used to map from decoded tree output domain to - direct tree output domain */ -static picoos_uint8 kdtReverseMapOutFixed(const kdt_subobj_t *dt, - const picoos_uint16 inval, - picoos_uint16 *outval, - picoos_uint16 *outfallbackval) { - picoos_uint8 size; - picoos_uint32 pos; - picoos_uint16 lentable; - picoos_uint16 posbound; - picoos_uint16 i; - - /* no check of lentable vs. nr in initialize done */ - - size = 0; - pos = 0; - *outval = 0; - *outfallbackval = 0; - - if (dt->outmaptable == NULL) { - /* empty table no mapping needed */ - PICODBG_TRACE(("empty table")); - *outval = inval; - return TRUE; - } - - /* check what can be checked */ - if (dt->outmaptable[pos++] != 1) { /* only one omt possible */ - PICODBG_ERROR(("check failed: nrtab: %d", dt->outmaptable[pos-1])); - return FALSE; - } - - /* get length */ - lentable = ((picoos_uint16)(dt->outmaptable[pos+1])) << 8 | - dt->outmaptable[pos]; - posbound = pos + lentable; - pos += 2; - - /* check type of table and set size */ - /* if (dt->outmaptable[pos] == PICOKDT_MTTYPE_EMPTY), in - ...Initialize the omt is set to NULL if not existing, checked - above */ - - if (dt->outmaptable[pos] == PICOKDT_MTTYPE_BYTE) { - size = 1; - } else if (dt->outmaptable[pos] == PICOKDT_MTTYPE_WORD) { - size = 2; - } else { - /* wrong table type */ - PICODBG_ERROR(("wrong table type %d", dt->outmaptable[pos])); - return FALSE; - } - pos++; - - /* set fallback value in case of failed mapping, and set upper bound pos */ - *outfallbackval = ((picoos_uint16)(dt->outmaptable[pos+1])) << 8 | - dt->outmaptable[pos]; - pos += 2; - - /* size must be 1 or 2 here, keep 'redundant' so save time */ - if (size == 1) { - for (i = 0; (i < *outfallbackval) && (pos < posbound); i++) { - if (inval == dt->outmaptable[pos]) { - *outval = i; - PICODBG_TRACE(("s1 inval %d -> outval %d", inval, *outval)); - return TRUE; - } - pos++; - } - } else if (size == 2) { - posbound--; - for (i = 0; (i < *outfallbackval) && (pos < posbound); i++) { - if (inval == (((picoos_uint16)(dt->outmaptable[pos+1])) << 8 | - dt->outmaptable[pos])) { - *outval = i; - PICODBG_TRACE(("s2 inval %d -> outval %d", inval, *outval)); - return TRUE; - } - pos += 2; - } - } else { - /* impossible size */ - PICODBG_ERROR(("wrong size %d", size)); - return FALSE; - } - - PICODBG_DEBUG(("no mapping found, fallback: %d", *outfallbackval)); - return FALSE; -} - - -picoos_uint8 picokdt_dtPosDreverseMapOutFixed(const picokdt_DtPosD this, - const picoos_uint16 inval, - picoos_uint16 *outval, - picoos_uint16 *outfallbackval) { - - kdtposd_subobj_t * dtposd = (kdtposd_subobj_t *)this; - kdt_subobj_t * dt = &(dtposd->dt); - return kdtReverseMapOutFixed(dt,inval, outval, outfallbackval); -} - -/* not yet impl. size==1 -> MapOutByteToVar, - fix: size==2 -> MapOutWordToVar */ -static picoos_uint8 kdtMapOutVar(const kdt_subobj_t *dt, - const picoos_uint16 inval, - picoos_uint8 *nr, - picoos_uint16 *outval, - const picoos_uint16 outvalmaxlen) { - picoos_uint16 pos; - picoos_uint16 off2ind; - picoos_uint16 lentable; - picoos_uint16 nrinbytes; - picoos_uint8 size; - picoos_uint16 offset1; - picoos_uint16 i; - - if (dt->outmaptable == NULL) { - /* empty table not possible */ - PICODBG_ERROR(("no table found")); - return FALSE; - } - - /* nr of tables == 1 already checked in *Initialize, no need here, go - directly to position 1 */ - pos = 1; - - /* get length of table */ - lentable = (((picoos_uint16)(dt->outmaptable[pos + 1])) << 8 | - dt->outmaptable[pos]); - pos += 2; - - /* check table type */ - if (dt->outmaptable[pos] != PICOKDT_MTTYPE_BYTETOVAR) { - /* wrong table type */ - PICODBG_ERROR(("wrong table type %d", dt->outmaptable[pos])); - return FALSE; - } - size = 2; - pos++; - - /* get nr of ele in maptable (= nr of possible invals) */ - nrinbytes = (((picoos_uint16)(dt->outmaptable[pos+1])) << 8 | - dt->outmaptable[pos]); - pos += 2; - - /* check what's checkable */ - if (nrinbytes == 0) { - PICODBG_ERROR(("table with length zero")); - return FALSE; - } else if (inval >= nrinbytes) { - PICODBG_ERROR(("inval %d outside valid range %d", inval, nrinbytes)); - return FALSE; - } - - PICODBG_TRACE(("inval %d, lentable %d, nrinbytes %d, pos %d", inval, - lentable, nrinbytes, pos)); - - /* set off2ind to the position of the start of offset2-val */ - /* offset2 points to start of next ele */ - off2ind = pos + (size*inval); - - /* get number of output values, offset2 - offset1 */ - if (inval == 0) { - offset1 = 0; - } else { - offset1 = (((picoos_uint16)(dt->outmaptable[off2ind - 1])) << 8 | - dt->outmaptable[off2ind - 2]); - } - *nr = (((picoos_uint16)(dt->outmaptable[off2ind + 1])) << 8 | - dt->outmaptable[off2ind]) - offset1; - - PICODBG_TRACE(("offset1 %d, nr %d, pos %d", offset1, *nr, pos)); - - /* set pos to position of 1st value being mapped to */ - pos += (size * nrinbytes) + offset1; - - if ((pos + *nr - 1) > lentable) { - /* outside table, should not happen */ - PICODBG_ERROR(("problem with table index, pos %d, nr %d, len %d", - pos, *nr, lentable)); - return FALSE; - } - if (*nr > outvalmaxlen) { - /* not enough space in outval */ - PICODBG_ERROR(("overflow in outval, %d > %d", *nr, outvalmaxlen)); - return FALSE; - } - - /* finally, copy outmap result to outval */ - for (i = 0; i < *nr; i++) { - outval[i] = dt->outmaptable[pos++]; - } - return TRUE; -} - - - -/* ************************************************************/ -/* decision tree POS prediction (PosP) functions */ -/* ************************************************************/ - -/* number of prefix and suffix graphemes used to construct the input vector */ -#define KDT_POSP_NRGRAPHPREFATT 4 -#define KDT_POSP_NRGRAPHSUFFATT 6 -#define KDT_POSP_NRGRAPHATT 10 - -/* positions of specgraph and nrgraphs attributes */ -#define KDT_POSP_SPECGRAPHATTPOS 10 -#define KDT_POSP_NRGRAPHSATTPOS 11 - - -/* construct PosP input vector - - PosP invec: 12 elements - - prefix 0-3 prefix graphemes (encoded using tree inpmaptable 0-3) - suffix 4-9 suffix graphemes (encoded using tree inpmaptable 4-9) - isspecchar 10 is a special grapheme (e.g. hyphen) inside the word (0/1)? - nr-utf-graphs 11 number of graphemes (ie. UTF8 chars) - - if there are less than 10 graphemes, each grapheme is used only - once, with the suffix having higher priority, ie. elements 0-9 are - filled as follows: - - #graph - 1 0 0 0 0 0 0 0 0 0 1 - 2 0 0 0 0 0 0 0 0 1 2 - 3 0 0 0 0 0 0 0 1 2 3 - 4 0 0 0 0 0 0 1 2 3 4 - 5 0 0 0 0 0 1 2 3 4 5 - 6 0 0 0 0 1 2 3 4 5 6 - 7 1 0 0 0 2 3 4 5 6 7 - 8 1 2 0 0 3 4 5 6 7 8 - 9 1 2 3 0 4 5 6 7 8 9 - 10 1 2 3 4 5 6 7 8 9 10 - 11 1 2 3 4 6 7 8 9 10 11 - ... - - 1-6: Fill chbuf - 7-10: front to invec 1st part, remove front, add rear - >10: remove front, add rear - no more graph -> - while chbuflen>0: - add rear to the last empty slot in 2nd part of invec, remove rear -*/ - - -picoos_uint8 picokdt_dtPosPconstructInVec(const picokdt_DtPosP this, - const picoos_uint8 *graph, - const picoos_uint16 graphlen, - const picoos_uint8 specgraphflag) { - kdtposp_subobj_t *dtposp; - - /* utf8 circular char buffer, used as restricted input deque */ - /* 2nd part of graph invec has KDT_POSP_NRGRAPHSUFFATT elements, */ - /* max of UTF8_MAXLEN bytes per utf8 char */ - picoos_uint8 chbuf[KDT_POSP_NRGRAPHSUFFATT][PICOBASE_UTF8_MAXLEN]; - picoos_uint8 chbrear; /* next free pos */ - picoos_uint8 chbfront; /* next read pos */ - picoos_uint8 chblen; /* empty=0; full=KDT_POSP_NRGRAPHSUFFATT */ - - picoos_uint16 poscg; /* position of current graph (= utf8 char) */ - picoos_uint16 lencg = 0; /* length of current grapheme */ - picoos_uint16 nrutfg; /* number of utf graphemes */ - picoos_uint8 invecpos; /* next element to add in invec */ - picoos_uint16 fallback; /* fallback value for failed graph encodings */ - picoos_uint8 i; - - dtposp = (kdtposp_subobj_t *)this; - chbrear = 0; - chbfront = 0; - chblen = 0; - poscg = 0; - nrutfg = 0; - invecpos = 0; - - PICODBG_DEBUG(("graphlen %d", graphlen)); - - /* not needed, since all elements are set - for (i = 0; i < PICOKDT_NRATT_POSP; i++) { - dtposp->invec[i] = '\x63'; - } - */ - - dtposp->inveclen = 0; - - while ((poscg < graphlen) && - ((lencg = picobase_det_utf8_length(graph[poscg])) > 0)) { - if (chblen >= KDT_POSP_NRGRAPHSUFFATT) { /* chbuf full */ - if (invecpos < KDT_POSP_NRGRAPHPREFATT) { /* prefix not full */ - /* att-encode front utf graph and add in invec */ - if (!kdtMapInGraph(&(dtposp->dt), invecpos, - chbuf[chbfront], PICOBASE_UTF8_MAXLEN, - &(dtposp->invec[invecpos]), - &fallback)) { - if (fallback) { - dtposp->invec[invecpos] = fallback; - } else { - return FALSE; - } - } - invecpos++; - } - /* remove front utf graph */ - chbfront++; - chbfront %= KDT_POSP_NRGRAPHSUFFATT; - chblen--; - } - /* add current utf graph to chbuf */ - for (i=0; i 0) { - - while (invecpos < KDT_POSP_NRGRAPHPREFATT) { /* fill up prefix */ - if (!kdtMapInGraph(&(dtposp->dt), invecpos, - PICOKDT_OUTSIDEGRAPH_DEFSTR, - PICOKDT_OUTSIDEGRAPH_DEFLEN, - &(dtposp->invec[invecpos]), &fallback)) { - if (fallback) { - dtposp->invec[invecpos] = fallback; - } else { - return FALSE; - } - } - invecpos++; - } - - for (i = (KDT_POSP_NRGRAPHATT - 1); - i >= KDT_POSP_NRGRAPHPREFATT; i--) { - if (chblen > 0) { - if (chbrear == 0) { - chbrear = KDT_POSP_NRGRAPHSUFFATT - 1; - } else { - chbrear--; - } - if (!kdtMapInGraph(&(dtposp->dt), i, chbuf[chbrear], - PICOBASE_UTF8_MAXLEN, - &(dtposp->invec[i]), &fallback)) { - if (fallback) { - dtposp->invec[i] = fallback; - } else { - return FALSE; - } - } - chblen--; - } else { - if (!kdtMapInGraph(&(dtposp->dt), i, - PICOKDT_OUTSIDEGRAPH_DEFSTR, - PICOKDT_OUTSIDEGRAPH_DEFLEN, - &(dtposp->invec[i]), &fallback)) { - if (fallback) { - dtposp->invec[i] = fallback; - } else { - return FALSE; - } - } - } - } - - /* set isSpecChar attribute, reuse var i */ - i = (specgraphflag ? 1 : 0); - if (!kdtMapInFixed(&(dtposp->dt), KDT_POSP_SPECGRAPHATTPOS, i, - &(dtposp->invec[KDT_POSP_SPECGRAPHATTPOS]), - &fallback)) { - if (fallback) { - dtposp->invec[KDT_POSP_SPECGRAPHATTPOS] = fallback; - } else { - return FALSE; - } - } - - /* set nrGraphs attribute */ - if (!kdtMapInFixed(&(dtposp->dt), KDT_POSP_NRGRAPHSATTPOS, nrutfg, - &(dtposp->invec[KDT_POSP_NRGRAPHSATTPOS]), - &fallback)) { - if (fallback) { - dtposp->invec[KDT_POSP_NRGRAPHSATTPOS] = fallback; - } else { - return FALSE; - } - } - PICODBG_DEBUG(("posp-invec: [%d,%d,%d,%d|%d,%d,%d,%d,%d,%d|%d|%d]", - dtposp->invec[0], dtposp->invec[1], dtposp->invec[2], - dtposp->invec[3], dtposp->invec[4], dtposp->invec[5], - dtposp->invec[6], dtposp->invec[7], dtposp->invec[8], - dtposp->invec[9], dtposp->invec[10], - dtposp->invec[11], dtposp->invec[12])); - dtposp->inveclen = PICOKDT_NRINPMT_POSP; - return TRUE; - } - - return FALSE; -} - - -picoos_uint8 picokdt_dtPosPclassify(const picokdt_DtPosP this) { - picoos_uint32 iByteNo; - picoos_int8 iBitNo; - picoos_int8 rv; - kdtposp_subobj_t *dtposp; - kdt_subobj_t *dt; - - dtposp = (kdtposp_subobj_t *)this; - dt = &(dtposp->dt); - iByteNo = 0; - iBitNo = 7; - while ((rv = kdtAskTree(dt, dtposp->invec, PICOKDT_NRATT_POSP, - &iByteNo, &iBitNo)) > 0) { - PICODBG_TRACE(("asking tree")); - } - PICODBG_DEBUG(("done: %d", dt->dclass)); - return ((rv == 0) && dt->dset); -} - - -picoos_uint8 picokdt_dtPosPdecomposeOutClass(const picokdt_DtPosP this, - picokdt_classify_result_t *dtres) { - kdtposp_subobj_t *dtposp; - picoos_uint16 val; - - dtposp = (kdtposp_subobj_t *)this; - - if (dtposp->dt.dset && - kdtMapOutFixed(&(dtposp->dt), dtposp->dt.dclass, &val)) { - dtres->set = TRUE; - dtres->class = val; - return TRUE; - } else { - dtres->set = FALSE; - return FALSE; - } -} - - - -/* ************************************************************/ -/* decision tree POS disambiguation (PosD) functions */ -/* ************************************************************/ - - -picoos_uint8 picokdt_dtPosDconstructInVec(const picokdt_DtPosD this, - const picoos_uint16 * input) { - kdtposd_subobj_t *dtposd; - picoos_uint8 i; - picoos_uint16 fallback = 0; - - dtposd = (kdtposd_subobj_t *)this; - dtposd->inveclen = 0; - - PICODBG_DEBUG(("in: [%d,%d,%d|%d|%d,%d,%d]", - input[0], input[1], input[2], - input[3], input[4], input[5], - input[6])); - for (i = 0; i < PICOKDT_NRATT_POSD; i++) { - - /* do the imt mapping for all inval */ - if (!kdtMapInFixed(&(dtposd->dt), i, input[i], - &(dtposd->invec[i]), &fallback)) { - if (fallback) { - PICODBG_DEBUG(("*** using fallback for input mapping: %i -> %i", input[i], fallback)); - dtposd->invec[i] = fallback; - } else { - PICODBG_ERROR(("problem doing input mapping")); - return FALSE; - } - } - } - - PICODBG_DEBUG(("out: [%d,%d,%d|%d|%d,%d,%d]", - dtposd->invec[0], dtposd->invec[1], dtposd->invec[2], - dtposd->invec[3], dtposd->invec[4], dtposd->invec[5], - dtposd->invec[6])); - dtposd->inveclen = PICOKDT_NRINPMT_POSD; - return TRUE; -} - - -picoos_uint8 picokdt_dtPosDclassify(const picokdt_DtPosD this, - picoos_uint16 *treeout) { - picoos_uint32 iByteNo; - picoos_int8 iBitNo; - picoos_int8 rv; - kdtposd_subobj_t *dtposd; - kdt_subobj_t *dt; - - dtposd = (kdtposd_subobj_t *)this; - dt = &(dtposd->dt); - iByteNo = 0; - iBitNo = 7; - while ((rv = kdtAskTree(dt, dtposd->invec, PICOKDT_NRATT_POSD, - &iByteNo, &iBitNo)) > 0) { - PICODBG_TRACE(("asking tree")); - } - PICODBG_DEBUG(("done: %d", dt->dclass)); - if ((rv == 0) && dt->dset) { - *treeout = dt->dclass; - return TRUE; - } else { - return FALSE; - } -} - - -/* decompose the tree output and return the class in dtres - dtres: POS classification result - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtPosDdecomposeOutClass(const picokdt_DtPosD this, - picokdt_classify_result_t *dtres) { - kdtposd_subobj_t *dtposd; - picoos_uint16 val; - - dtposd = (kdtposd_subobj_t *)this; - - if (dtposd->dt.dset && - kdtMapOutFixed(&(dtposd->dt), dtposd->dt.dclass, &val)) { - dtres->set = TRUE; - dtres->class = val; - return TRUE; - } else { - dtres->set = FALSE; - return FALSE; - } -} - - - -/* ************************************************************/ -/* decision tree grapheme-to-phoneme (G2P) functions */ -/* ************************************************************/ - - -/* get the nr'th (starting at 0) utf char in utfgraph */ -static picoos_uint8 kdtGetUTF8char(const picoos_uint8 *utfgraph, - const picoos_uint16 graphlen, - const picoos_uint16 nr, - picoos_uint8 *utf8char) { - picoos_uint16 i; - picoos_uint32 pos; - - pos = 0; - for (i = 0; i < nr; i++) { - if (!picobase_get_next_utf8charpos(utfgraph, graphlen, &pos)) { - return FALSE; - } - } - return picobase_get_next_utf8char(utfgraph, graphlen, &pos, utf8char); -} - -/* determine the utfchar count (starting at 1) of the utfchar starting at pos */ -static picoos_uint16 kdtGetUTF8Nr(const picoos_uint8 *utfgraph, - const picoos_uint16 graphlen, - const picoos_uint16 pos) { - picoos_uint32 postmp; - picoos_uint16 count; - - count = 0; - postmp = 0; - while ((postmp <= pos) && (count < graphlen)) { - if (!picobase_get_next_utf8charpos(utfgraph, graphlen, &postmp)) { - PICODBG_ERROR(("invalid utf8 string, count: %d, pos: %d, post: %d", - count, pos, postmp)); - return count + 1; - } - count++; - } - return count; -} - - -picoos_uint8 picokdt_dtG2PconstructInVec(const picokdt_DtG2P this, - const picoos_uint8 *graph, - const picoos_uint16 graphlen, - const picoos_uint8 count, - const picoos_uint8 pos, - const picoos_uint8 nrvow, - const picoos_uint8 ordvow, - picoos_uint8 *primstressflag, - const picoos_uint16 phonech1, - const picoos_uint16 phonech2, - const picoos_uint16 phonech3) { - kdtg2p_subobj_t *dtg2p; - picoos_uint16 fallback = 0; - picoos_uint8 iAttr; - picoos_uint8 utf8char[PICOBASE_UTF8_MAXLEN + 1]; - picoos_uint16 inval; - picoos_int16 cinv; - picoos_uint8 retval; - picoos_int32 utfgraphlen; - picoos_uint16 utfcount; - - dtg2p = (kdtg2p_subobj_t *)this; - retval = TRUE; - inval = 0; - - PICODBG_TRACE(("in: [%d,%d,%d|%d,%d|%d|%d,%d,%d]", graphlen, count, pos, - nrvow, ordvow, *primstressflag, phonech1, phonech2, - phonech3)); - - dtg2p->inveclen = 0; - - /* many speed-ups possible */ - - /* graph attributes */ - /* count > = <= count - iAttr lowbound eow upbound delta - 0 4 4 graphlen 5 - 1 3 3 graphlen 4 - 2 2 2 graphlen 3 - 3 1 1 graphlen 2 - 4 0 - graphlen 1 - - 5 0 graphlen graphlen-1 0 - 6 0 graphlen-1 graphlen-2 -1 - 7 0 graphlen-2 graphlen-3 -2 - 8 0 graphlen-3 graphlen-4 -3 - */ - - /* graph attributes left (context -4/-3/-2/-1) and current, MapInGraph */ - - utfgraphlen = picobase_utf8_length(graph, graphlen); - if (utfgraphlen <= 0) { - utfgraphlen = 0; - } - utfcount = kdtGetUTF8Nr(graph, graphlen, count); - - cinv = 4; - for (iAttr = 0; iAttr < 5; iAttr++) { - if ((utfcount > cinv) && (utfcount <= utfgraphlen)) { - -/* utf8char[0] = graph[count - cinv - 1];*/ - if (!kdtGetUTF8char(graph, graphlen, utfcount-cinv-1, - utf8char)) { - PICODBG_WARN(("problem getting UTF char %d", utfcount-cinv-1)); - utf8char[0] = PICOKDT_OUTSIDEGRAPH_DEFCH; - utf8char[1] = '\0'; - } - } else { - if ((utfcount == cinv) && (iAttr != 4)) { - utf8char[0] = PICOKDT_OUTSIDEGRAPH_EOW_DEFCH; - } else { - utf8char[0] = PICOKDT_OUTSIDEGRAPH_DEFCH; - } - utf8char[1] = '\0'; - } - - if (!kdtMapInGraph(&(dtg2p->dt), iAttr, - utf8char, PICOBASE_UTF8_MAXLEN, - &(dtg2p->invec[iAttr]), - &fallback)) { - if (fallback) { - dtg2p->invec[iAttr] = fallback; - } else { - PICODBG_WARN(("setting attribute %d to zero", iAttr)); - dtg2p->invec[iAttr] = 0; - retval = FALSE; - } - } - PICODBG_TRACE(("invec %d %c", iAttr, utf8char[0])); - cinv--; - } - - /* graph attributes right (context 1/2/3/4), MapInGraph */ - cinv = utfgraphlen; - for (iAttr = 5; iAttr < 9; iAttr++) { - if ((utfcount > 0) && (utfcount <= (cinv - 1))) { -/* utf8char[0] = graph[count + graphlen - cinv];*/ - if (!kdtGetUTF8char(graph, graphlen, utfcount+utfgraphlen-cinv, - utf8char)) { - PICODBG_WARN(("problem getting UTF char %d", - utfcount+utfgraphlen-cinv-1)); - utf8char[0] = PICOKDT_OUTSIDEGRAPH_DEFCH; - utf8char[1] = '\0'; - } - } else { - if (utfcount == cinv) { - utf8char[0] = PICOKDT_OUTSIDEGRAPH_EOW_DEFCH; - utf8char[1] = '\0'; - } else { - utf8char[0] = PICOKDT_OUTSIDEGRAPH_DEFCH; - utf8char[1] = '\0'; - } - } - if (!kdtMapInGraph(&(dtg2p->dt), iAttr, - utf8char, PICOBASE_UTF8_MAXLEN, - &(dtg2p->invec[iAttr]), - &fallback)) { - if (fallback) { - dtg2p->invec[iAttr] = fallback; - } else { - PICODBG_WARN(("setting attribute %d to zero", iAttr)); - dtg2p->invec[iAttr] = 0; - retval = FALSE; - } - } - PICODBG_TRACE(("invec %d %c", iAttr, utf8char[0])); - cinv--; - } - - /* other attributes, MapInFixed */ - for (iAttr = 9; iAttr < PICOKDT_NRATT_G2P; iAttr++) { - switch (iAttr) { - case 9: /* word POS, Fix1 */ - inval = pos; - break; - case 10: /* nr of vowel-like graphs in word, if vowel, Fix2 */ - inval = nrvow; - break; - case 11: /* order of current vowel-like graph in word, Fix2 */ - inval = ordvow; - break; - case 12: /* primary stress mark, Fix2 */ - if (*primstressflag == 1) { - /*already set previously*/ - inval = 1; - } else { - inval = 0; - } - break; - case 13: /* phone chunk right context +1, Hist */ - inval = phonech1; - break; - case 14: /* phone chunk right context +2, Hist */ - inval = phonech2; - break; - case 15: /* phone chunk right context +3, Hist */ - inval = phonech3; - break; - } - - PICODBG_TRACE(("invec %d %d", iAttr, inval)); - - if (!kdtMapInFixed(&(dtg2p->dt), iAttr, inval, - &(dtg2p->invec[iAttr]), &fallback)) { - if (fallback) { - dtg2p->invec[iAttr] = fallback; - } else { - PICODBG_WARN(("setting attribute %d to zero", iAttr)); - dtg2p->invec[iAttr] = 0; - retval = FALSE; - } - } - } - - PICODBG_TRACE(("out: [%d,%d%,%d,%d|%d|%d,%d,%d,%d|%d,%d,%d,%d|" - "%d,%d,%d]", dtg2p->invec[0], dtg2p->invec[1], - dtg2p->invec[2], dtg2p->invec[3], dtg2p->invec[4], - dtg2p->invec[5], dtg2p->invec[6], dtg2p->invec[7], - dtg2p->invec[8], dtg2p->invec[9], dtg2p->invec[10], - dtg2p->invec[11], dtg2p->invec[12], dtg2p->invec[13], - dtg2p->invec[14], dtg2p->invec[15])); - - dtg2p->inveclen = PICOKDT_NRINPMT_G2P; - return retval; -} - - - - -picoos_uint8 picokdt_dtG2Pclassify(const picokdt_DtG2P this, - picoos_uint16 *treeout) { - picoos_uint32 iByteNo; - picoos_int8 iBitNo; - picoos_int8 rv; - kdtg2p_subobj_t *dtg2p; - kdt_subobj_t *dt; - - dtg2p = (kdtg2p_subobj_t *)this; - dt = &(dtg2p->dt); - iByteNo = 0; - iBitNo = 7; - while ((rv = kdtAskTree(dt, dtg2p->invec, PICOKDT_NRATT_G2P, - &iByteNo, &iBitNo)) > 0) { - PICODBG_TRACE(("asking tree")); - } - PICODBG_TRACE(("done: %d", dt->dclass)); - if ((rv == 0) && dt->dset) { - *treeout = dt->dclass; - return TRUE; - } else { - return FALSE; - } -} - - - -picoos_uint8 picokdt_dtG2PdecomposeOutClass(const picokdt_DtG2P this, - picokdt_classify_vecresult_t *dtvres) { - kdtg2p_subobj_t *dtg2p; - - dtg2p = (kdtg2p_subobj_t *)this; - - if (dtg2p->dt.dset && - kdtMapOutVar(&(dtg2p->dt), dtg2p->dt.dclass, &(dtvres->nr), - dtvres->classvec, PICOKDT_MAXSIZE_OUTVEC)) { - return TRUE; - } else { - dtvres->nr = 0; - return FALSE; - } - return TRUE; -} - - - -/* ************************************************************/ -/* decision tree phrasing (PHR) functions */ -/* ************************************************************/ - -picoos_uint8 picokdt_dtPHRconstructInVec(const picokdt_DtPHR this, - const picoos_uint8 pre2, - const picoos_uint8 pre1, - const picoos_uint8 src, - const picoos_uint8 fol1, - const picoos_uint8 fol2, - const picoos_uint16 nrwordspre, - const picoos_uint16 nrwordsfol, - const picoos_uint16 nrsyllsfol) { - kdtphr_subobj_t *dtphr; - picoos_uint8 i; - picoos_uint16 inval = 0; - picoos_uint16 fallback = 0; - - dtphr = (kdtphr_subobj_t *)this; - PICODBG_DEBUG(("in: [%d,%d|%d|%d,%d|%d,%d,%d]", - pre2, pre1, src, fol1, fol2, - nrwordspre, nrwordsfol, nrsyllsfol)); - dtphr->inveclen = 0; - - for (i = 0; i < PICOKDT_NRATT_PHR; i++) { - switch (i) { - case 0: inval = pre2; break; - case 1: inval = pre1; break; - case 2: inval = src; break; - case 3: inval = fol1; break; - case 4: inval = fol2; break; - case 5: inval = nrwordspre; break; - case 6: inval = nrwordsfol; break; - case 7: inval = nrsyllsfol; break; - default: - PICODBG_ERROR(("size mismatch")); - return FALSE; - break; - } - - /* do the imt mapping for all inval */ - if (!kdtMapInFixed(&(dtphr->dt), i, inval, - &(dtphr->invec[i]), &fallback)) { - if (fallback) { - dtphr->invec[i] = fallback; - } else { - PICODBG_ERROR(("problem doing input mapping")); - return FALSE; - } - } - } - - PICODBG_DEBUG(("out: [%d,%d|%d|%d,%d|%d,%d,%d]", - dtphr->invec[0], dtphr->invec[1], dtphr->invec[2], - dtphr->invec[3], dtphr->invec[4], dtphr->invec[5], - dtphr->invec[6], dtphr->invec[7])); - dtphr->inveclen = PICOKDT_NRINPMT_PHR; - return TRUE; -} - - -picoos_uint8 picokdt_dtPHRclassify(const picokdt_DtPHR this) { - picoos_uint32 iByteNo; - picoos_int8 iBitNo; - picoos_int8 rv; - kdtphr_subobj_t *dtphr; - kdt_subobj_t *dt; - - dtphr = (kdtphr_subobj_t *)this; - dt = &(dtphr->dt); - iByteNo = 0; - iBitNo = 7; - while ((rv = kdtAskTree(dt, dtphr->invec, PICOKDT_NRATT_PHR, - &iByteNo, &iBitNo)) > 0) { - PICODBG_TRACE(("asking tree")); - } - PICODBG_DEBUG(("done: %d", dt->dclass)); - return ((rv == 0) && dt->dset); -} - - -picoos_uint8 picokdt_dtPHRdecomposeOutClass(const picokdt_DtPHR this, - picokdt_classify_result_t *dtres) { - kdtphr_subobj_t *dtphr; - picoos_uint16 val; - - dtphr = (kdtphr_subobj_t *)this; - - if (dtphr->dt.dset && - kdtMapOutFixed(&(dtphr->dt), dtphr->dt.dclass, &val)) { - dtres->set = TRUE; - dtres->class = val; - return TRUE; - } else { - dtres->set = FALSE; - return FALSE; - } -} - - - -/* ************************************************************/ -/* decision tree phono-acoustical model (PAM) functions */ -/* ************************************************************/ - -picoos_uint8 picokdt_dtPAMconstructInVec(const picokdt_DtPAM this, - const picoos_uint8 *vec, - const picoos_uint8 veclen) { - kdtpam_subobj_t *dtpam; - picoos_uint8 i; - picoos_uint16 fallback = 0; - - dtpam = (kdtpam_subobj_t *)this; - - PICODBG_TRACE(("in0: %d %d %d %d %d %d %d %d %d %d", - vec[0], vec[1], vec[2], vec[3], vec[4], - vec[5], vec[6], vec[7], vec[8], vec[9])); - PICODBG_TRACE(("in1: %d %d %d %d %d %d %d %d %d %d", - vec[10], vec[11], vec[12], vec[13], vec[14], - vec[15], vec[16], vec[17], vec[18], vec[19])); - PICODBG_TRACE(("in2: %d %d %d %d %d %d %d %d %d %d", - vec[20], vec[21], vec[22], vec[23], vec[24], - vec[25], vec[26], vec[27], vec[28], vec[29])); - PICODBG_TRACE(("in3: %d %d %d %d %d %d %d %d %d %d", - vec[30], vec[31], vec[32], vec[33], vec[34], - vec[35], vec[36], vec[37], vec[38], vec[39])); - PICODBG_TRACE(("in4: %d %d %d %d %d %d %d %d %d %d", - vec[40], vec[41], vec[42], vec[43], vec[44], - vec[45], vec[46], vec[47], vec[48], vec[49])); - PICODBG_TRACE(("in5: %d %d %d %d %d %d %d %d %d %d", - vec[50], vec[51], vec[52], vec[53], vec[54], - vec[55], vec[56], vec[57], vec[58], vec[59])); - - dtpam->inveclen = 0; - - /* check veclen */ - if (veclen != PICOKDT_NRINPMT_PAM) { - PICODBG_ERROR(("wrong number of input vector elements")); - return FALSE; - } - - for (i = 0; i < PICOKDT_NRATT_PAM; i++) { - - /* do the imt mapping for all vec eles */ - if (!kdtMapInFixed(&(dtpam->dt), i, vec[i], - &(dtpam->invec[i]), &fallback)) { - if (fallback) { - dtpam->invec[i] = fallback; - } else { - PICODBG_ERROR(("problem doing input mapping, %d %d", i,vec[i])); - return FALSE; - } - } - } - - PICODBG_TRACE(("in0: %d %d %d %d %d %d %d %d %d %d", - dtpam->invec[0], dtpam->invec[1], dtpam->invec[2], - dtpam->invec[3], dtpam->invec[4], dtpam->invec[5], - dtpam->invec[6], dtpam->invec[7], dtpam->invec[8], - dtpam->invec[9])); - PICODBG_TRACE(("in1: %d %d %d %d %d %d %d %d %d %d", - dtpam->invec[10], dtpam->invec[11], dtpam->invec[12], - dtpam->invec[13], dtpam->invec[14], dtpam->invec[15], - dtpam->invec[16], dtpam->invec[17], dtpam->invec[18], - dtpam->invec[19])); - PICODBG_TRACE(("in2: %d %d %d %d %d %d %d %d %d %d", - dtpam->invec[20], dtpam->invec[21], dtpam->invec[22], - dtpam->invec[23], dtpam->invec[24], dtpam->invec[25], - dtpam->invec[26], dtpam->invec[27], dtpam->invec[28], - dtpam->invec[29])); - PICODBG_TRACE(("in3: %d %d %d %d %d %d %d %d %d %d", - dtpam->invec[30], dtpam->invec[31], dtpam->invec[32], - dtpam->invec[33], dtpam->invec[34], dtpam->invec[35], - dtpam->invec[36], dtpam->invec[37], dtpam->invec[38], - dtpam->invec[39])); - PICODBG_TRACE(("in4: %d %d %d %d %d %d %d %d %d %d", - dtpam->invec[40], dtpam->invec[41], dtpam->invec[42], - dtpam->invec[43], dtpam->invec[44], dtpam->invec[45], - dtpam->invec[46], dtpam->invec[47], dtpam->invec[48], - dtpam->invec[49])); - PICODBG_TRACE(("in5: %d %d %d %d %d %d %d %d %d %d", - dtpam->invec[50], dtpam->invec[51], dtpam->invec[52], - dtpam->invec[53], dtpam->invec[54], dtpam->invec[55], - dtpam->invec[56], dtpam->invec[57], dtpam->invec[58], - dtpam->invec[59])); - - dtpam->inveclen = PICOKDT_NRINPMT_PAM; - return TRUE; -} - - -picoos_uint8 picokdt_dtPAMclassify(const picokdt_DtPAM this) { - picoos_uint32 iByteNo; - picoos_int8 iBitNo; - picoos_int8 rv; - kdtpam_subobj_t *dtpam; - kdt_subobj_t *dt; - - dtpam = (kdtpam_subobj_t *)this; - dt = &(dtpam->dt); - iByteNo = 0; - iBitNo = 7; - while ((rv = kdtAskTree(dt, dtpam->invec, PICOKDT_NRATT_PAM, - &iByteNo, &iBitNo)) > 0) { - PICODBG_TRACE(("asking tree")); - } - PICODBG_DEBUG(("done: %d", dt->dclass)); - return ((rv == 0) && dt->dset); -} - - -picoos_uint8 picokdt_dtPAMdecomposeOutClass(const picokdt_DtPAM this, - picokdt_classify_result_t *dtres) { - kdtpam_subobj_t *dtpam; - picoos_uint16 val; - - dtpam = (kdtpam_subobj_t *)this; - - if (dtpam->dt.dset && - kdtMapOutFixed(&(dtpam->dt), dtpam->dt.dclass, &val)) { - dtres->set = TRUE; - dtres->class = val; - return TRUE; - } else { - dtres->set = FALSE; - return FALSE; - } -} - - - -/* ************************************************************/ -/* decision tree accentuation (ACC) functions */ -/* ************************************************************/ - -picoos_uint8 picokdt_dtACCconstructInVec(const picokdt_DtACC this, - const picoos_uint8 pre2, - const picoos_uint8 pre1, - const picoos_uint8 src, - const picoos_uint8 fol1, - const picoos_uint8 fol2, - const picoos_uint16 hist1, - const picoos_uint16 hist2, - const picoos_uint16 nrwordspre, - const picoos_uint16 nrsyllspre, - const picoos_uint16 nrwordsfol, - const picoos_uint16 nrsyllsfol, - const picoos_uint16 footwordsfol, - const picoos_uint16 footsyllsfol) { - kdtacc_subobj_t *dtacc; - picoos_uint8 i; - picoos_uint16 inval = 0; - picoos_uint16 fallback = 0; - - dtacc = (kdtacc_subobj_t *)this; - PICODBG_DEBUG(("in: [%d,%d,%d,%d,%d|%d,%d|%d,%d,%d,%d|%d,%d]", - pre2, pre1, src, fol1, fol2, hist1, hist2, - nrwordspre, nrsyllspre, nrwordsfol, nrsyllsfol, - footwordsfol, footsyllsfol)); - dtacc->inveclen = 0; - - for (i = 0; i < PICOKDT_NRATT_ACC; i++) { - switch (i) { - case 0: inval = pre2; break; - case 1: inval = pre1; break; - case 2: inval = src; break; - case 3: inval = fol1; break; - case 4: inval = fol2; break; - case 5: inval = hist1; break; - case 6: inval = hist2; break; - case 7: inval = nrwordspre; break; - case 8: inval = nrsyllspre; break; - case 9: inval = nrwordsfol; break; - case 10: inval = nrsyllsfol; break; - case 11: inval = footwordsfol; break; - case 12: inval = footsyllsfol; break; - default: - PICODBG_ERROR(("size mismatch")); - return FALSE; - break; - } - - if (((i == 5) || (i == 6)) && (inval == PICOKDT_HISTORY_ZERO)) { - /* in input to this function the HISTORY_ZERO is used to - mark the no-value-available case. For sparsity reasons - this was not used in the training. For - no-value-available cases, instead, do reverse out - mapping of ACC0 to get tree domain for ACC0 */ - if (!kdtReverseMapOutFixed(&(dtacc->dt), PICODATA_ACC0, - &inval, &fallback)) { - if (fallback) { - inval = fallback; - } else { - PICODBG_ERROR(("problem doing reverse output mapping")); - return FALSE; - } - } - } - - /* do the imt mapping for all inval */ - if (!kdtMapInFixed(&(dtacc->dt), i, inval, - &(dtacc->invec[i]), &fallback)) { - if (fallback) { - dtacc->invec[i] = fallback; - } else { - PICODBG_ERROR(("problem doing input mapping")); - return FALSE; - } - } - } - - PICODBG_DEBUG(("out: [%d,%d,%d,%d,%d|%d,%d|%d,%d,%d,%d|%d,%d]", - dtacc->invec[0], dtacc->invec[1], dtacc->invec[2], - dtacc->invec[3], dtacc->invec[4], dtacc->invec[5], - dtacc->invec[6], dtacc->invec[7], dtacc->invec[8], - dtacc->invec[9], dtacc->invec[10], dtacc->invec[11], - dtacc->invec[12])); - dtacc->inveclen = PICOKDT_NRINPMT_ACC; - return TRUE; -} - - -picoos_uint8 picokdt_dtACCclassify(const picokdt_DtACC this, - picoos_uint16 *treeout) { - picoos_uint32 iByteNo; - picoos_int8 iBitNo; - picoos_int8 rv; - kdtacc_subobj_t *dtacc; - kdt_subobj_t *dt; - - dtacc = (kdtacc_subobj_t *)this; - dt = &(dtacc->dt); - iByteNo = 0; - iBitNo = 7; - while ((rv = kdtAskTree(dt, dtacc->invec, PICOKDT_NRATT_ACC, - &iByteNo, &iBitNo)) > 0) { - PICODBG_TRACE(("asking tree")); - } - PICODBG_TRACE(("done: %d", dt->dclass)); - if ((rv == 0) && dt->dset) { - *treeout = dt->dclass; - return TRUE; - } else { - return FALSE; - } -} - - -picoos_uint8 picokdt_dtACCdecomposeOutClass(const picokdt_DtACC this, - picokdt_classify_result_t *dtres) { - kdtacc_subobj_t *dtacc; - picoos_uint16 val; - - dtacc = (kdtacc_subobj_t *)this; - - if (dtacc->dt.dset && - kdtMapOutFixed(&(dtacc->dt), dtacc->dt.dclass, &val)) { - dtres->set = TRUE; - dtres->class = val; - return TRUE; - } else { - dtres->set = FALSE; - return FALSE; - } -} - -#ifdef __cplusplus -} -#endif - - -/* end */ diff --git a/lib/picokdt.h b/lib/picokdt.h deleted file mode 100644 index 3ef973c..0000000 --- a/lib/picokdt.h +++ /dev/null @@ -1,465 +0,0 @@ -/* - * 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 picokdt.h - * - * knowledge handling for decision trees - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#ifndef PICOKDT_H_ -#define PICOKDT_H_ - -#include "picoos.h" -#include "picoknow.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* ************************************************************/ -/* - Several specialized decision trees kb are provided by this - knowledge handling module: - - - Part of speech prediction decision tree: ...kdt_PosP - - Part of speech disambiguation decision tree: ...kdt_PosD - - Grapheme-to-phoneme decision tree: ...kdt_G2P - - Phrasing decision tree: ...kdt_PHR - - Accentuation decision tree: ...kdt_ACC - these 5 tree types may be unified in the future to a single type - - - Phono-acoustical model trees: ...kdt_PAM - (actually 11 trees, but all have the same characteristics and - are instances of the same class) -*/ -/* ************************************************************/ - - -/* ************************************************************/ -/* defines and functions to create specialized kb, */ -/* to be used by picorsrc only */ -/* ************************************************************/ - -typedef enum { - PICOKDT_KDTTYPE_POSP, - PICOKDT_KDTTYPE_POSD, - PICOKDT_KDTTYPE_G2P, - PICOKDT_KDTTYPE_PHR, - PICOKDT_KDTTYPE_ACC, - PICOKDT_KDTTYPE_PAM -} picokdt_kdttype_t; - -pico_status_t picokdt_specializeDtKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common, - const picokdt_kdttype_t type); - - -/* ************************************************************/ -/* decision tree types (opaque) and get Tree functions */ -/* ************************************************************/ - -/* decision tree types */ -typedef struct picokdt_dtposp * picokdt_DtPosP; -typedef struct picokdt_dtposd * picokdt_DtPosD; -typedef struct picokdt_dtg2p * picokdt_DtG2P; -typedef struct picokdt_dtphr * picokdt_DtPHR; -typedef struct picokdt_dtacc * picokdt_DtACC; -typedef struct picokdt_dtpam * picokdt_DtPAM; - -/* return kb decision tree for usage in PU */ -picokdt_DtPosP picokdt_getDtPosP(picoknow_KnowledgeBase this); -picokdt_DtPosD picokdt_getDtPosD(picoknow_KnowledgeBase this); -picokdt_DtG2P picokdt_getDtG2P (picoknow_KnowledgeBase this); -picokdt_DtPHR picokdt_getDtPHR (picoknow_KnowledgeBase this); -picokdt_DtACC picokdt_getDtACC (picoknow_KnowledgeBase this); -picokdt_DtPAM picokdt_getDtPAM (picoknow_KnowledgeBase this); - - -/* number of attributes (= input vector size) for each tree type */ -typedef enum { - PICOKDT_NRATT_POSP = 12, - PICOKDT_NRATT_POSD = 7, - PICOKDT_NRATT_G2P = 16, - PICOKDT_NRATT_PHR = 8, - PICOKDT_NRATT_ACC = 13, - PICOKDT_NRATT_PAM = 60 -} kdt_nratt_t; - - -/* ************************************************************/ -/* decision tree classification result type */ -/* ************************************************************/ - -typedef struct { - picoos_uint8 set; /* TRUE if class set, FALSE otherwise */ - picoos_uint16 class; -} picokdt_classify_result_t; - - -/* maximum number of output values the tree output is mapped to */ -#define PICOKDT_MAXSIZE_OUTVEC 8 - -typedef struct { - picoos_uint8 nr; /* 0 if no class set, nr of values set otherwise */ - picoos_uint16 classvec[PICOKDT_MAXSIZE_OUTVEC]; -} picokdt_classify_vecresult_t; - - -/* ************************************************************/ -/* decision tree functions */ -/* ************************************************************/ - -/* constructInVec: - for every tree type there is a constructInVec function to construct - the size-optimized input vector for the tree using the input map - tables that are part of the decistion tree knowledge base. The - constructed input vector is stored in the tree object (this->invec - and this->inveclen) and will be used in the following call to the - classify function. - - classify: - for every tree type there is a classify function to apply the - decision tree to the previously constructed input vector. The - size-optimized, encoded output is stored in the tree object - (this->outval) and will be used in the following call to the - decompose function. Where needed (hitory attribute) the direct tree - output is returned by the classify function in a variable. - - decomposeOutClass: - for every tree type there is a decompose function to decompose the - size-optimized, encoded tree output and map it to the outside the - tree usable class value. -*/ - - -/* ************************************************************/ -/* decision tree defines */ -/* ************************************************************/ - -/* to construct the input vectors several hard-coded values are used - to handle attributes that, at the given position, are outside the - context. */ - -/* graph attributes: values to be used if the graph attribute is - outside the grapheme string (ie. word) */ -#define PICOKDT_OUTSIDEGRAPH_DEFCH (picoos_uint8)'\x30' /* ascii "0" */ -#define PICOKDT_OUTSIDEGRAPH_DEFSTR (picoos_uint8 *)"\x30" /* ascii "0" */ -#define PICOKDT_OUTSIDEGRAPH_DEFLEN 1 - -/* graph attributes (special case for g2p): values to be used if the - graph attribute is directly outside the grapheme string (ie. at the - word boundary word). Use PICOKDT_OUTSIDEGRAPH_DEF* if further - outside. */ -#define PICOKDT_OUTSIDEGRAPH_EOW_DEFCH (picoos_uint8)'\x31' /* ascii "1" */ -#define PICOKDT_OUTSIDEGRAPH_EOW_DEFSTR (picoos_uint8 *)"\x31" /* ascii "1" */ -#define PICOKDT_OUTSIDEGRAPH_EOW_DEFLEN 1 - -/* byte and word type attributes: value to be used if a byte or word - attribute is outside the context, e.g. for POS */ -#define PICOKDT_EPSILON 7 - -/* byte and word type attributes: for attribute with history info a - 'zero' value is needed when starting the sequence of predictions. - Use the following value to initialize history. Note that the direct - tree outputs (not mapped with output map table) of previous - predictions need to be used when constructing the input vector for - a following prediction. This direct tree output will then be mapped - together with the rest of the input vector by the input map - table. */ -#define PICOKDT_HISTORY_ZERO 30000 - - -/* ************************************************************/ -/* decision tree POS prediction (PosP) functions */ -/* ************************************************************/ - -/* construct a POS prediction input vector - tree input vector: 0-3 prefix UTF8 graphemes - 4-9 suffex UTF8 graphemes - 10 special grapheme existence flag (TRUE/FALSE) - 11 number of graphemes - graph: the grapheme string of the word for wich POS will be predicted - graphlen: length of graph in number of bytes - specgraphflag: existence of a special grapheme boolean - returns: TRUE if okay, FALSE otherwise - note: use PICOKDT_OUTSIDEGRAPH* for att values outside context -*/ -picoos_uint8 picokdt_dtPosPconstructInVec(const picokdt_DtPosP this, - const picoos_uint8 *graph, - const picoos_uint16 graphlen, - const picoos_uint8 specgraphflag); - - -/* classify a previously constructed input vector using tree 'this' - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtPosPclassify(const picokdt_DtPosP this); - -/* decompose the tree output and return the class in dtres - dtres: POS or POSgroup ID classification result - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtPosPdecomposeOutClass(const picokdt_DtPosP this, - picokdt_classify_result_t *dtres); - - -/* ************************************************************/ -/* decision tree POS disambiguation (PosD) functions */ -/* ************************************************************/ - -/* construct a POS disambiguation input vector (run in left-to-right mode) - tree input vector: 0-2 POS or POSgroup for each of the three previous words - 3 POSgroup for current word - 4-6 POS or POSgroup (can be history) for each of - the three following words - pre3 - pre1: POSgroup or POS for the previous three words - src: POSgroup of current word (if unique POS no posdisa possible) - fol1 - fol3: POS or history for the following three words (the more - complicated the better... :-( NEEDS TO BE uint16 - ishist1-ishist3: flag to indicate if fol1-3 are predicted tree - output values (history) or the HISTORY_ZERO (TRUE) - or an already unambiguous POS (FALSE) - returns: TRUE if okay, FALSE otherwise - note: use PICOKDT_EPSILON for att values outside context, - if POS in fol* unique use this POS instead of real - history, use reverse output mapping in these cases -*/ -picoos_uint8 picokdt_dtPosDconstructInVec(const picokdt_DtPosD this, - const picoos_uint16 * input); - - -/* classify a previously constructed input vector using tree 'this' - treeout: direct tree output value - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtPosDclassify(const picokdt_DtPosD this, - picoos_uint16 *treeout); - -/* decompose the tree output and return the class in dtres - dtres: POS classification result - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtPosDdecomposeOutClass(const picokdt_DtPosD this, - picokdt_classify_result_t *dtres); - -/* convert (unique) POS index into corresponding tree output index */ -picoos_uint8 picokdt_dtPosDreverseMapOutFixed(const picokdt_DtPosD this, - const picoos_uint16 inval, - picoos_uint16 *outval, - picoos_uint16 *outfallbackval); - -/* ************************************************************/ -/* decision tree grapheme-to-phoneme (G2P) functions */ -/* ************************************************************/ - -/* construct a G2P input vector (run in right-to-left mode) - tree input vector: 0-8 the 4 previous, current, and 4 following graphemes - 9 POS - 10-11 vowel count and vowel ID - 12 primary stress flag (TRUE/FALSE) - 13-15 the three following phones predicted - graph: the grapheme string used to determine invec[0:8] - graphlen: length of graph in number of bytes - count: the grapheme number for which invec will be constructed [0..] - pos: the part of speech of the word - nrvow number of vowel-like graphemes in graph if vowel, - set to 0 otherwise - ordvow order of 'count' vowel in graph if vowel, - set to 0 otherwise - primstressflag: flag indicating if primary stress was already predicted - phonech1-3: the three following phon chunks predicted (right-to-left) - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtG2PconstructInVec(const picokdt_DtG2P this, - const picoos_uint8 *graph, - const picoos_uint16 graphlen, - const picoos_uint8 count, - const picoos_uint8 pos, - const picoos_uint8 nrvow, - const picoos_uint8 ordvow, - picoos_uint8 *primstressflag, - const picoos_uint16 phonech1, - const picoos_uint16 phonech2, - const picoos_uint16 phonech3); - -/* classify a previously constructed input vector using tree 'this' - treeout: direct tree output value - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtG2Pclassify(const picokdt_DtG2P this, - picoos_uint16 *treeout); - -/* decompose the tree output and return the class vector in dtvres - dtvres: phones vector classification result - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtG2PdecomposeOutClass(const picokdt_DtG2P this, - picokdt_classify_vecresult_t *dtvres); - - -/* ************************************************************/ -/* decision tree phrasing (PHR) functions */ -/* ************************************************************/ - -/* construct a PHR input vector (run in right-to-left mode) - tree input vector: 0-1 POS for each of the two previous words - 2 POS for current word - 3-4 POS for each of the two following words - 5 nr words left - 6 nr words right - 7 nr syllables right - pre2 - pre1: POS for the previous two words - src: POS of current word - fol1 - fol2: POS for the following two words - nrwordspre: number of words left (previous) of current word - nrwordsfol: number of words right (following) of current word, - incl. current word, up to next BOUND (also - considering previously predicted PHR2/3) - nrsyllsfol: number of syllables right (following) of current word, - incl. syllables of current word, up to next BOUND - (also considering previously predicted PHR2/3) - returns: TRUE if okay, FALSE otherwise - note: use PICOKDT_EPSILON for att values outside context -*/ -picoos_uint8 picokdt_dtPHRconstructInVec(const picokdt_DtPHR this, - const picoos_uint8 pre2, - const picoos_uint8 pre1, - const picoos_uint8 src, - const picoos_uint8 fol1, - const picoos_uint8 fol2, - const picoos_uint16 nrwordspre, - const picoos_uint16 nrwordsfol, - const picoos_uint16 nrsyllsfol); - -/* classify a previously constructed input vector using tree 'this' - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtPHRclassify(const picokdt_DtPHR this); - -/* decompose the tree output and return the class vector in dtres - dtres: phrasing classification result - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtPHRdecomposeOutClass(const picokdt_DtPHR this, - picokdt_classify_result_t *dtres); - - -/* ************************************************************/ -/* decision tree accentuation (ACC) functions */ -/* ************************************************************/ - -/* construct an ACC input vector (run in right-to-left mode) - tree input vector: 0-1 POS for each of the two previous words - 2 POS for current word - 3-4 POS for each of the two following words - 5-6 history values (already predicted following) - 7 nr words left (previous) to any bound - 8 nr syllables left to any bound - 9 nr words right (following) to any bound - 10 nr syllables right to any bound - 11 nr words right to predicted "1" prominence (foot) - 12 nr syllables right to predicted "1" prominence (foot) - pre2 - pre1: POS for the previous two words - src: POS of current word - fol1 - fol2: POS for the following two words - hist1 - hist2: previously predicted ACC values - nrwordspre: number of words left (previous) of current word - nrsyllspre: number of syllables left (previous) of current word, - incl. initial non-prim stress syllables of current word - nrwordsfol: number of words right (following) of current word, - incl. current word, up to next BOUND (any strength != 0) - nrsyllsfol: number of syllables right (following) of current word, - incl. syllables of current word starting with prim. stress - syllable - footwordsfol: nr of words to the following prominence '1' - footsyllspre: nr of syllables to the previous prominence '1' - returns: TRUE if okay, FALSE otherwise - note: use PICOKDT_EPSILON for att 0-4 values outside context -*/ -picoos_uint8 picokdt_dtACCconstructInVec(const picokdt_DtACC this, - const picoos_uint8 pre2, - const picoos_uint8 pre1, - const picoos_uint8 src, - const picoos_uint8 fol1, - const picoos_uint8 fol2, - const picoos_uint16 hist1, - const picoos_uint16 hist2, - const picoos_uint16 nrwordspre, - const picoos_uint16 nrsyllspre, - const picoos_uint16 nrwordsfol, - const picoos_uint16 nrsyllsfol, - const picoos_uint16 footwordsfol, - const picoos_uint16 footsyllsfol); - -/* classify a previously constructed input vector using tree 'this' - treeout: direct tree output value - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtACCclassify(const picokdt_DtACC this, - picoos_uint16 *treeout); - -/* decompose the tree output and return the class vector in dtres - dtres: phrasing classification result - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtACCdecomposeOutClass(const picokdt_DtACC this, - picokdt_classify_result_t *dtres); - - -/* ************************************************************/ -/* decision tree phono-acoustical model (PAM) functions */ -/* ************************************************************/ - -/* construct a Pam input vector and store the tree-specific encoded - input vector in the tree object. - vec: tree input vector, 60 single-byte-sized attributes - veclen: length of vec in number of bytes - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtPAMconstructInVec(const picokdt_DtPAM this, - const picoos_uint8 *vec, - const picoos_uint8 veclen); - -/* classify a previously constructed input vector using tree 'this' - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtPAMclassify(const picokdt_DtPAM this); - -/* decompose the tree output and return the class in dtres - dtres: phones vector classification result - returns: TRUE if okay, FALSE otherwise -*/ -picoos_uint8 picokdt_dtPAMdecomposeOutClass(const picokdt_DtPAM this, - picokdt_classify_result_t *dtres); - -#ifdef __cplusplus -} -#endif - - - -#endif /*PICOKDT_H_*/ diff --git a/lib/picokfst.c b/lib/picokfst.c deleted file mode 100644 index 560709c..0000000 --- a/lib/picokfst.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - * 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 picokfst.c - * - * FST knowledge loading and access - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -#include "picoos.h" -#include "picodbg.h" -#include "picoknow.h" -#include "picokfst.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -#define FileHdrSize 4 /* size of FST file header */ - - - -/* ************************************************************/ -/* function to create specialized kb, */ -/* to be used by picorsrc only */ -/* ************************************************************/ - -/** object : FSTKnowledgeBase - * shortcut : kfst - * derived from : picoknow_KnowledgeBase - */ - -typedef struct kfst_subobj * kfst_SubObj; - -typedef struct kfst_subobj{ - picoos_uint8 * fstStream; /* the byte stream base address */ - picoos_int32 hdrLen; /* length of file header */ - picoos_int32 transductionMode; /* transduction mode to be used for FST */ - picoos_int32 nrClasses; /* nr of pair/transition classes in FST; class is in [1..nrClasses] */ - picoos_int32 nrStates; /* nr of states in FST; state is in [1..nrState] */ - picoos_int32 termClass; /* pair class of terminator symbol pair; probably obsolete */ - picoos_int32 alphaHashTabSize; /* size of pair alphabet hash table */ - picoos_int32 alphaHashTabPos; /* absolute address of the start of the pair alphabet */ - picoos_int32 transTabEntrySize; /* size in bytes of each transition table entry */ - picoos_int32 transTabPos; /* absolute address of the start of the transition table */ - picoos_int32 inEpsStateTabPos; /* absolute address of the start of the input epsilon transition table */ - picoos_int32 accStateTabPos; /* absolute address of the table of accepting states */ -} kfst_subobj_t; - - - -/* ************************************************************/ -/* primitives for reading from byte stream */ -/* ************************************************************/ - -/* Converts 'nrBytes' bytes starting at position '*pos' in byte stream 'stream' into unsigned number 'num'. - '*pos' is modified to the position right after the number */ -static void FixedBytesToUnsignedNum (picoos_uint8 * stream, picoos_uint8 nrBytes, picoos_uint32 * pos, picoos_uint32 * num) -{ - picoos_int32 i; - - (*num) = 0; - for (i = 0; i < nrBytes; i++) { - (*num) = ((*num) << 8) + (picoos_uint32)stream[*pos]; - (*pos)++; - } -} - - -/* Converts 'nrBytes' bytes starting at position '*pos' in byte stream 'stream' into signed number 'num'. - '*pos' is modified to the position right after the number */ -static void FixedBytesToSignedNum (picoos_uint8 * stream, picoos_uint8 nrBytes, picoos_uint32 * pos, picoos_int32 * num) -{ - picoos_int32 i; - picoos_uint32 val; - - val = 0; - for (i = 0; i < nrBytes; i++) { - val = (val << 8) + (picoos_uint32)stream[*pos]; - (*pos)++; - } - if (val % 2 == 1) { - /* negative number */ - (*num) = -((picoos_int32)((val - 1) / 2)) - 1; - } else { - /* positive number */ - (*num) = val / 2; - } -} - - -/* Converts varying-sized sequence of bytes starting at position '*pos' in byte stream 'stream' - into (signed) number 'num'. '*pos' is modified to the position right after the number. */ -static void BytesToNum (picoos_uint8 * stream, picoos_uint32 * pos, picoos_int32 * num) -{ - picoos_uint32 val; - picoos_uint32 b; - - val = 0; - b = (picoos_uint32)stream[*pos]; - (*pos)++; - while (b < 128) { - val = (val << 7) + b; - b = (picoos_uint32)stream[*pos]; - (*pos)++; - } - val = (val << 7) + (b - 128); - if (val % 2 == 1) { - /* negative number */ - (*num) = -((picoos_int32)((val - 1) / 2)) - 1; - } else { - /* positive number */ - (*num) = val / 2; - } -} - - -/* ************************************************************/ -/* setting up FST from byte stream */ -/* ************************************************************/ - -static pico_status_t kfstInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) -{ - picoos_uint32 curpos; - picoos_int32 offs; - kfst_subobj_t * kfst; - - PICODBG_DEBUG(("kfstInitialize -- start\n")); - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, NULL, - NULL); - } - kfst = (kfst_subobj_t *) this->subObj; - - /* +CT+ */ - kfst->fstStream = this->base; - PICODBG_TRACE(("base: %d\n",this->base)); - kfst->hdrLen = FileHdrSize; - curpos = kfst->hdrLen; - BytesToNum(kfst->fstStream,& curpos,& kfst->transductionMode); - BytesToNum(kfst->fstStream,& curpos,& kfst->nrClasses); - BytesToNum(kfst->fstStream,& curpos,& kfst->nrStates); - BytesToNum(kfst->fstStream,& curpos,& kfst->termClass); - BytesToNum(kfst->fstStream,& curpos,& kfst->alphaHashTabSize); - BytesToNum(kfst->fstStream,& curpos,& offs); - kfst->alphaHashTabPos = kfst->hdrLen + offs; - BytesToNum(kfst->fstStream,& curpos,& kfst->transTabEntrySize); - BytesToNum(kfst->fstStream,& curpos,& offs); - kfst->transTabPos = kfst->hdrLen + offs; - BytesToNum(kfst->fstStream,& curpos,& offs); - kfst->inEpsStateTabPos = kfst->hdrLen + offs; - BytesToNum(kfst->fstStream,& curpos,& offs); - kfst->accStateTabPos = kfst->hdrLen + offs; - /* -CT- */ - - return PICO_OK; -} - - -static pico_status_t kfstSubObjDeallocate(register picoknow_KnowledgeBase this, - picoos_MemoryManager mm) -{ - if (NULL != this) { - picoos_deallocate(mm, (void *) &this->subObj); - } - return PICO_OK; -} - - -/* calculates a small number of data (e.g. addresses) from kb for fast access. - * This data is encapsulated in a picokfst_FST that can later be retrieved - * with picokfst_getFST. */ -pico_status_t picokfst_specializeFSTKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common) -{ - pico_status_t status; - - if (NULL == this) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, NULL, NULL); - } - if (0 < this->size) { - /* not a dummy kb */ - this->subDeallocate = kfstSubObjDeallocate; - - this->subObj = picoos_allocate(common->mm, sizeof(kfst_subobj_t)); - - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); - } - status = kfstInitialize(this, common); - if (PICO_OK != status) { - picoos_deallocate(common->mm,(void **)&this->subObj); - } - } - return PICO_OK; -} - - -/* ************************************************************/ -/* FST type and getFST function */ -/* ************************************************************/ - - - -/* return kb FST for usage in PU */ -picokfst_FST picokfst_getFST(picoknow_KnowledgeBase this) -{ - if (NULL == this) { - return NULL; - } else { - return (picokfst_FST) this->subObj; - } -} - - - -/* ************************************************************/ -/* FST access methods */ -/* ************************************************************/ - - -/* see description in header file */ -extern picoos_uint8 picokfst_kfstGetTransductionMode(picokfst_FST this) -{ - kfst_SubObj fst = (kfst_SubObj) this; - if (fst != NULL) { - return fst->transductionMode; - } else { - return 0; - } -} - - -/* see description in header file */ -extern void picokfst_kfstGetFSTSizes (picokfst_FST this, picoos_int32 *nrStates, picoos_int32 *nrClasses) -{ - kfst_SubObj fst = (kfst_SubObj) this; - if (fst != NULL) { - *nrStates = fst->nrStates; - *nrClasses = fst->nrClasses; - } else { - *nrStates = 0; - *nrClasses = 0; - } -} - -/* see description in header file */ -extern void picokfst_kfstStartPairSearch (picokfst_FST this, picokfst_symid_t inSym, - picoos_bool * inSymFound, picoos_int32 * searchState) -{ - picoos_uint32 pos; - picoos_int32 offs; - picoos_int32 h; - picoos_int32 inSymCellPos; - picoos_int32 inSymX; - picoos_int32 nextSameHashInSymOffs; - - kfst_SubObj fst = (kfst_SubObj) this; - (*searchState) = -1; - (*inSymFound) = 0; - h = inSym % fst->alphaHashTabSize; - pos = fst->alphaHashTabPos + (h * 4); - FixedBytesToSignedNum(fst->fstStream,4,& pos,& offs); - if (offs > 0) { - inSymCellPos = fst->alphaHashTabPos + offs; - pos = inSymCellPos; - BytesToNum(fst->fstStream,& pos,& inSymX); - BytesToNum(fst->fstStream,& pos,& nextSameHashInSymOffs); - while ((inSymX != inSym) && (nextSameHashInSymOffs > 0)) { - inSymCellPos = inSymCellPos + nextSameHashInSymOffs; - pos = inSymCellPos; - BytesToNum(fst->fstStream,& pos,& inSymX); - BytesToNum(fst->fstStream,& pos,& nextSameHashInSymOffs); - } - if (inSymX == inSym) { - /* input symbol found; state is set to position after symbol cell */ - (*searchState) = pos; - (*inSymFound) = 1; - } - } -} - - -/* see description in header file */ -extern void picokfst_kfstGetNextPair (picokfst_FST this, picoos_int32 * searchState, - picoos_bool * pairFound, - picokfst_symid_t * outSym, picokfst_class_t * pairClass) -{ - picoos_uint32 pos; - picoos_int32 val; - - kfst_SubObj fst = (kfst_SubObj) this; - if ((*searchState) < 0) { - (*pairFound) = 0; - (*outSym) = PICOKFST_SYMID_ILLEG; - (*pairClass) = -1; - } else { - pos = (*searchState); - BytesToNum(fst->fstStream,& pos,& val); - *outSym = (picokfst_symid_t)val; - if ((*outSym) != PICOKFST_SYMID_ILLEG) { - BytesToNum(fst->fstStream,& pos,& val); - *pairClass = (picokfst_class_t)val; - (*pairFound) = 1; - (*searchState) = pos; - } else { - (*pairFound) = 0; - (*outSym) = PICOKFST_SYMID_ILLEG; - (*pairClass) = -1; - (*searchState) = -1; - } - } -} - - - -/* see description in header file */ -extern void picokfst_kfstGetTrans (picokfst_FST this, picokfst_state_t startState, picokfst_class_t transClass, - picokfst_state_t * endState) -{ - - picoos_uint32 pos; - picoos_int32 index; - picoos_uint32 endStateX; - - kfst_SubObj fst = (kfst_SubObj) this; - if ((startState < 1) || (startState > fst->nrStates) || (transClass < 1) || (transClass > fst->nrClasses)) { - (*endState) = 0; - } else { - index = (startState - 1) * fst->nrClasses + transClass - 1; - pos = fst->transTabPos + (index * fst->transTabEntrySize); - FixedBytesToUnsignedNum(fst->fstStream,fst->transTabEntrySize,& pos,& endStateX); - (*endState) = endStateX; - } -} - - -/* see description in header file */ -extern void picokfst_kfstStartInEpsTransSearch (picokfst_FST this, picokfst_state_t startState, - picoos_bool * inEpsTransFound, picoos_int32 * searchState) -{ - - picoos_int32 offs; - picoos_uint32 pos; - - kfst_SubObj fst = (kfst_SubObj) this; - (*searchState) = -1; - (*inEpsTransFound) = 0; - if ((startState > 0) && (startState <= fst->nrStates)) { - pos = fst->inEpsStateTabPos + (startState - 1) * 4; - FixedBytesToSignedNum(fst->fstStream,4,& pos,& offs); - if (offs > 0) { - (*searchState) = fst->inEpsStateTabPos + offs; - (*inEpsTransFound) = 1; - } - } -} - - - -/* see description in header file */ -extern void picokfst_kfstGetNextInEpsTrans (picokfst_FST this, picoos_int32 * searchState, - picoos_bool * inEpsTransFound, - picokfst_symid_t * outSym, picokfst_state_t * endState) -{ - picoos_uint32 pos; - picoos_int32 val; - - kfst_SubObj fst = (kfst_SubObj) this; - if ((*searchState) < 0) { - (*inEpsTransFound) = 0; - (*outSym) = PICOKFST_SYMID_ILLEG; - (*endState) = 0; - } else { - pos = (*searchState); - BytesToNum(fst->fstStream,& pos,& val); - *outSym = (picokfst_symid_t)val; - if ((*outSym) != PICOKFST_SYMID_ILLEG) { - BytesToNum(fst->fstStream,& pos,& val); - *endState = (picokfst_state_t)val; - (*inEpsTransFound) = 1; - (*searchState) = pos; - } else { - (*inEpsTransFound) = 0; - (*outSym) = PICOKFST_SYMID_ILLEG; - (*endState) = 0; - (*searchState) = -1; - } - } -} - - -/* see description in header file */ -extern picoos_bool picokfst_kfstIsAcceptingState (picokfst_FST this, picokfst_state_t state) -{ - - picoos_uint32 pos; - picoos_uint32 val; - - kfst_SubObj fst = (kfst_SubObj) this; - if ((state > 0) && (state <= fst->nrStates)) { - pos = fst->accStateTabPos + (state - 1); - FixedBytesToUnsignedNum(fst->fstStream,1,& pos,& val); - return (val == 1); - } else { - return 0; - } -} - -#ifdef __cplusplus -} -#endif - -/* End picofst.c */ diff --git a/lib/picokfst.h b/lib/picokfst.h deleted file mode 100644 index b391013..0000000 --- a/lib/picokfst.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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 picokfst.h - * - * FST knowledge loading and access - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -#ifndef PICOKFST_H_ -#define PICOKFST_H_ - -#include "picodefs.h" -#include "picodbg.h" -#include "picoos.h" -#include "picoknow.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -typedef picoos_int16 picokfst_symid_t; /* type of symbol identifiers */ -typedef picoos_int16 picokfst_class_t; /* type of symbol pair classes */ -typedef picoos_int16 picokfst_state_t; /* type of states */ - -#define PICOKFST_SYMID_EPS (picokfst_symid_t) 0 /* epsilon symbol id */ -#define PICOKFST_SYMID_ILLEG (picokfst_symid_t) -1 /* illegal symbol id */ - -/** - * @addtogroup picokfst - * - * Mapping of values to FST symbol id (relevant for compiling the FST) \n - * Value FST symbol id \n - * -------------------------------------- \n - * phoneme_id -> phoneme_id + 256 * PICOKFST_PLANE_PHONEMES \n - * accentlevel_id -> accentlevel_id + 256 * PICOKFST_PLANE_ACCENTS \n - * POS_id -> POS_id + 256 * PICOKFST_PLANE_POS \n - * pb_strength_id -> pb_strength_id + 256 * PICOKFST_PLANE_PB_STRENGTHS \n - * phon_term_id -> phon_term_id + 256 * PICOKFST_PLANE_INTERN \n -*/ -enum picokfst_symbol_plane { - PICOKFST_PLANE_PHONEMES = 0, /* phoneme plane */ - PICOKFST_PLANE_ASCII = 1, /* "ascii" plane (values > 127 may be used internally) */ - PICOKFST_PLANE_XSAMPA = 2, /* x-sampa primitives plane (pico-specific table) */ - PICOKFST_PLANE_ACCENTS = 4, /* accent plane */ - PICOKFST_PLANE_POS = 5, /* part of speech plane */ - PICOKFST_PLANE_PB_STRENGTHS = 6, /* phrase boundary strength plane */ - PICOKFST_PLANE_INTERN = 7 /* internal plane, e.g. phonStartId, phonTermId */ -}; - -/* to be used as bit set, e.g. - * picoos_uint8 transductionMode = PICOKFST_TRANSMODE_NEWSYMS | PICOKFST_TRANSMODE_POSUSED; - */ -enum picofst_transduction_mode { - PICOKFST_TRANSMODE_NEWSYMS = 1, /* e.g. {#WB},{#PB-S},{#PB-W},{#ACC0},{#ACC1},{#ACC2},{#ACC3}, */ - PICOKFST_TRANSMODE_POSUSED = 2 /* FST contains Part Of Speech symbols */ - -}; - - -/* ************************************************************/ -/* function to create specialized kb, */ -/* to be used by knowledge layer (picorsrc) only */ -/* ************************************************************/ - -/* calculates a small number of data (e.g. addresses) from kb for fast access. - * This data is encapsulated in a picokfst_FST that can later be retrieved - * with picokfst_getFST. */ -pico_status_t picokfst_specializeFSTKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common); - - -/* ************************************************************/ -/* FST type and getFST function */ -/* ************************************************************/ - -/* FST type */ -typedef struct picokfst_fst * picokfst_FST; - -/* return kb FST for usage in PU */ -picokfst_FST picokfst_getFST(picoknow_KnowledgeBase this); - - -/* ************************************************************/ -/* FST access methods */ -/* ************************************************************/ - -/* returns transduction mode specified with rule sources; - result to be interpreted as set of picofst_transduction_mode */ -picoos_uint8 picokfst_kfstGetTransductionMode(picokfst_FST this); - -/* returns number of states and number of pair classes in FST; - legal states are 1..nrStates, legal classes are 1..nrClasses */ -void picokfst_kfstGetFSTSizes (picokfst_FST this, picoos_int32 *nrStates, picoos_int32 *nrClasses); - -/* starts search for all pairs with input symbol 'inSym'; '*inSymFound' returns whether - such pairs exist at all; '*searchState' returns a search state to be used in - subsequent calls to function 'picokfst_kfstGetNextPair', which must be used - to get the symbol pairs */ -void picokfst_kfstStartPairSearch (picokfst_FST this, picokfst_symid_t inSym, - picoos_bool * inSymFound, picoos_int32 * searchState); - -/* gets next pair for input symbol specified with preceding call to 'picokfst_kfstStartPairSearch'; - '*searchState' maintains the search state, 'pairFound' returns whether any more pair was found, - '*outSym' returns the output symbol of the found pair, and '*pairClass' returns the - transition class of the found symbol pair */ -void picokfst_kfstGetNextPair (picokfst_FST this, picoos_int32 * searchState, - picoos_bool * pairFound, - picokfst_symid_t * outSym, picokfst_class_t * pairClass); - -/* attempts to do FST transition from state 'startState' with pair class 'transClass'; - if such a transition exists, 'endState' returns the end state of the transition (> 0), - otherwise 'endState' returns <= 0 */ -void picokfst_kfstGetTrans (picokfst_FST this, picokfst_state_t startState, picokfst_class_t transClass, - picokfst_state_t * endState); - -/* starts search for all pairs with input epsilon symbol and all correponding - FST transitions starting in state 'startState'; to be used for fast - computation of epsilon closures; - '*inEpsTransFound' returns whether any such transition was found at all; - if so, '*searchState' returns a search state to be used in subsequent calls - to 'picokfst_kfstGetNextInEpsTrans' */ -void picokfst_kfstStartInEpsTransSearch (picokfst_FST this, picokfst_state_t startState, - picoos_bool * inEpsTransFound, picoos_int32 * searchState); - -/* gets next FST transition with a pair with empty input symbol starting from a state - previoulsy specified in 'picokfst_kfstStartInEpsTransSearch'; - '*searchState' maintains the search state, '*inEpsTransFound' returns - whether a new transition with input epsilon was found, '*outSym 'returns - the output symbol of the found pair, and '*endState' returns the end state - of the found transition with that pair */ -void picokfst_kfstGetNextInEpsTrans (picokfst_FST this, picoos_int32 * searchState, - picoos_bool * inEpsTransFound, - picokfst_symid_t * outSym, picokfst_state_t * endState); - -/* returns whether 'state' is an accepting state of FST; originally, only - state 1 was an accepting state; however, in order to remove the need to - always do a last transition with a termination symbol pair, this function - defines a state as an accepting state if there is transition to state 1 - with the terminator symbol pair */ -picoos_bool picokfst_kfstIsAcceptingState (picokfst_FST this, picokfst_state_t state); - -#ifdef __cplusplus -} -#endif - - -#endif /*PICOKFST_H_*/ diff --git a/lib/picoklex.c b/lib/picoklex.c deleted file mode 100644 index 7ff0a33..0000000 --- a/lib/picoklex.c +++ /dev/null @@ -1,572 +0,0 @@ -/* - * 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 picoklex.c - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -#include "picoos.h" -#include "picodbg.h" -#include "picodata.h" -#include "picoknow.h" -#include "picoklex.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -/* ************************************************************/ -/* lexicon */ -/* ************************************************************/ - -/** - * @addtogroup picolex - * - overview: - - lex consists of optional searchindex and a non-empty list of lexblocks - - lexblocks are fixed size, at the start of a block there is also the - start of an entry - - using the searchindex a unambiguous lexblock can be determined which - contains the entry (or there is no entry) - - one lex entry has POS GRAPH PHON, all mandatory, but - - PHON can be empty string -> no pronunciation in the resulting TTS output - - PHON can be :G2P -> use G2P later to add pronunciation - - (POS,GRAPH) is a uniq key (only one entry allowed) - - (GRAPH) is almost a uniq key (2-4 entries with the same GRAPH, and - differing POS and differing PHON possible) - - for one graph we can have two or three solutions from the lex - which all need to be passed on the the next PU - - in this case GRAPH, POS, and PHON all must be available in lex - - sizing: - - 3 bytes entry index -> 16MB addressable - - 2 bytes searchindex nr -> 64K blocks possible - - 5 bytes per searchindex entry - - 3 bytes for graph-prefix - - 2 bytes blockadr in searchindex -> 64K blocks possible - - lexblock size 512B: - - 32M possible - - with ~20 bytes per entry - -> max. average of ~26 entries to be searched per lookup - - overhead of ~10 bytes per block to sync with - block boundaries - - examples: - - 500KB lex -> 1000 blocks, - 1000 entries in searchindex, ~25.6K lex-entries, - - ~5KB searchindex - ~10KB overhead for block sync - - 100KB lex -> 200 blocks, - 200 entries in searchindex, ~5.1K lex-entries, - - ~1KB searchindex - ~2KB overhead for block sync - - pil-file: lexicon knowledge base in binary form - - lex-kb = content - - content = searchindex {lexblock}1:NRBLOCKS2 - - lexblock = {lexentry}1: (lexblock size is fixed 512Bytes) - - searchindex = NRBLOCKS2 {GRAPH1 GRAPH1 GRAPH1 LEXBLOCKIND2}=NRBLOCKS2 - - lexentry = LENGRAPH1 {GRAPH1}=LENGRAPH1-1 - LENPOSPHON1 POS1 {PHON1}=LENPOSPHON1-2 - - - special cases: - - PHON is empty string (no pronunciation in the resulting TTS output): - lexentry = LENGRAPH1 {GRAPH1}=LENGRAPH1-1 2 POS1 - - PHON can be :G2P -> use G2P later to add pronunciation: - lexentry = LENGRAPH1 {GRAPH1}=LENGRAPH1-1 3 POS1 - - multi-byte values always little endian -*/ - - -/* ************************************************************/ -/* lexicon data defines */ -/* may not be changed with current implementation */ -/* ************************************************************/ - -/* nr bytes of nrblocks info */ -#define PICOKLEX_LEX_NRBLOCKS_SIZE 2 - -/* search index entry: - nr graphs - - nr bytes of block index - - nr bytes per entry, NRGRAPHS*INDSIZE */ -#define PICOKLEX_LEX_SIE_NRGRAPHS 3 -#define PICOKLEX_LEX_SIE_INDSIZE 2 -#define PICOKLEX_LEX_SIE_SIZE 5 - -/* nr of bytes per lexblock */ -#define PICOKLEX_LEXBLOCK_SIZE 512 - - -/* reserved values in klex to indicate :G2P needed for a lexentry */ -#define PICOKLEX_NEEDS_G2P 5 - - -/* ************************************************************/ -/* lexicon type and loading */ -/* ************************************************************/ - -/** object : LexKnowledgeBase - * shortcut : klex - * derived from : picoknow_KnowledgeBase - */ - -typedef struct klex_subobj *klex_SubObj; - -typedef struct klex_subobj -{ - picoos_uint16 nrblocks; /* nr lexblocks = nr eles in searchind */ - picoos_uint8 *searchind; - picoos_uint8 *lexblocks; -} klex_subobj_t; - - -static pico_status_t klexInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) -{ - picoos_uint32 curpos = 0; - klex_subobj_t *klex; - - PICODBG_DEBUG(("start")); - - /* check whether (this->size != 0) done before calling this function */ - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - klex = (klex_subobj_t *) this->subObj; - - if (PICO_OK == picoos_read_mem_pi_uint16(this->base, &curpos, - &(klex->nrblocks))) { - if (klex->nrblocks > 0) { - PICODBG_DEBUG(("nr blocks: %i, curpos: %i", klex->nrblocks,curpos)); - klex->searchind = this->base + curpos; - } else { - klex->searchind = NULL; - } - klex->lexblocks = this->base + PICOKLEX_LEX_NRBLOCKS_SIZE + - (klex->nrblocks * (PICOKLEX_LEX_SIE_SIZE)); - return PICO_OK; - } else { - return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, - NULL, NULL); - } -} - - -static pico_status_t klexSubObjDeallocate(register picoknow_KnowledgeBase this, - picoos_MemoryManager mm) -{ - if (NULL != this) { - picoos_deallocate(mm, (void *) &this->subObj); - } - return PICO_OK; -} - - -/* we don't offer a specialized constructor for a LexKnowledgeBase but - * instead a "specializer" of an allready existing generic - * picoknow_KnowledgeBase */ - -pico_status_t picoklex_specializeLexKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common) -{ - if (NULL == this) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - if (this->size > 0) { - this->subDeallocate = klexSubObjDeallocate; - this->subObj = picoos_allocate(common->mm, sizeof(klex_subobj_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - return klexInitialize(this, common); - } else { - /* some dummy klex */ - return PICO_OK; - } -} - -/* for now we don't need to do anything special for the main lex */ -/* -pico_status_t picoklex_specializeMainLexKnowledgeBase( - picoknow_KnowledgeBase this, - picoos_Common common) -{ - return picoklex_specializeLexKnowledgeBase(this,common); -} -*/ - - -/* ************************************************************/ -/* lexicon getLex */ -/* ************************************************************/ - -picoklex_Lex picoklex_getLex(picoknow_KnowledgeBase this) -{ - if (NULL == this) { - return NULL; - } else { - return (picoklex_Lex) this->subObj; - } -} - - -/* ************************************************************/ -/* functions on searchindex */ -/* ************************************************************/ - - -static picoos_uint32 klex_getSearchIndexVal(const klex_SubObj this, - picoos_uint16 index) -{ - picoos_uint32 pos, val; - pos = index * PICOKLEX_LEX_SIE_SIZE; - val = this->searchind[pos]; - val = (val << 8) + this->searchind[pos + 1]; - val = (val << 8) + this->searchind[pos + 2]; - return val; -} - - -/* Determine first lexblock containing entries for specified - grapheme. */ - -static picoos_uint16 klex_getLexblockNr(const klex_SubObj this, - const picoos_uint8 *graphsi) { - /* graphsi is of len PICOKLEX_LEX_SI_NGRAPHS */ - picoos_int32 low, mid, high; - picoos_uint32 searchval, indval; - - /* PICOKLEX_LEX_SIE_NRGRAPHS */ - - /* convert graph-prefix to number with 'lexicographic' ordering */ - searchval = graphsi[0]; - searchval = (searchval << 8) + graphsi[1]; - searchval = (searchval << 8) + graphsi[2]; - - low = 0; - high = this->nrblocks; - - /* do binary search */ - while (low < high) { - mid = (low + high) / 2; - indval = klex_getSearchIndexVal(this, mid); - if (indval < searchval) { - low = mid + 1; - } else { - high = mid; - } - } - PICODBG_ASSERT(high == low); - /* low points to the first entry greater than or equal to searchval */ - - if (low < this->nrblocks) { - indval = klex_getSearchIndexVal(this, low); - if (indval > searchval) { - low--; - /* if there are identical elements in the search index we have - to move to the first one */ - if (low > 0) { - indval = klex_getSearchIndexVal(this, low); - while (indval == klex_getSearchIndexVal(this, low-1)) { - low--; - } - } - } - } else { - low = this->nrblocks - 1; - } - -#if defined(PICO_DEBUG) - { - picoos_uint32 pos = low * PICOKLEX_LEX_SIE_SIZE; - PICODBG_DEBUG(("binary search result is %c%c%c (%d)", - this->searchind[pos], this->searchind[pos + 1], - this->searchind[pos + 2], low)); - } -#endif - - return (picoos_uint16) low; -} - - -/* Determine number of adjacent lexblocks containing entries for - the same grapheme search prefix (identified by search index). */ - -static picoos_uint16 klex_getLexblockRange(const klex_SubObj this, - picoos_uint16 index) -{ - picoos_uint16 count; - picoos_uint32 sval1, sval2; - - sval1 = klex_getSearchIndexVal(this, index); - -#if defined(PICO_DEBUG) - /* 'index' must point to first lexblock of its kind */ - if (index > 0) { - sval2 = klex_getSearchIndexVal(this, index - 1); - PICODBG_ASSERT(sval1 != sval2); - } -#endif - - index++; - sval2 = klex_getSearchIndexVal(this, index); - - count = 1; - while (sval1 == sval2) { - count++; - index++; - sval2 = klex_getSearchIndexVal(this, index); - } - - return count; -} - - -/* ************************************************************/ -/* functions on single lexblock */ -/* ************************************************************/ - -static picoos_int8 klex_lexMatch(picoos_uint8 *lexentry, - const picoos_uint8 *graph, - const picoos_uint16 graphlen) { - picoos_uint8 i; - picoos_uint8 lexlen; - picoos_uint8 *lexgraph; - - lexlen = lexentry[0] - 1; - lexgraph = &(lexentry[1]); - for (i=0; (i graph[i]) { - return 1; - } - } - if (graphlen == lexlen) { - return 0; - } else if (lexlen < graphlen) { - return -1; - } else { - return 1; - } -} - - -static void klex_setLexResult(const picoos_uint8 *lexentry, - const picoos_uint32 lexpos, - picoklex_lexl_result_t *lexres) { - picoos_uint8 i; - - /* check if :G2P */ - if ((lexentry[lexentry[0] + 2]) == PICOKLEX_NEEDS_G2P) { - /* set pos */ - lexres->posind[0] = lexentry[lexentry[0] + 1]; - /* set rest */ - lexres->phonfound = FALSE; - lexres->posindlen = 1; - lexres->nrres = 1; - PICODBG_DEBUG(("result %d :G2P", lexres->nrres)); - } else { - i = lexres->nrres * (PICOKLEX_POSIND_SIZE); - lexres->posindlen += PICOKLEX_POSIND_SIZE; - lexres->phonfound = TRUE; - /* set pos */ - lexres->posind[i++] = lexentry[lexentry[0] + 1]; - /* set ind, PICOKLEX_IND_SIZE */ - lexres->posind[i++] = 0x000000ff & (lexpos); - lexres->posind[i++] = 0x000000ff & (lexpos >> 8); - lexres->posind[i] = 0x000000ff & (lexpos >> 16); - lexres->nrres++; - PICODBG_DEBUG(("result %d", lexres->nrres)); - } -} - - -static void klex_lexblockLookup(klex_SubObj this, - const picoos_uint32 lexposStart, - const picoos_uint32 lexposEnd, - const picoos_uint8 *graph, - const picoos_uint16 graphlen, - picoklex_lexl_result_t *lexres) { - picoos_uint32 lexpos; - picoos_int8 rv; - - lexres->nrres = 0; - - lexpos = lexposStart; - rv = -1; - while ((rv < 0) && (lexpos < lexposEnd)) { - - rv = klex_lexMatch(&(this->lexblocks[lexpos]), graph, graphlen); - - if (rv == 0) { /* found */ - klex_setLexResult(&(this->lexblocks[lexpos]), lexpos, lexres); - if (lexres->phonfound) { - /* look for more results, up to MAX_NRRES, don't even - check if more results would be available */ - while ((lexres->nrres < PICOKLEX_MAX_NRRES) && - (lexpos < lexposEnd)) { - lexpos += this->lexblocks[lexpos]; - lexpos += this->lexblocks[lexpos]; - /* if there are no more entries in this block, advance - to next block by skipping all zeros */ - while ((this->lexblocks[lexpos] == 0) && - (lexpos < lexposEnd)) { - lexpos++; - } - if (lexpos < lexposEnd) { - if (klex_lexMatch(&(this->lexblocks[lexpos]), graph, - graphlen) == 0) { - klex_setLexResult(&(this->lexblocks[lexpos]), - lexpos, lexres); - } else { - /* no more results, quit loop */ - lexpos = lexposEnd; - } - } - } - } else { - /* :G2P mark */ - } - } else if (rv < 0) { - /* not found, goto next entry */ - lexpos += this->lexblocks[lexpos]; - lexpos += this->lexblocks[lexpos]; - /* if there are no more entries in this block, advance - to next block by skipping all zeros */ - while ((this->lexblocks[lexpos] == 0) && (lexpos < lexposEnd)) { - lexpos++; - } - } else { - /* rv > 0, not found, won't show up later in block */ - } - } -} - - -/* ************************************************************/ -/* lexicon lookup functions */ -/* ************************************************************/ - -picoos_uint8 picoklex_lexLookup(const picoklex_Lex this, - const picoos_uint8 *graph, - const picoos_uint16 graphlen, - picoklex_lexl_result_t *lexres) { - picoos_uint16 lbnr, lbc; - picoos_uint32 lexposStart, lexposEnd; - picoos_uint8 i; - picoos_uint8 tgraph[PICOKLEX_LEX_SIE_NRGRAPHS]; - klex_SubObj klex = (klex_SubObj) this; - - if (NULL == klex) { - PICODBG_ERROR(("no lexicon loaded")); - /* no exception here needed, already checked at initialization */ - return FALSE; - } - - lexres->nrres = 0; - lexres->posindlen = 0; - lexres->phonfound = FALSE; - - for (i = 0; inrblocks) == 0) { - /* no searchindex, no lexblock */ - PICODBG_WARN(("no searchindex, no lexblock")); - return FALSE; - } else { - lbnr = klex_getLexblockNr(klex, tgraph); - PICODBG_ASSERT(lbnr < klex->nrblocks); - lbc = klex_getLexblockRange(klex, lbnr); - PICODBG_ASSERT((lbc >= 1) && (lbc <= klex->nrblocks)); - } - PICODBG_DEBUG(("lexblock nr: %d (#%d)", lbnr, lbc)); - - lexposStart = lbnr * PICOKLEX_LEXBLOCK_SIZE; - lexposEnd = lexposStart + lbc * PICOKLEX_LEXBLOCK_SIZE; - - PICODBG_DEBUG(("lookup start, lexpos range %d..%d", lexposStart,lexposEnd)); - klex_lexblockLookup(klex, lexposStart, lexposEnd, graph, graphlen, lexres); - PICODBG_DEBUG(("lookup done, %d found", lexres->nrres)); - - return (lexres->nrres > 0); -} - - -picoos_uint8 picoklex_lexIndLookup(const picoklex_Lex this, - const picoos_uint8 *ind, - const picoos_uint8 indlen, - picoos_uint8 *pos, - picoos_uint8 **phon, - picoos_uint8 *phonlen) { - picoos_uint32 pentry; - klex_SubObj klex = (klex_SubObj) this; - - /* check indlen */ - if (indlen != PICOKLEX_IND_SIZE) { - return FALSE; - } - - /* PICOKLEX_IND_SIZE */ - pentry = 0x000000ff & (ind[0]); - pentry |= ((picoos_uint32)(ind[1]) << 8); - pentry |= ((picoos_uint32)(ind[2]) << 16); - - /* check ind if it is within lexblocks byte stream, if not, return FALSE */ - if (pentry >= ((picoos_uint32)klex->nrblocks * PICOKLEX_LEXBLOCK_SIZE)) { - return FALSE; - } - - pentry += (klex->lexblocks[pentry]); - *phonlen = (klex->lexblocks[pentry++]) - 2; - *pos = klex->lexblocks[pentry++]; - *phon = &(klex->lexblocks[pentry]); - - PICODBG_DEBUG(("pentry: %d, phonlen: %d", pentry, *phonlen)); - return TRUE; -} - -#ifdef __cplusplus -} -#endif - - -/* end */ diff --git a/lib/picoklex.h b/lib/picoklex.h deleted file mode 100644 index e186393..0000000 --- a/lib/picoklex.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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 picoklex.h - * - * knowledge base: lexicon - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#ifndef PICOKLEX_H_ -#define PICOKLEX_H_ - -#include "picoos.h" -#include "picoknow.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* ************************************************************/ -/* function to create specialized kb, */ -/* to be used by picorsrc only */ -/* ************************************************************/ - -pico_status_t picoklex_specializeLexKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common); - - -/* ************************************************************/ -/* lexicon type and getLex function */ -/* ************************************************************/ - -/* lexicon type */ -typedef struct picoklex_lex * picoklex_Lex; - -/* return kb lex for usage in PU */ -picoklex_Lex picoklex_getLex(picoknow_KnowledgeBase this); - - -/* ************************************************************/ -/* lexicon lookup result type */ -/* ************************************************************/ - -/* max nr of results */ -#define PICOKLEX_MAX_NRRES 4 - -/* nr of bytes used for pos and index, needs to fit in uint32, ie. max 4 */ -#define PICOKLEX_POSIND_SIZE 4 -/* nr of bytes used for index, needs to fit in uint32, ie. max 4 */ -#define PICOKLEX_IND_SIZE 3 -/* max len (in bytes) of ind, (PICOKLEX_MAX_NRRES * PICOKLEX_POSIND_SIZE) */ -#define PICOKLEX_POSIND_MAXLEN 16 - - -/* the lexicon lookup result(s) are stored in field posind, which - contains a sequence of - POS1-byte, IND1-bytes, POS2-byte, IND2-bytes, etc. - - the IND-bytes are the byte position(s) in the lexblocks part of the - lexicon byte stream, starting at picoklex_lex_t.lexblocks. - - for lexentries without phones only the POS (there can be only one) - is stored in posind, nrres equals one, and phonfound is FALSE. -*/ - -typedef struct { - picoos_uint8 nrres; /* number of results, 0 of no entry found */ - picoos_uint8 posindlen; /* number of posind bytes */ - picoos_uint8 phonfound; /* phones found flag, TRUE if found */ - picoos_uint8 posind[PICOKLEX_POSIND_MAXLEN]; /* sequence of multi-ind, - one per result */ -} picoklex_lexl_result_t; - - -/* ************************************************************/ -/* lexicon lookup functions */ -/* ************************************************************/ - -/** lookup lex by graph; result(s) are in lexres, ie. the phones are - not returned directly (because they are used later and space can be - saved using indices first), lexres contains an index (or several) - to the entry for later fast lookup once the phones are needed. - PICOKLEX_IND_SIZE bytes are used for the index, these ind bytes are - saved in the WORDINDEX items. If at least one entry is found TRUE - is returned, FALSE otherwise */ -picoos_uint8 picoklex_lexLookup(const picoklex_Lex this, - const picoos_uint8 *graph, - const picoos_uint16 graphlen, - picoklex_lexl_result_t *lexres); - -/** lookup lex entry by index ind; ind is a sequence of bytes with - length indlen (must be equal PICOKLEX_IND_SIZE) that is the content - of a WORDINDEX item. Returns TRUE if okay, FALSE otherwise */ -picoos_uint8 picoklex_lexIndLookup(const picoklex_Lex this, - const picoos_uint8 *ind, - const picoos_uint8 indlen, - picoos_uint8 *pos, - picoos_uint8 **phon, - picoos_uint8 *phonlen); - -#ifdef __cplusplus -} -#endif - - -#endif /*PICOKLEX_H_*/ diff --git a/lib/picoknow.c b/lib/picoknow.c deleted file mode 100644 index 70b471c..0000000 --- a/lib/picoknow.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 picoknow.c - * - * 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 "picoknow.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/** class : KnowledgeBase - * shortcut : kb - * - */ -extern picoknow_KnowledgeBase picoknow_newKnowledgeBase(picoos_MemoryManager mm) -{ - picoknow_KnowledgeBase this; - PICODBG_TRACE(("start")); - - this = picoos_allocate(mm,sizeof(*this)); - if (NULL != this) { - PICODBG_TRACE(("allocated KnowledgeBase at address %i with size %i",(picoos_uint32)this,sizeof(*this))); - /* initialize */ - this->next = NULL; - this->id = PICOKNOW_KBID_NULL; - this->base = NULL; - this->size = 0; - this->subObj = NULL; - this->subDeallocate = NULL; - } - return this; -} - -extern void picoknow_disposeKnowledgeBase(picoos_MemoryManager mm, picoknow_KnowledgeBase * this) -{ - picoos_uint8 id; - if (NULL != (*this)) { - id = (*this)->id; - PICODBG_TRACE(("disposing KnowledgeBase id=%i",id)); - /* terminate */ - if ((*this)->subObj != NULL) { - (*this)->subDeallocate((*this),mm); - } - picoos_deallocate(mm,(void**)this); - } -} - -#ifdef __cplusplus -} -#endif - -/* End picoknow.c */ diff --git a/lib/picoknow.h b/lib/picoknow.h deleted file mode 100644 index 1444856..0000000 --- a/lib/picoknow.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * 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 picoknow.h - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -/** - * @addtogroup picoknow - - * Pico knowledge base \n - * -*/ - -#ifndef PICOKNOW_H_ -#define PICOKNOW_H_ - -#include "picodefs.h" -#include "picoos.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -typedef enum picoknow_kb_id { - PICOKNOW_KBID_NULL = 0, - /* base / tpp 1 - 7 */ - PICOKNOW_KBID_TPP_MAIN = 1, - PICOKNOW_KBID_TAB_GRAPHS = 2, - PICOKNOW_KBID_TAB_PHONES = 3, - PICOKNOW_KBID_TAB_POS = 4, - PICOKNOW_KBID_FIXED_IDS = 7, - /* debug */ - PICOKNOW_KBID_DBG = 8, - - /* textana 9 - 32 */ - PICOKNOW_KBID_LEX_MAIN = 9, - PICOKNOW_KBID_DT_POSP = 10, - PICOKNOW_KBID_DT_POSD = 11, - PICOKNOW_KBID_DT_G2P = 12, - PICOKNOW_KBID_FST_WPHO_1 = 13, - PICOKNOW_KBID_FST_WPHO_2 = 14, - PICOKNOW_KBID_FST_WPHO_3 = 15, - PICOKNOW_KBID_FST_WPHO_4 = 16, - PICOKNOW_KBID_FST_WPHO_5 = 17, - PICOKNOW_KBID_DT_PHR = 18, - PICOKNOW_KBID_DT_ACC = 19, - PICOKNOW_KBID_FST_SPHO_1 = 20, - PICOKNOW_KBID_FST_SPHO_2 = 21, - PICOKNOW_KBID_FST_SPHO_3 = 22, - PICOKNOW_KBID_FST_SPHO_4 = 23, - PICOKNOW_KBID_FST_SPHO_5 = 24, - - PICOKNOW_KBID_FST_XSAMPA_PARSE = 25, - PICOKNOW_KBID_FST_SVOXPA_PARSE = 26, - PICOKNOW_KBID_FST_XSAMPA2SVOXPA = 27, - - PICOKNOW_KBID_FST_SPHO_6 = 28, - PICOKNOW_KBID_FST_SPHO_7 = 29, - PICOKNOW_KBID_FST_SPHO_8 = 30, - PICOKNOW_KBID_FST_SPHO_9 = 31, - PICOKNOW_KBID_FST_SPHO_10 = 32, - - - /* siggen 33 - 48 */ - PICOKNOW_KBID_DT_DUR = 34, - PICOKNOW_KBID_DT_LFZ1 = 35, - PICOKNOW_KBID_DT_LFZ2 = 36, - PICOKNOW_KBID_DT_LFZ3 = 37, - PICOKNOW_KBID_DT_LFZ4 = 38, - PICOKNOW_KBID_DT_LFZ5 = 39, - PICOKNOW_KBID_DT_MGC1 = 40, - PICOKNOW_KBID_DT_MGC2 = 41, - PICOKNOW_KBID_DT_MGC3 = 42, - PICOKNOW_KBID_DT_MGC4 = 43, - PICOKNOW_KBID_DT_MGC5 = 44, - PICOKNOW_KBID_PDF_DUR = 45, - PICOKNOW_KBID_PDF_LFZ = 46, - PICOKNOW_KBID_PDF_MGC = 47, - PICOKNOW_KBID_PDF_PHS = 48, - - /* user tpp 49 - 56 */ - PICOKNOW_KBID_TPP_USER_1 = 49, - PICOKNOW_KBID_TPP_USER_2 = 50, - - /* user lex 57 - 63 */ - PICOKNOW_KBID_LEX_USER_1 = 57, - PICOKNOW_KBID_LEX_USER_2 = 58, - - PICOKNOW_KBID_DUMMY = 127 - -} picoknow_kb_id_t; - -#define PICOKNOW_DEFAULT_RESOURCE_NAME (picoos_char *) "__PICO_DEF_RSRC" - -#define PICOKNOW_MAX_NUM_WPHO_FSTS 5 -#define PICOKNOW_MAX_NUM_SPHO_FSTS 10 -#define PICOKNOW_MAX_NUM_ULEX 2 -#define PICOKNOW_MAX_NUM_UTPP 2 - -#define PICOKNOW_KBID_WPHO_ARRAY { \ - PICOKNOW_KBID_FST_WPHO_1, \ - PICOKNOW_KBID_FST_WPHO_2, \ - PICOKNOW_KBID_FST_WPHO_3, \ - PICOKNOW_KBID_FST_WPHO_4, \ - PICOKNOW_KBID_FST_WPHO_5 \ -} - -#define PICOKNOW_KBID_SPHO_ARRAY { \ - PICOKNOW_KBID_FST_SPHO_1, \ - PICOKNOW_KBID_FST_SPHO_2, \ - PICOKNOW_KBID_FST_SPHO_3, \ - PICOKNOW_KBID_FST_SPHO_4, \ - PICOKNOW_KBID_FST_SPHO_5, \ - PICOKNOW_KBID_FST_SPHO_6, \ - PICOKNOW_KBID_FST_SPHO_7, \ - PICOKNOW_KBID_FST_SPHO_8, \ - PICOKNOW_KBID_FST_SPHO_9, \ - PICOKNOW_KBID_FST_SPHO_10 \ -} - -#define PICOKNOW_KBID_ULEX_ARRAY { \ - PICOKNOW_KBID_LEX_USER_1, \ - PICOKNOW_KBID_LEX_USER_2, \ -} - -#define PICOKNOW_KBID_UTPP_ARRAY { \ - PICOKNOW_KBID_TPP_USER_1, \ - PICOKNOW_KBID_TPP_USER_2, \ -} - -/* max size (including NULLC) of descriptive name corresponding to KBID */ -#define PICOKNOW_MAX_KB_NAME_SIZ 16 - -/* maximum number of kbs in one resource */ -#define PICOKNOW_MAX_NUM_RESOURCE_KBS 64 - - -/** class : KnowledgeBase - * shortcut : kb - * - */ -typedef struct picoknow_knowledge_base * picoknow_KnowledgeBase; - -typedef pico_status_t (* picoknow_kbSubDeallocate) (register picoknow_KnowledgeBase this, picoos_MemoryManager mm); - -typedef struct picoknow_knowledge_base { - /* public */ - picoknow_KnowledgeBase next; - picoknow_kb_id_t id; - picoos_uint8 * base; /* start address */ - picoos_uint32 size; /* size */ - - /* protected */ - picoknow_kbSubDeallocate subDeallocate; - void * subObj; -} picoknow_knowledge_base_t; - -extern picoknow_KnowledgeBase picoknow_newKnowledgeBase(picoos_MemoryManager mm); - -extern void picoknow_disposeKnowledgeBase(picoos_MemoryManager mm, picoknow_KnowledgeBase * this); - -#ifdef __cplusplus -} -#endif - - -#endif /*PICOKNOW_H_*/ diff --git a/lib/picokpdf.c b/lib/picokpdf.c deleted file mode 100644 index bbdbec4..0000000 --- a/lib/picokpdf.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * 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 picokpdf.c - * - * knowledge handling for pdf - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#include "picoos.h" -#include "picodbg.h" -#include "picoknow.h" -#include "picokpdf.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* ************************************************************/ -/* pdf */ -/* ************************************************************/ - -/* - * @addtogroup picokpdf - * - overview: format of knowledge base pdf file - - This is the format for the dur pdf file: - - Numframes: 1 uint16 - - Vecsize: 1 uint8 - - sampperframe: 1 uint8 - - Phonquantlen: 1 uint8 - - Phonquant: Phonquantlen uint8 - - Statequantlen: 1 uint8 - - Statequantlen: Statequantlen uint8 - - And then numframes x vecsize uint8 - - This is the format for mul (mgc and lfz) pdf files: - - numframes: 1 uint16 - - vecsize: 1 uint8 - - numstates: 1 uint8 - - numframesperstate: numstates uint16 - - ceporder: 1 uint8 - - numvuv 1 uint8 - - numdeltas: 1 uint8 - - scmeanpow: 1 uint8 - - maxbigpow: 1 uint8 - - scmeanpowum KPDF_NUMSTREAMS * ceporder uint8 - - scivarpow KPDF_NUMSTREAMS * ceporder uint8 - - And then numframes x vecsize uint8 - -*/ - - -/* ************************************************************/ -/* pdf data defines */ -/* may not be changed with current implementation */ -/* ************************************************************/ - - -#define KPDF_NUMSTREAMS 3 /* coeff, delta, deltadelta */ - - -/* ************************************************************/ -/* pdf loading */ -/* ************************************************************/ - -static pico_status_t kpdfDURInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) { - picokpdf_pdfdur_t *pdfdur; - picoos_uint16 pos; - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - pdfdur = (picokpdf_pdfdur_t *)this->subObj; - - pos = 0; - - pdfdur->numframes = ((picoos_uint16)(this->base[pos+1])) << 8 | - this->base[pos]; - pos += 2; - pdfdur->vecsize = this->base[pos++]; - pdfdur->sampperframe = this->base[pos++]; - pdfdur->phonquantlen = this->base[pos++]; - pdfdur->phonquant = &(this->base[pos]); - pos += pdfdur->phonquantlen; - pdfdur->statequantlen = this->base[pos++]; - pdfdur->statequant = &(this->base[pos]); - pos += pdfdur->statequantlen; - pdfdur->content = &(this->base[pos]); - PICODBG_DEBUG(("numframes %d, vecsize %d, phonquantlen %d, " - "statequantlen %d", pdfdur->numframes, pdfdur->vecsize, - pdfdur->phonquantlen, pdfdur->statequantlen)); - if ((picoos_uint32)(pos + (pdfdur->numframes * pdfdur->vecsize)) != this->size) { - PICODBG_DEBUG(("header-spec size %d, kb-size %d", - pos + (pdfdur->numframes * pdfdur->vecsize), - this->size)); - return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, - NULL, NULL); - } - PICODBG_DEBUG(("dur pdf initialized")); - return PICO_OK; -} - -static picoos_uint8 convScaleFactorToBig(picoos_uint8 pow, picoos_uint8 bigpow) -{ - if (pow > 0x0F) { - pow = bigpow + (0xFF - pow + 1); /* take 2's complement of negative pow */ - } else if (bigpow >= pow) { - pow = bigpow - pow; - } else { - /* error: bigpow is smaller than input pow */ - return 0; - } - return pow; -} - -static pico_status_t kpdfMULInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) { - picokpdf_pdfmul_t *pdfmul; - picoos_uint16 pos; - picoos_uint8 scmeanpow, maxbigpow, nummean; - picoos_uint8 i; - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - pdfmul = (picokpdf_pdfmul_t *)this->subObj; - - pos = 0; - - pdfmul->numframes = ((picoos_uint16)(this->base[pos+1])) << 8 | - this->base[pos]; - pos += 2; - pdfmul->vecsize = this->base[pos++]; - pdfmul->numstates = this->base[pos++]; - { - pdfmul->stateoffset[0] = (picoos_uint16) 0; - for (i=1; inumstates; i++) { - pdfmul->stateoffset[i] = pdfmul->stateoffset[i-1] + (this->base[pos] | ((picoos_uint16) this->base[pos+1] << 8)); - pos += 2; - } - pos += 2; /* we don't need the last number if we only need the offset (i.e. how to get to the vector start) */ - } - - pdfmul->ceporder = this->base[pos++]; - pdfmul->numvuv = this->base[pos++]; - pdfmul->numdeltas = this->base[pos++]; - scmeanpow = this->base[pos++]; - maxbigpow = this->base[pos++]; - if (maxbigpow < PICOKPDF_BIG_POW) { - PICODBG_ERROR(("bigpow %i is larger than maxbigpow %i defined in pdf lingware", PICOKPDF_BIG_POW, maxbigpow)); - return picoos_emRaiseException(common->em, PICO_EXC_MAX_NUM_EXCEED,NULL,NULL); - } - pdfmul->bigpow = PICOKPDF_BIG_POW; /* what we have to use is the smaller number! */ - - pdfmul->amplif = this->base[pos++]; - - /* bigpow corrected by scmeanpow, multiply means by 2^meanpow to obtain fixed point representation */ - pdfmul->meanpow = convScaleFactorToBig(scmeanpow, pdfmul->bigpow); - if (0 == pdfmul->meanpow) { - PICODBG_ERROR(("error in convScaleFactorToBig")); - return picoos_emRaiseException(common->em, PICO_EXC_MAX_NUM_EXCEED,NULL,NULL); - } - nummean = 3*pdfmul->ceporder; - - pdfmul->meanpowUm = picoos_allocate(common->mm,nummean*sizeof(picoos_uint8)); - pdfmul->ivarpow = picoos_allocate(common->mm,nummean*sizeof(picoos_uint8)); - if ((NULL == pdfmul->meanpowUm) || (NULL == pdfmul->ivarpow)) { - picoos_deallocate(common->mm,(void *) &(pdfmul->meanpowUm)); - picoos_deallocate(common->mm,(void *) &(pdfmul->ivarpow)); - return picoos_emRaiseException(common->em,PICO_EXC_OUT_OF_MEM,NULL,NULL); - } - - /* read meanpowUm and convert on the fly */ - /* meaning of meanpowUm becomes: multiply means from pdf stream by 2^meanpowUm - * to achieve fixed point scaling by big - */ - for (i=0; imeanpowUm[i] = convScaleFactorToBig(this->base[pos++], pdfmul->bigpow); - } - - /*read ivarpow and convert on the fly */ - for (i=0; iivarpow[i] = convScaleFactorToBig(this->base[pos++], pdfmul->bigpow); - } - - /* check numdeltas */ - if ((pdfmul->numdeltas == 0xFF) && (pdfmul->vecsize != (pdfmul->numvuv + pdfmul->ceporder * 3 * (2+1)))) { - PICODBG_ERROR(("header has inconsistent values for vecsize, ceporder, numvuv, and numdeltas")); - return picoos_emRaiseException(common->em,PICO_EXC_FILE_CORRUPT,NULL,NULL); - } - -/* vecsize: 1 uint8 for vuv - + ceporder short for static means - + numdeltas uint8 and short for sparse delta means - + ceporder*3 uint8 for static and delta inverse variances -*/ - if ((pdfmul->numdeltas != 0xFF) && (pdfmul->vecsize != pdfmul->numvuv+pdfmul->ceporder*2+pdfmul->numdeltas*3+pdfmul->ceporder*3)) { - PICODBG_ERROR(("header has inconsistent values for vecsize, ceporder, numvuv, and numdeltas\n" - "vecsize = %i while numvuv+ceporder*2 + numdeltas*3 + ceporder*3 = %i", - pdfmul->vecsize, pdfmul->numvuv + pdfmul->ceporder*2 + pdfmul->numdeltas * 3 + pdfmul->ceporder * 3)); - return picoos_emRaiseException(common->em,PICO_EXC_FILE_CORRUPT,NULL,NULL); - } - pdfmul->content = &(this->base[pos]); - PICODBG_DEBUG(("numframes %d, vecsize %d, numstates %d, ceporder %d, " - "numvuv %d, numdeltas %d, meanpow %d, bigpow %d", - pdfmul->numframes, pdfmul->vecsize, pdfmul->numstates, - pdfmul->ceporder, pdfmul->numvuv, pdfmul->numdeltas, - pdfmul->meanpow, pdfmul->bigpow)); - if ((picoos_uint32)(pos + (pdfmul->numframes * pdfmul->vecsize)) != this->size) { - PICODBG_DEBUG(("header-spec size %d, kb-size %d", - pos + (pdfmul->numframes * pdfmul->vecsize), - this->size)); - return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, - NULL, NULL); - } - PICODBG_DEBUG(("mul pdf initialized")); - return PICO_OK; -} - -static pico_status_t kpdfPHSInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) { - picokpdf_pdfphs_t *pdfphs; - picoos_uint16 pos; - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - pdfphs = (picokpdf_pdfphs_t *)this->subObj; - - pos = 0; - - pdfphs->numvectors = ((picoos_uint16)(this->base[pos+1])) << 8 | - this->base[pos]; - pos += 2; - pdfphs->indexBase = &(this->base[pos]); - pdfphs->contentBase = pdfphs->indexBase + pdfphs->numvectors * sizeof(picoos_uint32); - PICODBG_DEBUG(("phs pdf initialized")); - return PICO_OK; -} - - - -static pico_status_t kpdfMULSubObjDeallocate(register picoknow_KnowledgeBase this, - picoos_MemoryManager mm) { - - - picokpdf_pdfmul_t *pdfmul; - - if ((NULL != this) && (NULL != this->subObj)) { - pdfmul = (picokpdf_pdfmul_t *)this->subObj; - picoos_deallocate(mm,(void *) &(pdfmul->meanpowUm)); - picoos_deallocate(mm,(void *) &(pdfmul->ivarpow)); - picoos_deallocate(mm, (void *) &(this->subObj)); - } - return PICO_OK; -} - -static pico_status_t kpdfDURSubObjDeallocate(register picoknow_KnowledgeBase this, - picoos_MemoryManager mm) { - if (NULL != this) { - picoos_deallocate(mm, (void *) &this->subObj); - } - return PICO_OK; -} - -static pico_status_t kpdfPHSSubObjDeallocate(register picoknow_KnowledgeBase this, - picoos_MemoryManager mm) { - if (NULL != this) { - picoos_deallocate(mm, (void *) &this->subObj); - } - return PICO_OK; -} - -/* we don't offer a specialized constructor for a *KnowledgeBase but - * instead a "specializer" of an allready existing generic - * picoknow_KnowledgeBase */ - -pico_status_t picokpdf_specializePdfKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common, - const picokpdf_kpdftype_t kpdftype) { - pico_status_t status; - - if (NULL == this) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - switch (kpdftype) { - case PICOKPDF_KPDFTYPE_DUR: - this->subDeallocate = kpdfDURSubObjDeallocate; - this->subObj = picoos_allocate(common->mm,sizeof(picokpdf_pdfdur_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - status = kpdfDURInitialize(this, common); - break; - case PICOKPDF_KPDFTYPE_MUL: - this->subDeallocate = kpdfMULSubObjDeallocate; - this->subObj = picoos_allocate(common->mm,sizeof(picokpdf_pdfmul_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - status = kpdfMULInitialize(this, common); - break; - case PICOKPDF_KPDFTYPE_PHS: - this->subDeallocate = kpdfPHSSubObjDeallocate; - this->subObj = picoos_allocate(common->mm,sizeof(picokpdf_pdfphs_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - status = kpdfPHSInitialize(this, common); - break; - - default: - return picoos_emRaiseException(common->em, PICO_ERR_OTHER, - NULL, NULL); - } - - if (status != PICO_OK) { - picoos_deallocate(common->mm, (void *) &this->subObj); - return picoos_emRaiseException(common->em, status, NULL, NULL); - } - return PICO_OK; -} - - -/* ************************************************************/ -/* pdf getPdf* */ -/* ************************************************************/ - -picokpdf_PdfDUR picokpdf_getPdfDUR(picoknow_KnowledgeBase this) { - return ((NULL == this) ? NULL : ((picokpdf_PdfDUR) this->subObj)); -} - -picokpdf_PdfMUL picokpdf_getPdfMUL(picoknow_KnowledgeBase this) { - return ((NULL == this) ? NULL : ((picokpdf_PdfMUL) this->subObj)); -} - -picokpdf_PdfPHS picokpdf_getPdfPHS(picoknow_KnowledgeBase this) { - return ((NULL == this) ? NULL : ((picokpdf_PdfPHS) this->subObj)); -} - - -#ifdef __cplusplus -} -#endif - - -/* end */ diff --git a/lib/picokpdf.h b/lib/picokpdf.h deleted file mode 100644 index f4508a1..0000000 --- a/lib/picokpdf.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * 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 picokpdf.h - * - * knowledge handling for pdf - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#ifndef PICOKPDF_H_ -#define PICOKPDF_H_ - -#include "picoos.h" -#include "picoknow.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* ************************************************************/ -/** - * @addtogroup picokpdf - * - Two specialized pdf kb types are provided by this knowledge - handling module: - - - pdf dur: ...kpdf_DUR (for dur) - - pdf mul: ...kpdf_MUL (for lfz and mgc) - - pdf phs: ...kpdf_PHS (for phase) - -*/ -/* ************************************************************/ - - -/* ************************************************************/ -/* defines and functions to create specialized kb, */ -/* to be used by picorsrc only */ -/* ************************************************************/ - -#define PICOKPDF_MAX_NUM_STATES 10 - -#define PICOKPDF_MAX_MUL_LFZ_CEPORDER 1 -#define PICOKPDF_MAX_MUL_MGC_CEPORDER 25 - -/* trade accuracy against computation: more long multiplications. - * Maximum is 15 when invdiag0=(1<<(2*bigpow))/diag0 used - * currently observing instability in mlpg when bigpow >= 14, this needs to be investigated */ - -#define PICOKPDF_BIG_POW 12 - -typedef enum { - PICOKPDF_KPDFTYPE_DUR, - PICOKPDF_KPDFTYPE_MUL, - PICOKPDF_KPDFTYPE_PHS -} picokpdf_kpdftype_t; - -pico_status_t picokpdf_specializePdfKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common, - const picokpdf_kpdftype_t type); - - -/* ************************************************************/ -/* pdf types and get Pdf functions */ -/* ************************************************************/ - -/** object : PdfDur, PdfMUL - * shortcut : kpdf* - * derived from : picoknow_KnowledgeBase - */ - -typedef struct picokpdf_pdfdur *picokpdf_PdfDUR; -typedef struct picokpdf_pdfmul *picokpdf_PdfMUL; -typedef struct picokpdf_pdfphs *picokpdf_PdfPHS; - -/* subobj specific for pdf dur type */ -typedef struct picokpdf_pdfdur { - picoos_uint16 numframes; - picoos_uint8 vecsize; - picoos_uint8 sampperframe; - picoos_uint8 phonquantlen; - picoos_uint8 *phonquant; - picoos_uint8 statequantlen; - picoos_uint8 *statequant; - picoos_uint8 *content; -} picokpdf_pdfdur_t; - -/* subobj specific for pdf mul type */ -typedef struct picokpdf_pdfmul { - picoos_uint16 numframes; - picoos_uint8 vecsize; - picoos_uint8 numstates; - picoos_uint16 stateoffset[PICOKPDF_MAX_NUM_STATES]; /* offset within a phone to find the state ? */ - picoos_uint8 ceporder; - picoos_uint8 numvuv; - picoos_uint8 numdeltas; - picoos_uint8 meanpow; - picoos_uint8 bigpow; - picoos_uint8 amplif; - picoos_uint8 *meanpowUm; /* KPDF_NUMSTREAMS x ceporder values */ - picoos_uint8 *ivarpow; /* KPDF_NUMSTREAMS x ceporder values */ - picoos_uint8 *content; -} picokpdf_pdfmul_t; - -/* subobj specific for pdf phs type */ -typedef struct picokpdf_pdfphs { - picoos_uint16 numvectors; - picoos_uint8 *indexBase; - picoos_uint8 *contentBase; -} picokpdf_pdfphs_t; - -/* return kb pdf for usage in PU */ -picokpdf_PdfDUR picokpdf_getPdfDUR(picoknow_KnowledgeBase this); -picokpdf_PdfMUL picokpdf_getPdfMUL(picoknow_KnowledgeBase this); -picokpdf_PdfPHS picokpdf_getPdfPHS(picoknow_KnowledgeBase this); - - -/* ************************************************************/ -/* PDF DUR functions */ -/* ************************************************************/ - -/* e.g. */ -/*picoos_uint8 picokpdf_pdfDURgetEle(const picokpdf_PdfDUR this, - const picoos_uint16 row, - const picoos_uint16 col, - picoos_uint16 *val); -*/ - -/* ************************************************************/ -/* PDF MUL functions */ -/* ************************************************************/ - -#ifdef __cplusplus -} -#endif - - -#endif /*PICOKPDF_H_*/ diff --git a/lib/picokpr.c b/lib/picokpr.c deleted file mode 100644 index 956ae39..0000000 --- a/lib/picokpr.c +++ /dev/null @@ -1,652 +0,0 @@ -/* - * 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 picokpr.c - * - * knowledge handling for text preprocessing - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -#include "picoos.h" -#include "picodbg.h" -#include "picodata.h" -#include "picoknow.h" -#include "picokpr.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* ************************************************************/ -/* preproc */ -/* ************************************************************/ - -/* - overview: -*/ - - -/* ************************************************************/ -/* preproc data defines */ -/* ************************************************************/ - -#define KPR_STR_SIZE 1 -#define KPR_LEXCAT_SIZE 2 -#define KPR_ATTRVAL_SIZE 4 -#define KPR_OUTITEM_SIZE 7 -#define KPR_TOK_SIZE 16 -#define KPR_PROD_SIZE 12 -#define KPR_CTX_SIZE 12 - -#define KPR_NETNAME_OFFSET 0 -#define KPR_STRARRLEN_OFFSET 4 -#define KPR_LEXCATARRLEN_OFFSET 8 -#define KPR_ATTRVALARRLEN_OFFSET 12 -#define KPR_OUTITEMARRLEN_OFFSET 16 -#define KPR_TOKARRLEN_OFFSET 20 -#define KPR_PRODARRLEN_OFFSET 24 -#define KPR_CTXARRLEN_OFFSET 28 - -#define KPR_ARRAY_START 32 - -#define KPR_MAX_INT32 2147483647 - -#define KPR_STR_OFS 0 - -#define KPR_LEXCAT_OFS 0 - -#define KPR_ATTRVAL_INT_OFS 0 -#define KPR_ATTRVAL_STROFS_OFS 0 -#define KPR_ATTRVAL_PRODOFS_OFS 0 -#define KPR_ATTRVAL_OUTITMOFS_OFS 0 -#define KPR_ATTRVAL_LEXCATOFS_OFS 0 - -#define KPR_OUTITEM_NEXTOFS_OFS 0 -#define KPR_OUTITEM_TYPE_OFS 2 -#define KPR_OUTITEM_STROFS_OFS 3 -#define KPR_OUTITEM_VAL_OFS 3 -#define KPR_OUTITEM_ARGOFS_OFS 3 - -#define KPR_TOK_SETWP_OFS 0 -#define KPR_TOK_SETNP_OFS 4 -#define KPR_TOK_NEXTOFS_OFS 8 -#define KPR_TOK_ALTLOFS_OFS 10 -#define KPR_TOK_ALTROFS_OFS 12 -#define KPR_TOK_ATTRIBOFS_OFS 14 - -#define KPR_PROD_PRODPREFCOST_OFS 0 -#define KPR_PROD_PRODNAMEOFS_OFS 4 -#define KPR_PROD_ATOKOFS_OFS 8 -#define KPR_PROD_ETOKOFS_OFS 10 - -#define KPR_CTX_CTXNAMEOFS_OFS 0 -#define KPR_CTX_NETNAMEOFS_OFS 4 -#define KPR_CTX_PRODNAMEOFS_OFS 8 - -/* ************************************************************/ -/* preproc type and loading */ -/* ************************************************************/ - -/* variable array element types */ -typedef picoos_uint8 picokpr_Str[KPR_STR_SIZE]; -typedef picoos_uint16 picokpr_LexCat2; -typedef picoos_uint8 picokpr_AttrVal[KPR_ATTRVAL_SIZE]; -typedef picoos_uint8 picokpr_OutItem[KPR_OUTITEM_SIZE]; -typedef picoos_uint8 picokpr_Tok[KPR_TOK_SIZE]; -typedef picoos_uint8 picokpr_Prod[KPR_PROD_SIZE]; -typedef picoos_uint8 picokpr_Ctx[KPR_CTX_SIZE]; - -/* variable array types */ -typedef picokpr_Str * picokpr_VarStrArr; -typedef picokpr_LexCat2 * picokpr_VarLexCatArr; -typedef picokpr_AttrVal * picokpr_VarAttrValArr; -typedef picokpr_OutItem * picokpr_VarOutItemArr; -typedef picokpr_Tok * picokpr_VarTokArr; -typedef picokpr_Prod * picokpr_VarProdArr; -typedef picokpr_Ctx * picokpr_VarCtxArr; - -/* ************************************************************/ -/* preproc type and loading */ -/* ************************************************************/ - -/** object : PreprocKnowledgeBase - * shortcut : kpr - * derived from : picoknow_KnowledgeBase - */ - -typedef struct kpr_subobj * kpr_SubObj; - -typedef struct kpr_subobj -{ - picoos_uchar * rNetName; - - picoos_int32 rStrArrLen; - picoos_int32 rLexCatArrLen; - picoos_int32 rAttrValArrLen; - picoos_int32 rOutItemArrLen; - picoos_int32 rTokArrLen; - picoos_int32 rProdArrLen; - picoos_int32 rCtxArrLen; - - picoos_uint8 * rStrArr; - picokpr_LexCat2 * rLexCatArr; - picokpr_AttrVal * rAttrValArr; - picokpr_OutItem * rOutItemArr; - picokpr_Tok * rTokArr; - picokpr_Prod * rProdArr; - picokpr_Ctx * rCtxArr; -} kpr_subobj_t; - - -static picoos_uint32 kpr_getUInt32(picoos_uint8 * p) -{ - return p[0] + 256*p[1] + 256*256*p[2] + 256*256*256*p[3]; -} - - -static pico_status_t kprInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) -{ - picoos_uint32 offset = 0; - kpr_subobj_t * kpr; - - PICODBG_DEBUG(("start")); - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - kpr = (kpr_subobj_t *) this->subObj; - - kpr->rStrArrLen = kpr_getUInt32(&(this->base[KPR_STRARRLEN_OFFSET])); - kpr->rLexCatArrLen = kpr_getUInt32(&(this->base[KPR_LEXCATARRLEN_OFFSET])); - kpr->rAttrValArrLen = kpr_getUInt32(&(this->base[KPR_ATTRVALARRLEN_OFFSET])); - kpr->rOutItemArrLen = kpr_getUInt32(&(this->base[KPR_OUTITEMARRLEN_OFFSET])); - kpr->rTokArrLen = kpr_getUInt32(&(this->base[KPR_TOKARRLEN_OFFSET])); - kpr->rProdArrLen = kpr_getUInt32(&(this->base[KPR_PRODARRLEN_OFFSET])); - kpr->rCtxArrLen = kpr_getUInt32(&(this->base[KPR_CTXARRLEN_OFFSET])); - - offset = KPR_ARRAY_START; - kpr->rStrArr = &(this->base[offset]); - PICODBG_DEBUG(("rStrArr : cs: %i, ss: %i, offset: %i", sizeof(picokpr_Str), KPR_STR_SIZE, offset)); - offset = offset + kpr->rStrArrLen * 1; - - kpr->rLexCatArr = (picokpr_LexCat2 *)&(this->base[offset]); - PICODBG_DEBUG(("rLexCatArr : cs: %i, ss: %i, offset: %i", KPR_LEXCAT_SIZE, sizeof(picokpr_LexCat2), offset)); - offset = offset + kpr->rLexCatArrLen * KPR_LEXCAT_SIZE; - - kpr->rAttrValArr = (picokpr_AttrVal *)&(this->base[offset]); - PICODBG_DEBUG(("rAttrValArr : cs: %i, ss: %i, offset: %i", KPR_ATTRVAL_SIZE, sizeof(picokpr_AttrVal), offset)); - offset = offset + kpr->rAttrValArrLen * KPR_ATTRVAL_SIZE; - - kpr->rOutItemArr = (picokpr_OutItem *)&(this->base[offset]); - PICODBG_DEBUG(("rOutItemArr : cs: %i, ss: %i, offset: %i", KPR_OUTITEM_SIZE, sizeof(picokpr_OutItem), offset)); - offset = offset + kpr->rOutItemArrLen * KPR_OUTITEM_SIZE; - - kpr->rTokArr = (picokpr_Tok *)&(this->base[offset]); - PICODBG_DEBUG(("rTokArr : cs: %i, ss: %i, offset: %i", KPR_TOK_SIZE, sizeof(picokpr_Tok), offset)); - offset = offset + kpr->rTokArrLen * KPR_TOK_SIZE; - - kpr->rProdArr = (picokpr_Prod *)&(this->base[offset]); - PICODBG_DEBUG(("rProdArr : cs: %i, ss: %i, offset: %i", KPR_PROD_SIZE, sizeof(picokpr_Prod), offset)); - offset = offset + kpr->rProdArrLen * KPR_PROD_SIZE; - - kpr->rCtxArr = (picokpr_Ctx *)&(this->base[offset]); - PICODBG_DEBUG(("rCtxArr : cs: %i, ss: %i, offset: %i", KPR_CTX_SIZE, sizeof(picokpr_Ctx), offset)); - offset = offset + kpr->rCtxArrLen * KPR_CTX_SIZE; - - kpr->rNetName = &(kpr->rStrArr[kpr_getUInt32(&(this->base[KPR_NETNAME_OFFSET]))]); - - return PICO_OK; -} - - -static pico_status_t kprSubObjDeallocate(register picoknow_KnowledgeBase this, - picoos_MemoryManager mm) -{ - if (NULL != this) { - picoos_deallocate(mm, (void *) &this->subObj); - } - return PICO_OK; -} - - -/* we don't offer a specialized constructor for a PreprocKnowledgeBase but - * instead a "specializer" of an allready existing generic - * picoknow_KnowledgeBase */ - -pico_status_t picokpr_specializePreprocKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common) -{ - if (NULL == this) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - this->subDeallocate = kprSubObjDeallocate; - this->subObj = picoos_allocate(common->mm, sizeof(kpr_subobj_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - return kprInitialize(this, common); -} - -/* ************************************************************/ -/* preproc getPreproc */ -/* ************************************************************/ - -picokpr_Preproc picokpr_getPreproc(picoknow_KnowledgeBase this) -{ - if (NULL == this) { - return NULL; - } else { - return (picokpr_Preproc) this->subObj; - } -} - - -/* *****************************************************************************/ -/* knowledge base access routines for strings in StrArr */ -/* *****************************************************************************/ - -extern picokpr_VarStrPtr picokpr_getVarStrPtr(picokpr_Preproc preproc, picokpr_StrArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rStrArr[ofs]); - - return p; -} - -/* *****************************************************************************/ - -extern picoos_bool picokpr_isEqual (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__9, picokpr_StrArrOffset str2) -{ - picokpr_VarStrPtr lstrp; - len__9 = len__9; /*PP 13.10.08 : fix warning "var not used in this function"*/ - lstrp = (picokpr_VarStrPtr)&((kpr_SubObj)preproc)->rStrArr[str2]; - return picoos_strcmp((picoos_char*)lstrp,(picoos_char*)str) == 0; -} - - - -extern picoos_bool picokpr_isEqualHead (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__10, picokpr_StrArrOffset head) -{ - picokpr_VarStrPtr lstrp; - len__10 = len__10; /*PP 13.10.08 : fix warning "var not used in this function"*/ - lstrp = (picokpr_VarStrPtr)&((kpr_SubObj)preproc)->rStrArr[head]; - return (picoos_strstr((picoos_char*)str, (picoos_char*)lstrp) == (picoos_char*)str); -} - - - -extern picoos_bool picokpr_isEqualMid (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__11, picokpr_StrArrOffset mid) -{ - picokpr_VarStrPtr lstrp; - len__11 = len__11; /*PP 13.10.08 : fix warning "var not used in this function"*/ - lstrp = (picokpr_VarStrPtr)(void *) &((kpr_SubObj)preproc)->rStrArr[mid]; - return (picoos_strstr((picoos_char*)str, (picoos_char*)lstrp) != NULL); -} - - - -extern picoos_bool picokpr_isEqualTail (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__12, picokpr_StrArrOffset tail) -{ - picoos_int32 lstart; - picokpr_VarStrPtr lstrp; - len__12 = len__12; /* avoid warning "var not used in this function"*/ - lstrp = (picokpr_VarStrPtr)&((kpr_SubObj)preproc)->rStrArr[tail]; - lstart = picoos_strlen((picoos_char*)str) - picoos_strlen((picoos_char*)lstrp); - if (lstart >= 0) { - return (picoos_strstr((picoos_char*)&(str[lstart]), (picoos_char*)lstrp) != NULL); - } else { - return FALSE; - } -} - -/* *****************************************************************************/ -/* knowledge base access routines for lexical categories in LexCatArr */ -/* *****************************************************************************/ - -extern picokpr_LexCat picokpr_getLexCat(picokpr_Preproc preproc, picokpr_LexCatArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rLexCatArr[ofs]); - - return p[0] + 256*p[1]; -} - -/* *****************************************************************************/ -/* knowledge base access routines for AttrVal fields in AttrValArr */ -/* *****************************************************************************/ - -extern picoos_int32 picokpr_getAttrValArrInt32(picokpr_Preproc preproc, picokpr_AttrValArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rAttrValArr[ofs]); - picoos_uint32 c = p[KPR_ATTRVAL_INT_OFS] + - 256*p[KPR_ATTRVAL_INT_OFS+1] + - 256*256*p[KPR_ATTRVAL_INT_OFS+2] + - 256*256*256*p[KPR_ATTRVAL_INT_OFS+3]; - - if (c > KPR_MAX_INT32) { - return (c - KPR_MAX_INT32) - 1; - } else { - return (((int)c + (int) -(KPR_MAX_INT32)) - 1); - } -} - -/* *****************************************************************************/ -/* knowledge base access routines for AttrVal fields in AttrValArr */ -/* *****************************************************************************/ - -extern picokpr_OutItemArrOffset picokpr_getOutItemNextOfs(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rOutItemArr[ofs]); - - return p[KPR_OUTITEM_NEXTOFS_OFS+0] + 256*p[KPR_OUTITEM_NEXTOFS_OFS+1]; -} - - -extern picoos_int32 picokpr_getOutItemType(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rOutItemArr[ofs]); - - return p[KPR_OUTITEM_TYPE_OFS+0]; -} - - -extern picokpr_StrArrOffset picokpr_getOutItemStrOfs(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rOutItemArr[ofs]); - - return p[KPR_OUTITEM_STROFS_OFS+0] + - 256*p[KPR_OUTITEM_STROFS_OFS+1] + - 256*256*p[KPR_OUTITEM_STROFS_OFS+2] + - 256*256*256*p[KPR_OUTITEM_STROFS_OFS+3]; -} - - -extern picokpr_VarStrPtr picokpr_getOutItemStr(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rOutItemArr[ofs]); - picoos_uint32 c = p[KPR_OUTITEM_STROFS_OFS+0] + - 256*p[KPR_OUTITEM_STROFS_OFS+1] + - 256*256*p[KPR_OUTITEM_STROFS_OFS+2] + - 256*256*256*p[KPR_OUTITEM_STROFS_OFS+3]; - - return (picoos_uint8 *)&(((kpr_SubObj)preproc)->rStrArr[c]); -} - -extern picoos_int32 picokpr_getOutItemVal(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rOutItemArr[ofs]); - picoos_uint32 c = p[KPR_OUTITEM_VAL_OFS+0] + - 256*p[KPR_OUTITEM_VAL_OFS+1] + - 256*256*p[KPR_OUTITEM_VAL_OFS+2] + - 256*256*256*p[KPR_OUTITEM_VAL_OFS+3]; - - if (c > KPR_MAX_INT32) { - return (c - KPR_MAX_INT32) - 1; - } else { - return (((int)c + (int) -(KPR_MAX_INT32)) - 1); - } -} - - -extern picokpr_OutItemArrOffset picokpr_getOutItemArgOfs(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rOutItemArr[ofs]); - - return p[KPR_OUTITEM_ARGOFS_OFS+0] + - 256*p[KPR_OUTITEM_ARGOFS_OFS+1] + - 256*256*p[KPR_OUTITEM_ARGOFS_OFS+2] + - 256*256*256*p[KPR_OUTITEM_ARGOFS_OFS+3]; -} - - -/* *****************************************************************************/ -/* knowledge base access routines for tokens in TokArr */ -/* *****************************************************************************/ - -extern picokpr_TokSetNP picokpr_getTokSetNP(picokpr_Preproc preproc, picokpr_TokArrOffset ofs) -{ - picoos_uint32 c/*, b*/; - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]) + KPR_TOK_SETNP_OFS; - /*picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]);*/ - picoos_uint32 p0, p1, p2, p3; - - p0 = *(p++); - p1 = *(p++); - p2 = *(p++); - p3 = *p; - - c = p0 + (p1<<8) + (p2<<16) + (p3<<24); - - return c; - - /* - c = p[KPR_TOK_SETNP_OFS+0] + - 256*p[KPR_TOK_SETNP_OFS+1] + - 256*256*p[KPR_TOK_SETNP_OFS+2] + - 256*256*256*p[KPR_TOK_SETNP_OFS+3]; - - b = 0; - i = 0; - while ((i <= 31) && (c > 0)) { - if (c % 2 == 1) { - b |= (1<rTokArr[ofs]);*/ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]) + KPR_TOK_SETWP_OFS; - picoos_uint32 p0, p1, p2, p3; - - p0 = *(p++); - p1 = *(p++); - p2 = *(p++); - p3 = *p; - - c = p0 + (p1<<8) + (p2<<16) + (p3<<24); - return c; - - /* - c = p[KPR_TOK_SETWP_OFS+0] + - 256*p[KPR_TOK_SETWP_OFS+1] + - 256*256*p[KPR_TOK_SETWP_OFS+2] + - 256*256*256*p[KPR_TOK_SETWP_OFS+3]; - - b = 0; - i = 0; - while ((i <= 31) && (c > 0)) { - if (c % 2 == 1) { - b |= (1<rTokArr[ofs]); - - return p[KPR_TOK_NEXTOFS_OFS+0] + 256*p[KPR_TOK_NEXTOFS_OFS+1]; -} - - -extern picokpr_TokArrOffset picokpr_getTokAltLOfs(picokpr_Preproc preproc, picokpr_TokArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]) + KPR_TOK_ALTLOFS_OFS; - picokpr_TokArrOffset c = *p++; - return c + 256**p; - - /*picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]); - - return p[KPR_TOK_ALTLOFS_OFS+0] + 256*p[KPR_TOK_ALTLOFS_OFS+1]; - */ -} - - -extern picokpr_TokArrOffset picokpr_getTokAltROfs(picokpr_Preproc preproc, picokpr_TokArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]) + KPR_TOK_ALTROFS_OFS; - picokpr_TokArrOffset c = *p++; - return c + 256**p; - - /*picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]); - - return p[KPR_TOK_ALTROFS_OFS+0] + 256*p[KPR_TOK_ALTROFS_OFS+1];*/ -} - - -extern picokpr_AttrValArrOffset picokpr_getTokAttribOfs(picokpr_Preproc preproc, picokpr_TokArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]); - - return p[KPR_TOK_ATTRIBOFS_OFS+0] + 256*p[KPR_TOK_ATTRIBOFS_OFS+1]; -} - -/* *****************************************************************************/ -/* knowledge base access routines for productions in ProdArr */ -/* *****************************************************************************/ - -extern picoos_int32 picokpr_getProdArrLen(picokpr_Preproc preproc) -{ - return ((kpr_SubObj)preproc)->rProdArrLen; -} - -extern picoos_int32 picokpr_getProdPrefCost(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rProdArr[ofs]); - picoos_uint32 c = p[KPR_PROD_PRODPREFCOST_OFS+0] + - 256*p[KPR_PROD_PRODPREFCOST_OFS+1] + - 256*256*p[KPR_PROD_PRODPREFCOST_OFS+2] + - 256*256*256*p[KPR_PROD_PRODPREFCOST_OFS+3]; - - - if (c > KPR_MAX_INT32) { - return (c - KPR_MAX_INT32) - 1; - } else { - return (((int)c + (int) -(KPR_MAX_INT32)) - 1); - } -} - - -extern picokpr_StrArrOffset picokpr_getProdNameOfs(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rProdArr[ofs]); - - return p[KPR_PROD_PRODNAMEOFS_OFS+0] + - 256*p[KPR_PROD_PRODNAMEOFS_OFS+1] + - 256*256*p[KPR_PROD_PRODNAMEOFS_OFS+2] + - 256*256*256*p[KPR_PROD_PRODNAMEOFS_OFS+3]; - -} - - -extern picokpr_TokArrOffset picokpr_getProdATokOfs(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rProdArr[ofs]); - - return p[KPR_PROD_ATOKOFS_OFS+0] + 256*p[KPR_PROD_ATOKOFS_OFS+1]; -} - - -extern picokpr_TokArrOffset picokpr_getProdETokOfs(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rProdArr[ofs]); - - return p[KPR_PROD_ETOKOFS_OFS+0] + 256*p[KPR_PROD_ETOKOFS_OFS+1]; -} - -/* *****************************************************************************/ -/* knowledge base access routines for contexts in CtxArr */ -/* *****************************************************************************/ - -extern picoos_int32 picokpr_getCtxArrLen(picokpr_Preproc preproc) -{ - return ((kpr_SubObj)preproc)->rCtxArrLen; -} - -extern picokpr_StrArrOffset picokpr_getCtxCtxNameOfs(picokpr_Preproc preproc, picokpr_CtxArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rCtxArr[ofs]); - - return p[KPR_CTX_CTXNAMEOFS_OFS+0] + - 256*p[KPR_CTX_CTXNAMEOFS_OFS+1] + - 256*256*p[KPR_CTX_CTXNAMEOFS_OFS+2] + - 256*256*256*p[KPR_CTX_CTXNAMEOFS_OFS+3]; -} - - -extern picokpr_StrArrOffset picokpr_getCtxNetNameOfs(picokpr_Preproc preproc, picokpr_CtxArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rCtxArr[ofs]); - - return p[KPR_CTX_NETNAMEOFS_OFS+0] + - 256*p[KPR_CTX_NETNAMEOFS_OFS+1] + - 256*256*p[KPR_CTX_NETNAMEOFS_OFS+2] + - 256*256*256*p[KPR_CTX_NETNAMEOFS_OFS+3]; -} - - -extern picokpr_StrArrOffset picokpr_getCtxProdNameOfs(picokpr_Preproc preproc, picokpr_CtxArrOffset ofs) -{ - picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rCtxArr[ofs]); - - return p[KPR_CTX_PRODNAMEOFS_OFS+0] + - 256*p[KPR_CTX_PRODNAMEOFS_OFS+1] + - 256*256*p[KPR_CTX_PRODNAMEOFS_OFS+2] + - 256*256*256*p[KPR_CTX_PRODNAMEOFS_OFS+3]; -} - -/* *****************************************************************************/ -/* knowledge base access routines for networks */ -/* *****************************************************************************/ - -extern picokpr_VarStrPtr picokpr_getPreprocNetName(picokpr_Preproc preproc) -{ - return ((kpr_SubObj)preproc)->rNetName; -} - - -#ifdef __cplusplus -} -#endif - - -/* end */ diff --git a/lib/picokpr.h b/lib/picokpr.h deleted file mode 100644 index 0532b49..0000000 --- a/lib/picokpr.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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 picokpr.h - * - * knowledge handling for text preprocessing - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -/** - * @addtogroup picokpr - - * Knowledge handling for text preprocessing \n - * -*/ - -#ifndef PICOKPR_H_ -#define PICOKPR_H_ - -#include "picoos.h" -#include "picoknow.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* ************************************************************/ -/* function to create specialized kb, */ -/* to be used by picorsrc only */ -/* ************************************************************/ - -pico_status_t picokpr_specializePreprocKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common); - - -/* ************************************************************/ -/* preproc type and getPreproc function */ -/* ************************************************************/ - -/* maximal array length in preproc knowledge */ -#define NPPMaxStrArrLen 100000000 -#define NPPMaxLexCatArrLen 65536 -#define NPPMaxAttrValLen 65536 -#define NPPMaxOutItemArrLen 65536 -#define NPPMaxTokArrLen 65536 -#define NPPMaxProdArrLen 65536 -#define NPPMaxCtxArrLen 65536 - -/* array offset types */ -typedef picoos_uint32 picokpr_StrArrOffset; -typedef picoos_uint16 picokpr_LexCatArrOffset; -typedef picoos_uint16 picokpr_AttrValArrOffset; -typedef picoos_uint16 picokpr_OutItemArrOffset; -typedef picoos_uint16 picokpr_TokArrOffset; -typedef picoos_uint16 picokpr_ProdArrOffset; -typedef picoos_uint16 picokpr_CtxArrOffset; - -typedef picoos_uchar * picokpr_VarStrPtr; - -typedef picoos_int16 picokpr_LexCat; -typedef picoos_uint32 picokpr_TokSetNP; -typedef picoos_uint32 picokpr_TokSetWP; - -/* preproc types */ -typedef struct picokpr_preproc * picokpr_Preproc; - -/* return kb preproc for usage in PU */ -picokpr_Preproc picokpr_getPreproc(picoknow_KnowledgeBase this); - - -/* *****************************************************************************/ -/* access routines */ -/* *****************************************************************************/ - -/* knowledge base access routines for strings in StrArr */ -extern picokpr_VarStrPtr picokpr_getVarStrPtr(picokpr_Preproc preproc, picokpr_StrArrOffset ofs); -extern picoos_bool picokpr_isEqual (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__9, picokpr_StrArrOffset str2); -extern picoos_bool picokpr_isEqualHead (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__10, picokpr_StrArrOffset head); -extern picoos_bool picokpr_isEqualMid (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__11, picokpr_StrArrOffset mid); -extern picoos_bool picokpr_isEqualTail (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__12, picokpr_StrArrOffset tail); - -/* knowledge base access routines for lexical categories in LexCatArr */ -extern picokpr_LexCat picokpr_getLexCat(picokpr_Preproc preproc, picokpr_LexCatArrOffset ofs); - -/* knowledge base access routines for AttrVal fields in AttrValArr */ -extern picoos_int32 picokpr_getAttrValArrInt32(picokpr_Preproc preproc, picokpr_AttrValArrOffset ofs); - -/* knowledge base access routines for out items fields in OutItemArr */ -extern picokpr_StrArrOffset picokpr_getOutItemStrOfs(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs); -extern picokpr_VarStrPtr picokpr_getOutItemStr(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs); -extern picoos_int32 picokpr_getOutItemType(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs); -extern picoos_int32 picokpr_getOutItemVal(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs); -extern picokpr_OutItemArrOffset picokpr_getOutItemArgOfs(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs); -extern picokpr_OutItemArrOffset picokpr_getOutItemNextOfs(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs); - -/* knowledge base access routines for tokens in TokArr */ -extern picokpr_TokSetNP picokpr_getTokSetNP(picokpr_Preproc preproc, picokpr_TokArrOffset ofs); -extern picokpr_TokSetWP picokpr_getTokSetWP(picokpr_Preproc preproc, picokpr_TokArrOffset ofs); -extern picokpr_TokArrOffset picokpr_getTokNextOfs(picokpr_Preproc preproc, picokpr_TokArrOffset ofs); -extern picokpr_TokArrOffset picokpr_getTokAltLOfs(picokpr_Preproc preproc, picokpr_TokArrOffset ofs); -extern picokpr_TokArrOffset picokpr_getTokAltROfs(picokpr_Preproc preproc, picokpr_TokArrOffset ofs); -extern picokpr_AttrValArrOffset picokpr_getTokAttribOfs(picokpr_Preproc preproc, picokpr_TokArrOffset ofs); - -/* knowledge base access routines for productions in ProdArr */ -extern picoos_int32 picokpr_getProdArrLen(picokpr_Preproc preproc); -extern picoos_int32 picokpr_getProdPrefCost(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs); -extern picokpr_StrArrOffset picokpr_getProdNameOfs(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs); -extern picokpr_TokArrOffset picokpr_getProdATokOfs(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs); -extern picokpr_TokArrOffset picokpr_getProdETokOfs(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs); - -/* knowledge base access routines for contexts in CtxArr */ -extern picoos_int32 picokpr_getCtxArrLen(picokpr_Preproc preproc); -extern picokpr_StrArrOffset picokpr_getCtxCtxNameOfs(picokpr_Preproc preproc, picokpr_CtxArrOffset ofs); -extern picokpr_StrArrOffset picokpr_getCtxNetNameOfs(picokpr_Preproc preproc, picokpr_CtxArrOffset ofs); -extern picokpr_StrArrOffset picokpr_getCtxProdNameOfs(picokpr_Preproc preproc, picokpr_CtxArrOffset ofs); - -/* knowledge base access routines for preprocs */ -extern picokpr_VarStrPtr picokpr_getPreprocNetName(picokpr_Preproc preproc); - -#ifdef __cplusplus -} -#endif - - -#endif /*PICOKPR_H_*/ diff --git a/lib/picoktab.c b/lib/picoktab.c deleted file mode 100644 index ca8b470..0000000 --- a/lib/picoktab.c +++ /dev/null @@ -1,1118 +0,0 @@ -/* - * 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 picoktab.c - * - * symbol tables needed at runtime - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#include "picoos.h" -#include "picodbg.h" -#include "picoknow.h" -#include "picobase.h" -#include "picoktab.h" -#include "picodata.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/** @todo : the following would be better part of a knowledge base. - * Make sure it is consistent with the phoneme symbol table used in the lingware */ - -/* PLANE_PHONEMES */ - -/* PLANE_POS */ - -/* PLANE_PB_STRENGTHS */ - -/* PLANE_ACCENTS */ - -/* PLANE_INTERN */ -#define PICOKTAB_TMPID_PHONSTART '\x26' /* 38 '&' */ -#define PICOKTAB_TMPID_PHONTERM '\x23' /* 35 '#' */ - - -/* ************************************************************/ -/* fixed ids */ -/* ************************************************************/ - - -static pico_status_t ktabIdsInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) -{ - picoktab_FixedIds ids; - - PICODBG_DEBUG(("start")); - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - ids = (picoktab_FixedIds) this->subObj; - - ids->phonStartId = PICOKTAB_TMPID_PHONSTART; - ids->phonTermId = PICOKTAB_TMPID_PHONTERM; - return PICO_OK; -} - - -static pico_status_t ktabIdsSubObjDeallocate(register picoknow_KnowledgeBase this, - picoos_MemoryManager mm) -{ - if (NULL != this) { - picoos_deallocate(mm, (void *) &this->subObj); - } - return PICO_OK; -} - -pico_status_t picoktab_specializeIdsKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common) -{ - if (NULL == this) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - this->subDeallocate = ktabIdsSubObjDeallocate; - this->subObj = picoos_allocate(common->mm, sizeof(picoktab_fixed_ids_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - return ktabIdsInitialize(this, common); -} - -picoktab_FixedIds picoktab_getFixedIds(picoknow_KnowledgeBase this) -{ - return ((NULL == this) ? NULL : ((picoktab_FixedIds) this->subObj)); -} - - -picoktab_FixedIds picoktab_newFixedIds(picoos_MemoryManager mm) -{ - picoktab_FixedIds this = (picoktab_FixedIds) picoos_allocate(mm,sizeof(*this)); - if (NULL != this) { - /* initialize */ - } - return this; -} - - -void picoktab_disposeFixedIds(picoos_MemoryManager mm, picoktab_FixedIds * this) -{ - if (NULL != (*this)) { - /* terminate */ - picoos_deallocate(mm,(void *)this); - } -} - - - -/* ************************************************************/ -/* Graphs */ -/* ************************************************************/ - -/* overview binary file format for graphs kb: - - graphs-kb = NROFSENTRIES SIZEOFSENTRY ofstable graphs - - NROFSENTRIES : 2 bytes, number of entries in offset table - SIZEOFSENTRY : 1 byte, size of one entry in offset table - - ofstable = {OFFSET}=NROFSENTRIES (contains NROFSENTRIES entries of OFFSET) - - OFFSET: SIZEOFSENTRY bytes, offset to baseaddress of graphs-kb to entry in graphs - - graphs = {graph}=NROFSENTRIES (contains NROFSENTRIES entries of graph) - - graph = PROPSET FROM TO [TOKENTYPE] [TOKENSUBTYPE] [VALUE] [LOWERCASE] [GRAPHSUBS1] [GRAPHSUBS2] - - FROM : 1..4 unsigned bytes, UTF8 character without terminating 0 - TO : 1..4 unsigned bytes, UTF8 character without terminating 0 - PROPSET : 1 unsigned byte, least significant bit : has TO field - next bit : has TOKENTYPE - next bit : has TOKENSUBTYPE - next bit : has VALUE - next bit : has LOWERCASE - next bit : has GRAPHSUBS1 - next bit : has GRAPHSUBS2 - next bit : has PUNC - - TOKENTYPE : 1 unsigned byte - TOKENSUBTYPE : 1 unsigned byte - VALUE : 1 unsigned byte - LOWERCASE : 1..4 unsigned bytes, UTF8 character without terminating 0 - GRAPHSUBS1 : 1..4 unsigned bytes, UTF8 character without terminating 0 - GRAPHSUBS2 : 1..4 unsigned bytes, UTF8 character without terminating 0 - PUNC : 1 unsigned byte -*/ - -static picoos_uint32 ktab_propOffset (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uint32 prop); - -#define KTAB_START_GRAPHS_NR_OFFSET 0 -#define KTAB_START_GRAPHS_SIZE_OFFSET 2 -#define KTAB_START_GRAPHS_OFFSET_TABLE 3 -#define KTAB_START_GRAPHS_GRAPH_TABLE 0 - -/* bitmasks to extract the grapheme properties info from the property set */ -#define KTAB_GRAPH_PROPSET_TO ((picoos_uint8)'\x01') -#define KTAB_GRAPH_PROPSET_TOKENTYPE ((picoos_uint8)'\x02') -#define KTAB_GRAPH_PROPSET_TOKENSUBTYPE ((picoos_uint8)'\x04') -#define KTAB_GRAPH_PROPSET_VALUE ((picoos_uint8)'\x08') -#define KTAB_GRAPH_PROPSET_LOWERCASE ((picoos_uint8)'\x010') -#define KTAB_GRAPH_PROPSET_GRAPHSUBS1 ((picoos_uint8)'\x020') -#define KTAB_GRAPH_PROPSET_GRAPHSUBS2 ((picoos_uint8)'\x040') -#define KTAB_GRAPH_PROPSET_PUNCT ((picoos_uint8)'\x080') - - -typedef struct ktabgraphs_subobj *ktabgraphs_SubObj; - -typedef struct ktabgraphs_subobj { - picoos_uint16 nrOffset; - picoos_uint16 sizeOffset; - - picoos_uint8 * offsetTable; - picoos_uint8 * graphTable; -} ktabgraphs_subobj_t; - - - -static pico_status_t ktabGraphsInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) { - ktabgraphs_subobj_t * ktabgraphs; - - PICODBG_DEBUG(("start")); - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - ktabgraphs = (ktabgraphs_subobj_t *) this->subObj; - ktabgraphs->nrOffset = ((int)(this->base[KTAB_START_GRAPHS_NR_OFFSET])) + 256*(int)(this->base[KTAB_START_GRAPHS_NR_OFFSET+1]); - ktabgraphs->sizeOffset = (int)(this->base[KTAB_START_GRAPHS_SIZE_OFFSET]); - ktabgraphs->offsetTable = &(this->base[KTAB_START_GRAPHS_OFFSET_TABLE]); - ktabgraphs->graphTable = &(this->base[KTAB_START_GRAPHS_GRAPH_TABLE]); - return PICO_OK; -} - -static pico_status_t ktabGraphsSubObjDeallocate(register picoknow_KnowledgeBase this, - picoos_MemoryManager mm) { - if (NULL != this) { - picoos_deallocate(mm, (void *) &this->subObj); - } - return PICO_OK; -} - - -pico_status_t picoktab_specializeGraphsKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common) { - if (NULL == this) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - this->subDeallocate = ktabGraphsSubObjDeallocate; - this->subObj = picoos_allocate(common->mm, sizeof(ktabgraphs_subobj_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - return ktabGraphsInitialize(this, common); -} - - -picoktab_Graphs picoktab_getGraphs(picoknow_KnowledgeBase this) { - if (NULL == this) { - return NULL; - } else { - return (picoktab_Graphs) this->subObj; - } -} - - -/* Graphs methods */ - -picoos_uint8 picoktab_hasVowellikeProp(const picoktab_Graphs this, - const picoos_uint8 *graph, - const picoos_uint8 graphlenmax) { - - picoos_uint8 ui8App; - picoos_uint32 graphsOffset; - ktabgraphs_subobj_t * g = (ktabgraphs_SubObj)this; - - ui8App = graphlenmax; /* avoid warning "var not used in this function"*/ - - graphsOffset = picoktab_graphOffset (this, (picoos_uchar *)graph); - return g->graphTable[graphsOffset + ktab_propOffset (this, graphsOffset, KTAB_GRAPH_PROPSET_TOKENTYPE)] == PICODATA_ITEMINFO1_TOKTYPE_LETTERV; -} - - -static void ktab_getStrProp (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uint32 propOffset, picoos_uchar * str) -{ - ktabgraphs_subobj_t * g = (ktabgraphs_SubObj)this; - picoos_uint32 i, l; - - i = 0; - l = picobase_det_utf8_length(g->graphTable[graphsOffset+propOffset]); - while (igraphTable[graphsOffset+propOffset+i]; - i++; - } - str[l] = 0; -} - - -static picoos_uint32 ktab_propOffset(const picoktab_Graphs this, - picoos_uint32 graphsOffset, picoos_uint32 prop) -/* Returns offset of property 'prop' inside the graph with offset 'graphsOffset' in graphs table; - If the property is found, a value > 0 is returned otherwise 0 */ -{ - picoos_uint32 n = 0; - ktabgraphs_subobj_t * g = (ktabgraphs_SubObj) this; - - if ((g->graphTable[graphsOffset] & prop) == prop) { - n = n + 1; /* overread PROPSET field */ - n = n + picobase_det_utf8_length(g->graphTable[graphsOffset+n]); /* overread FROM field */ - if (prop > KTAB_GRAPH_PROPSET_TO) { - if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_TO) - == KTAB_GRAPH_PROPSET_TO) { - n = n + picobase_det_utf8_length(g->graphTable[graphsOffset+n]); /* overread TO field */ - } - } else { - return n; - } - if (prop > KTAB_GRAPH_PROPSET_TOKENTYPE) { - if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_TOKENTYPE) - == KTAB_GRAPH_PROPSET_TOKENTYPE) { - n = n + 1; /* overread TOKENTYPE field */ - } - } else { - return n; - } - if (prop > KTAB_GRAPH_PROPSET_TOKENSUBTYPE) { - if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_TOKENSUBTYPE) - == KTAB_GRAPH_PROPSET_TOKENSUBTYPE) { - n = n + 1; /* overread stokentype field */ - } - } else { - return n; - } - if (prop > KTAB_GRAPH_PROPSET_VALUE) { - if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_VALUE) - == KTAB_GRAPH_PROPSET_VALUE) { - n = n + 1; /* overread value field */ - } - } else { - return n; - } - if (prop > KTAB_GRAPH_PROPSET_LOWERCASE) { - if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_LOWERCASE) - == KTAB_GRAPH_PROPSET_LOWERCASE) { - n = n + picobase_det_utf8_length(g->graphTable[graphsOffset+n]); /* overread lowercase field */ - } - } else { - return n; - } - if (prop > KTAB_GRAPH_PROPSET_GRAPHSUBS1) { - if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_GRAPHSUBS1) - == KTAB_GRAPH_PROPSET_GRAPHSUBS1) { - n = n + picobase_det_utf8_length(g->graphTable[graphsOffset+n]); /* overread graphsubs1 field */ - } - } else { - return n; - } - if (prop > KTAB_GRAPH_PROPSET_GRAPHSUBS2) { - if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_GRAPHSUBS2) - == KTAB_GRAPH_PROPSET_GRAPHSUBS2) { - n = n + picobase_det_utf8_length(g->graphTable[graphsOffset+n]); /* overread graphsubs2 field */ - } - } else { - return n; - } - if (prop > KTAB_GRAPH_PROPSET_PUNCT) { - if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_PUNCT) - == KTAB_GRAPH_PROPSET_PUNCT) { - n = n + 1; /* overread value field */ - } - } else { - return n; - } - } - - return n; -} - - -picoos_uint32 picoktab_graphOffset (const picoktab_Graphs this, picoos_uchar * utf8graph) -{ ktabgraphs_subobj_t * g = (ktabgraphs_SubObj)this; - picoos_int32 a, b, m; - picoos_uint32 graphsOffset; - picoos_uint32 propOffset; - picobase_utf8char from; - picobase_utf8char to; - picoos_bool utfGEfrom; - picoos_bool utfLEto; - - if (g->nrOffset > 0) { - a = 0; - b = g->nrOffset-1; - do { - m = (a+b) / 2; - - /* get offset to graph[m] */ - if (g->sizeOffset == 1) { - graphsOffset = g->offsetTable[g->sizeOffset*m]; - } - else { - graphsOffset = g->offsetTable[g->sizeOffset*m ] + - 256*g->offsetTable[g->sizeOffset*m + 1]; - /* PICODBG_DEBUG(("picoktab_graphOffset: %i %i %i %i", m, g->offsetTable[g->sizeOffset*m], g->offsetTable[g->sizeOffset*m + 1], graphsOffset)); - */ - } - - /* get FROM and TO field of graph[m] */ - ktab_getStrProp(this, graphsOffset, 1, from); - propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_TO); - if (propOffset > 0) { - ktab_getStrProp(this, graphsOffset, propOffset, to); - } - else { - picoos_strcpy((picoos_char *)to, (picoos_char *)from); - } - - /* PICODBG_DEBUG(("picoktab_graphOffset: %i %i %i '%s' '%s' '%s'", a, m, b, from, utf8graph, to)); - */ - utfGEfrom = picoos_strcmp((picoos_char *)utf8graph, (picoos_char *)from) >= 0; - utfLEto = picoos_strcmp((picoos_char *)utf8graph, (picoos_char *)to) <= 0; - - if (utfGEfrom && utfLEto) { - /* PICODBG_DEBUG(("picoktab_graphOffset: utf char '%s' found", utf8graph)); - */ - return graphsOffset; - } - if (!utfGEfrom) { - b = m-1; - } - else if (!utfLEto) { - a = m+1; - } - } while (a<=b); - } - PICODBG_DEBUG(("picoktab_graphOffset: utf char '%s' not found", utf8graph)); - return 0; -} - - - - -picoos_bool picoktab_getIntPropTokenType (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uint8 * stokenType) -{ - picoos_uint32 propOffset; - ktabgraphs_subobj_t * g = (ktabgraphs_SubObj)this; - - propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_TOKENTYPE); - if (propOffset > 0) { - *stokenType = (picoos_uint8)(g->graphTable[graphsOffset+propOffset]); - return TRUE; - } - else { - return FALSE; - } -} - - -picoos_bool picoktab_getIntPropTokenSubType (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_int8 * stokenSubType) -{ - picoos_uint32 propOffset; - ktabgraphs_subobj_t * g = (ktabgraphs_SubObj)this; - - propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_TOKENSUBTYPE); - if (propOffset > 0) { - *stokenSubType = (picoos_int8)(g->graphTable[graphsOffset+propOffset]); - return TRUE; - } - else { - return FALSE; - } -} - -picoos_bool picoktab_getIntPropValue (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uint32 * value) -{ - picoos_uint32 propOffset; - ktabgraphs_subobj_t * g = (ktabgraphs_SubObj)this; - - propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_VALUE); - if (propOffset > 0) { - *value = (picoos_uint32)(g->graphTable[graphsOffset+propOffset]); - return TRUE; - } - else { - return FALSE; - } -} - - -picoos_bool picoktab_getIntPropPunct (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uint8 * info1, picoos_uint8 * info2) -{ - picoos_uint32 propOffset; - ktabgraphs_subobj_t * g = (ktabgraphs_SubObj)this; - - propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_PUNCT); - if (propOffset > 0) { - if (g->graphTable[graphsOffset+propOffset] == 2) { - *info1 = PICODATA_ITEMINFO1_PUNC_SENTEND; - } - else { - *info1 = PICODATA_ITEMINFO1_PUNC_PHRASEEND; - } - if (g->graphTable[graphsOffset+1] == '.') { - *info2 = PICODATA_ITEMINFO2_PUNC_SENT_T; - } - else if (g->graphTable[graphsOffset+1] == '?') { - *info2 = PICODATA_ITEMINFO2_PUNC_SENT_Q; - } - else if (g->graphTable[graphsOffset+1] == '!') { - *info2 = PICODATA_ITEMINFO2_PUNC_SENT_E; - } - else { - *info2 = PICODATA_ITEMINFO2_PUNC_PHRASE; - } - return TRUE; - } - else { - return FALSE; - } -} - - -picoos_bool picoktab_getStrPropLowercase (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uchar * lowercase) -{ - picoos_uint32 propOffset; - - propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_LOWERCASE); - if (propOffset > 0) { - ktab_getStrProp(this, graphsOffset, propOffset, lowercase); - return TRUE; - } - else { - return FALSE; - } -} - - -picoos_bool picoktab_getStrPropGraphsubs1 (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uchar * graphsubs1) -{ - picoos_uint32 propOffset; - - propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_GRAPHSUBS1); - if (propOffset > 0) { - ktab_getStrProp(this, graphsOffset, propOffset, graphsubs1); - return TRUE; - } - else { - return FALSE; - } -} - - -picoos_bool picoktab_getStrPropGraphsubs2 (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uchar * graphsubs2) -{ - picoos_uint32 propOffset; - - propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_GRAPHSUBS2); - if (propOffset > 0) { - ktab_getStrProp(this, graphsOffset, propOffset, graphsubs2); - return TRUE; - } - else { - return FALSE; - } -} -/* *****************************************************************/ -/* used for tools */ - -static void ktab_getUtf8 (picoos_uchar ** pos, picoos_uchar * to) -{ - picoos_uint32 l; - l = picobase_det_utf8_length(**pos); - while (l>0) { - *(to++) = *((*pos)++); - l--; - } - *to = 0; -} - -picoos_uint16 picoktab_graphsGetNumEntries(const picoktab_Graphs this) -{ - ktabgraphs_subobj_t * g = (ktabgraphs_SubObj) this; - return g->nrOffset; -} - -void picoktab_graphsGetGraphInfo(const picoktab_Graphs this, - picoos_uint16 graphIndex, picoos_uchar * from, picoos_uchar * to, - picoos_uint8 * propset, - picoos_uint8 * stokenType, picoos_uint8 * stokenSubType, - picoos_uint8 * value, picoos_uchar * lowercase, - picoos_uchar * graphsubs1, picoos_uchar * graphsubs2, - picoos_uint8 * punct) { - ktabgraphs_subobj_t * g = (ktabgraphs_SubObj) this; - picoos_uint32 graphsOffset; - picoos_uint8 * pos; - - /* calculate offset of graph[graphIndex] */ - if (g->sizeOffset == 1) { - graphsOffset = g->offsetTable[graphIndex]; - } else { - graphsOffset = g->offsetTable[2 * graphIndex] - + (g->offsetTable[2 * graphIndex + 1] << 8); - } - pos = &(g->graphTable[graphsOffset]); - *propset = *pos; - - pos++; /* advance to FROM */ - ktab_getUtf8(&pos, from); /* get FROM and advance */ - if ((*propset) & KTAB_GRAPH_PROPSET_TO) { - ktab_getUtf8(&pos, to); /* get TO and advance */ - } else { - picoos_strcpy((picoos_char *)to, (picoos_char *)from); - } - if ((*propset) & KTAB_GRAPH_PROPSET_TOKENTYPE) { - (*stokenType) = *(pos++); /* get TOKENTYPE and advance */ - } else { - (*stokenType) = -1; - } - if ((*propset) & KTAB_GRAPH_PROPSET_TOKENSUBTYPE) { - (*stokenSubType) = *(pos++); /* get TOKENSUBTYPE and advance */ - } else { - (*stokenSubType) = -1; - } - if ((*propset) & KTAB_GRAPH_PROPSET_VALUE) { - (*value) = *(pos++); /* get VALUE and advance */ - } else { - (*value) = -1; - } - if ((*propset) & KTAB_GRAPH_PROPSET_LOWERCASE) { - ktab_getUtf8(&pos, lowercase); /* get LOWERCASE and advance */ - } else { - lowercase[0] = NULLC; - } - if ((*propset) & KTAB_GRAPH_PROPSET_GRAPHSUBS1) { - ktab_getUtf8(&pos, graphsubs1); /* get GRAPHSUBS1 and advance */ - } else { - graphsubs1[0] = NULLC; - } - if ((*propset) & KTAB_GRAPH_PROPSET_GRAPHSUBS2) { - ktab_getUtf8(&pos, graphsubs2); /* get GRAPHSUBS2 and advance */ - } else { - graphsubs2[0] = NULLC; - } - if ((*propset) & KTAB_GRAPH_PROPSET_PUNCT) { - (*punct) = *(pos++); /* get PUNCT and advance */ - } else { - (*punct) = -1; - } -} - -/* ************************************************************/ -/* Phones */ -/* ************************************************************/ - -/* overview binary file format for phones kb: - - phones-kb = specids propertytable - - specids = PRIMSTRESSID1 SECSTRESSID1 SYLLBOUNDID1 PAUSEID1 WORDBOUNDID1 - RESERVE1 RESERVE1 RESERVE1 - - propertytable = {PHONEPROP2}=256 - - PRIMSTRESSID1: one byte, ID of primary stress - SECSTRESSID1: one byte, ID of secondary stress - SYLLBOUNDID1: one byte, ID of syllable boundary - PAUSEID1: one byte, ID of pause - RESERVE1: reserved for future use - - PHONEPROP2: one byte, max. of 256 phones directly access this table - to check a property for a phone; binary properties - encoded (1 bit per prop) - least significant bit: vowel - next bit: diphth - next bit: glott - next bit: nonsyllvowel - next bit: syllcons - 3 bits spare - */ - -#define KTAB_START_SPECIDS 0 -#define KTAB_IND_PRIMSTRESS 0 -#define KTAB_IND_SECSTRESS 1 -#define KTAB_IND_SYLLBOUND 2 -#define KTAB_IND_PAUSE 3 -#define KTAB_IND_WORDBOUND 4 - -#define KTAB_START_PROPS 8 - - -typedef struct ktabphones_subobj *ktabphones_SubObj; - -typedef struct ktabphones_subobj { - picoos_uint8 *specids; - picoos_uint8 *props; -} ktabphones_subobj_t; - - -/* bitmasks to extract the property info from props */ -#define KTAB_PPROP_VOWEL '\x01' -#define KTAB_PPROP_DIPHTH '\x02' -#define KTAB_PPROP_GLOTT '\x04' -#define KTAB_PPROP_NONSYLLVOWEL '\x08' -#define KTAB_PPROP_SYLLCONS '\x10' - - -static pico_status_t ktabPhonesInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) { - ktabphones_subobj_t * ktabphones; - - PICODBG_DEBUG(("start")); - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - ktabphones = (ktabphones_subobj_t *) this->subObj; - ktabphones->specids = &(this->base[KTAB_START_SPECIDS]); - ktabphones->props = &(this->base[KTAB_START_PROPS]); - return PICO_OK; -} - -static pico_status_t ktabPhonesSubObjDeallocate(register picoknow_KnowledgeBase this, - picoos_MemoryManager mm) { - if (NULL != this) { - picoos_deallocate(mm, (void *) &this->subObj); - } - return PICO_OK; -} - -pico_status_t picoktab_specializePhonesKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common) { - if (NULL == this) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - this->subDeallocate = ktabPhonesSubObjDeallocate; - this->subObj = picoos_allocate(common->mm, sizeof(ktabphones_subobj_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - return ktabPhonesInitialize(this, common); -} - -picoktab_Phones picoktab_getPhones(picoknow_KnowledgeBase this) { - if (NULL == this) { - return NULL; - } else { - return (picoktab_Phones) this->subObj; - } -} - - -/* Phones methods */ - -picoos_uint8 picoktab_hasVowelProp(const picoktab_Phones this, - const picoos_uint8 ch) { - return (KTAB_PPROP_VOWEL & ((ktabphones_SubObj)this)->props[ch]); -} -picoos_uint8 picoktab_hasDiphthProp(const picoktab_Phones this, - const picoos_uint8 ch) { - return (KTAB_PPROP_DIPHTH & ((ktabphones_SubObj)this)->props[ch]); -} -picoos_uint8 picoktab_hasGlottProp(const picoktab_Phones this, - const picoos_uint8 ch) { - return (KTAB_PPROP_GLOTT & ((ktabphones_SubObj)this)->props[ch]); -} -picoos_uint8 picoktab_hasNonsyllvowelProp(const picoktab_Phones this, - const picoos_uint8 ch) { - return (KTAB_PPROP_NONSYLLVOWEL & ((ktabphones_SubObj)this)->props[ch]); -} -picoos_uint8 picoktab_hasSyllconsProp(const picoktab_Phones this, - const picoos_uint8 ch) { - return (KTAB_PPROP_SYLLCONS & ((ktabphones_SubObj)this)->props[ch]); -} - -picoos_bool picoktab_isSyllCarrier(const picoktab_Phones this, - const picoos_uint8 ch) { - picoos_uint8 props; - props = ((ktabphones_SubObj)this)->props[ch]; - return (((KTAB_PPROP_VOWEL & props) && - !(KTAB_PPROP_NONSYLLVOWEL & props)) - || (KTAB_PPROP_SYLLCONS & props)); -} - -picoos_bool picoktab_isPrimstress(const picoktab_Phones this, - const picoos_uint8 ch) { - return (ch == ((ktabphones_SubObj)this)->specids[KTAB_IND_PRIMSTRESS]); -} -picoos_bool picoktab_isSecstress(const picoktab_Phones this, - const picoos_uint8 ch) { - return (ch == ((ktabphones_SubObj)this)->specids[KTAB_IND_SECSTRESS]); -} -picoos_bool picoktab_isSyllbound(const picoktab_Phones this, - const picoos_uint8 ch) { - return (ch == ((ktabphones_SubObj)this)->specids[KTAB_IND_SYLLBOUND]); -} -picoos_bool picoktab_isWordbound(const picoktab_Phones this, - const picoos_uint8 ch) { - return (ch == ((ktabphones_SubObj)this)->specids[KTAB_IND_WORDBOUND]); -} -picoos_bool picoktab_isPause(const picoktab_Phones this, - const picoos_uint8 ch) { - return (ch == ((ktabphones_SubObj)this)->specids[KTAB_IND_PAUSE]); -} - -picoos_uint8 picoktab_getPrimstressID(const picoktab_Phones this) { - return ((ktabphones_SubObj)this)->specids[KTAB_IND_PRIMSTRESS]; -} -picoos_uint8 picoktab_getSecstressID(const picoktab_Phones this) { - return ((ktabphones_SubObj)this)->specids[KTAB_IND_SECSTRESS]; -} -picoos_uint8 picoktab_getSyllboundID(const picoktab_Phones this) { - return ((ktabphones_SubObj)this)->specids[KTAB_IND_SYLLBOUND]; -} -picoos_uint8 picoktab_getWordboundID(const picoktab_Phones this) { - return ((ktabphones_SubObj)this)->specids[KTAB_IND_WORDBOUND]; -} -picoos_uint8 picoktab_getPauseID(const picoktab_Phones this) { - return ((ktabphones_SubObj)this)->specids[KTAB_IND_PAUSE]; -} - -/* ************************************************************/ -/* Pos */ -/* ************************************************************/ - -/* overview binary file format for pos kb: - - pos-kb = header posids - header = {COUNT2 OFFS2}=8 - posids = {POSID1 {PARTID1}0:8}1: - - where POSID1 is the value of the (combined) part-of-speech symbol, - and {PARTID1} are the symbol values of its components (empty if it - is not a combined symbol). The {PARTID1} list is sorted. - Part-of-speech symbols with equal number of components are grouped - together. - - The header contains information about these groups: - - COUNT2 specifies the number of elements in the group, and OFFS2 - specifies the offset (relative to the beginning of the kb) where - the group data starts, i.e.: - - 25 32 -> 25 not-combined elements, starting at offset 32 - 44 57 -> 44 elements composed of 2 symbols, starting at offset 57 - 23 189 -> 23 elements composed of 3 symbols, starting at offset 189 - ... - - Currently, each symbol may be composed of up to 8 other symbols. - Therefore, the header has 8 entries, too. The header starts with - the unique POS list, and then in increasing order, 2 symbols, 3 - symbols,... - -Zur Anschauung die ge-printf-te Version: - - 25 32 - 44 57 - 23 189 - 12 281 - 4 341 - 1 365 - 0 0 - 0 0 - 33 | - 34 | - 35 | - 60 | - etc. - 36 | 35 60 - 50 | 35 95 - 51 | 35 97 - 58 | 35 120 - 59 | 35 131 - 61 | 60 75 - 63 | 60 95 - 64 | 60 97 - etc. - 42 | 35 60 117 - 44 | 35 60 131 - 45 | 35 73 97 - 48 | 35 84 97 - 54 | 35 97 131 - 56 | 35 113 120 - 57 | 35 117 120 - 62 | 60 84 122 - etc. - */ - -typedef struct ktabpos_subobj *ktabpos_SubObj; - -typedef struct ktabpos_subobj { - picoos_uint16 nrcomb[PICOKTAB_MAXNRPOS_IN_COMB]; - picoos_uint8 *nrcombstart[PICOKTAB_MAXNRPOS_IN_COMB]; -} ktabpos_subobj_t; - - -static pico_status_t ktabPosInitialize(register picoknow_KnowledgeBase this, - picoos_Common common) { - ktabpos_subobj_t *ktabpos; - picoos_uint16 osprev; - picoos_uint16 os, pos; - picoos_uint8 i; - - PICODBG_DEBUG(("start")); - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - ktabpos = (ktabpos_subobj_t *)this->subObj; - - os = 0; - for (i = 0, pos = 0; i < PICOKTAB_MAXNRPOS_IN_COMB; i++, pos += 4) { - ktabpos->nrcomb[i] = ((picoos_uint16)(this->base[pos+1])) << 8 | - this->base[pos]; - if (ktabpos->nrcomb[i] > 0) { - osprev = os; - os = ((picoos_uint16)(this->base[pos+3])) << 8 | this->base[pos+2]; - ktabpos->nrcombstart[i] = &(this->base[os]); - PICODBG_TRACE(("i %d, pos %d, nr %d, osprev %d, os %d", i, pos, - ktabpos->nrcomb[i], osprev, os)); - if (osprev >= os) { - /* cannot be, in a valid kb */ - return picoos_emRaiseException(common->em, - PICO_EXC_FILE_CORRUPT, - NULL, NULL); - } - } else { - if (i == 0) { - /* cannot be, in a valid kb */ - return picoos_emRaiseException(common->em, - PICO_EXC_FILE_CORRUPT, - NULL, NULL); - } - ktabpos->nrcombstart[i] = NULL; - } - } - return PICO_OK; -} - -static pico_status_t ktabPosSubObjDeallocate(register picoknow_KnowledgeBase this, - picoos_MemoryManager mm) { - if (NULL != this) { - picoos_deallocate(mm, (void *) &this->subObj); - } - return PICO_OK; -} - -pico_status_t picoktab_specializePosKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common) { - if (NULL == this) { - return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - this->subDeallocate = ktabPosSubObjDeallocate; - this->subObj = picoos_allocate(common->mm, sizeof(ktabpos_subobj_t)); - if (NULL == this->subObj) { - return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, - NULL, NULL); - } - return ktabPosInitialize(this, common); -} - -picoktab_Pos picoktab_getPos(picoknow_KnowledgeBase this) { - if (NULL == this) { - return NULL; - } else { - return (picoktab_Pos) this->subObj; - } -} - - -/* Pos methods */ - -static picoos_int16 ktab_isEqualPosGroup(const picoos_uint8 *grp1, - const picoos_uint8 *grp2, - picoos_uint8 len) -{ - /* if both, grp1 and grp2 would be sorted in ascending order - we could implement a function picoktab_comparePosGroup in - a similar manner as strcmp */ - - picoos_uint16 i, j, equal; - - equal = 1; - - i = 0; - while (equal && (i < len)) { - /* search grp1[i] in grp2 */ - j = 0; - while ((j < len) && (grp1[i] != grp2[j])) { - j++; - } - equal = (j < len); - i++; - } - - return equal; -} - - -picoos_bool picoktab_isUniquePos(const picoktab_Pos this, - const picoos_uint8 pos) { - ktabpos_subobj_t *ktabpos; - picoos_uint16 i; - - /* speed-up possible with e.g. binary search */ - - ktabpos = (ktabpos_subobj_t *)this; - PICODBG_TRACE(("pos %d, nrcombinations %d", pos, ktabpos->nrcomb[0])); - i = 0; - while ((i < ktabpos->nrcomb[0]) && (pos > ktabpos->nrcombstart[0][i])) { - PICODBG_TRACE(("compare with pos %d at position %d", - ktabpos->nrcombstart[0][i], pos, i)); - i++; - } - return ((i < ktabpos->nrcomb[0]) && (pos == ktabpos->nrcombstart[0][i])); -} - - -picoos_bool picoktab_isPartOfPosGroup(const picoktab_Pos this, - const picoos_uint8 pos, - const picoos_uint8 posgroup) -{ - ktabpos_subobj_t *ktabpos; - picoos_uint8 *grp; - picoos_uint16 i, j, n, s, grplen; - picoos_uint8 *e; - picoos_uint8 found; - - ktabpos = (ktabpos_subobj_t *) this; - - grp = NULL; - found = FALSE; - grplen = 0; - - /* currently, a linear search is required to find 'posgroup'; the - knowledge base should be extended to allow for a faster search */ - - /* treat case i==0, grplen==0, ie. pos == posgroup */ - if (pos == posgroup) { - found = TRUE; - } - - i = 1; - while ((grp == NULL) && (i < PICOKTAB_MAXNRPOS_IN_COMB)) { - n = ktabpos->nrcomb[i]; /* number of entries */ - e = ktabpos->nrcombstart[i]; /* ptr to first entry */ - s = i + 2; /* size of an entry in bytes */ - /* was with while starting at 0: - s = i > 0 ? i + 2 : 1; - */ - j = 0; - while ((grp == NULL) && (j < n)) { - if (posgroup == e[0]) { - grp = e + 1; - grplen = s - 1; - } - e += s; - j++; - } - i++; - } - - /* test if 'pos' is contained in the components of 'posgroup' */ - if (grp != NULL) { - for (i = 0; !found && (i < grplen); i++) { - if (pos == grp[i]) { - found = TRUE; - } - } - - /* just a way to test picoktab_getPosGroup */ - /* - PICODBG_ASSERT(picoktab_getPosGroup(this, grp, grplen) == posgroup); - */ - } - - return found; -} - - -picoos_uint8 picoktab_getPosGroup(const picoktab_Pos this, - const picoos_uint8 *poslist, - const picoos_uint8 poslistlen) -{ - picoos_uint8 poscomb; - ktabpos_subobj_t *ktabpos; - picoos_uint16 i, j, n, s; - picoos_uint8 *e; - - ktabpos = (ktabpos_subobj_t *) this; - poscomb = 0; - - if ((poslistlen > 0) && (poslistlen <= PICOKTAB_MAXNRPOS_IN_COMB)) { - i = poslistlen - 1; - if (i > 0) { - n = ktabpos->nrcomb[i]; /* number of entries */ - e = ktabpos->nrcombstart[i]; /* ptr to first entry */ - s = i + 2; /* size of an entry in bytes */ - j = 0; - while (!poscomb && (j < n)) { - if (ktab_isEqualPosGroup(poslist, e + 1, poslistlen)) { - poscomb = *e; - } - e += s; - j++; - } - if (!poscomb) { - /* combination not found; shouldn't occur if lingware OK! */ - /* contingency solution: take first */ - PICODBG_WARN(("dynamically created POS combination not found in table; taking first (%i)",poslist[0])); - poscomb = poslist[0]; - } - } else { /* not a composed POS */ - poscomb = poslist[0]; - } - } - - return poscomb; -} - -#ifdef __cplusplus -} -#endif - - -/* end */ diff --git a/lib/picoktab.h b/lib/picoktab.h deleted file mode 100644 index 71ba2ab..0000000 --- a/lib/picoktab.h +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 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 picoktab.h - * - * symbol tables needed at runtime - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -/** - * @addtogroup picoktab - - * Symbol tables needed at runtime \n - * -*/ - -#ifndef PICOKTAB_H_ -#define PICOKTAB_H_ - -#include "picoos.h" -#include "picoknow.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* ************************************************************/ -/* fixed IDs type and functions */ -/* ************************************************************/ - -/** object : FixedIds - * shortcut : ids - */ -typedef struct picoktab_fixed_ids * picoktab_FixedIds; - -typedef struct picoktab_fixed_ids { - picoos_uint8 phonStartId; - picoos_uint8 phonTermId; -} picoktab_fixed_ids_t; - -/* to be used by picorsrc only */ -pico_status_t picoktab_specializeIdsKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common); - -picoktab_FixedIds picoktab_getFixedIds(picoknow_KnowledgeBase this); - - -/* ************************************************************/ -/* Graphs type and functions */ -/* ************************************************************/ - -typedef struct picoktab_graphs *picoktab_Graphs; - -/* to be used by picorsrc only */ -pico_status_t picoktab_specializeGraphsKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common); - -/* return kb graphs for usage in PU */ -picoktab_Graphs picoktab_getGraphs(picoknow_KnowledgeBase this); - -/* graph access routine: if the desired graph 'utf8graph' exists in - the graph table a graph offset > 0 is returned, which then can be - used to access the properties */ -picoos_uint32 picoktab_graphOffset(const picoktab_Graphs this, - picoos_uchar * utf8graph); - - -/* check if UTF8 char 'graph' has property vowellike, return non-zero - if 'ch' has the property, 0 otherwise */ -picoos_uint8 picoktab_hasVowellikeProp(const picoktab_Graphs this, - const picoos_uint8 *graph, - const picoos_uint8 graphlenmax); - -/* graph properties access routines: if graph with offset 'graphsOffset' has the - desired property, returns TRUE if 'ch' has the property, FALSE otherwise */ -picoos_bool picoktab_getIntPropTokenType(const picoktab_Graphs this, - picoos_uint32 graphsOffset, - picoos_uint8 *stokenType); -picoos_bool picoktab_getIntPropTokenSubType(const picoktab_Graphs this, - picoos_uint32 graphsOffset, - picoos_int8 *stokenSubType); -picoos_bool picoktab_getIntPropValue(const picoktab_Graphs this, - picoos_uint32 graphsOffset, - picoos_uint32 *value); -picoos_bool picoktab_getStrPropLowercase(const picoktab_Graphs this, - picoos_uint32 graphsOffset, - picoos_uchar *lowercase); -picoos_bool picoktab_getStrPropGraphsubs1(const picoktab_Graphs this, - picoos_uint32 graphsOffset, - picoos_uchar *graphsubs1); -picoos_bool picoktab_getStrPropGraphsubs2(const picoktab_Graphs this, - picoos_uint32 graphsOffset, - picoos_uchar *graphsubs2); -picoos_bool picoktab_getIntPropPunct(const picoktab_Graphs this, - picoos_uint32 graphsOffset, - picoos_uint8 *info1, - picoos_uint8 *info2); - -picoos_uint16 picoktab_graphsGetNumEntries(const picoktab_Graphs this); -void picoktab_graphsGetGraphInfo(const picoktab_Graphs this, - picoos_uint16 graphIndex, picoos_uchar * from, picoos_uchar * to, - picoos_uint8 * propset, - picoos_uint8 * stokenType, picoos_uint8 * stokenSubType, - picoos_uint8 * value, picoos_uchar * lowercase, - picoos_uchar * graphsubs1, picoos_uchar * graphsubs2, - picoos_uint8 * punct); - - -/* ************************************************************/ -/* Phones type and functions */ -/* ************************************************************/ - -/* to be used by picorsrc only */ -pico_status_t picoktab_specializePhonesKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common); - -typedef struct picoktab_phones *picoktab_Phones; - -/* return kb Phones for usage in PU */ -picoktab_Phones picoktab_getPhones(picoknow_KnowledgeBase this); - -/* check if 'ch' has a property, return non-zero if 'ch' has the - property, 0 otherwise */ -picoos_uint8 picoktab_hasVowelProp(const picoktab_Phones this, - const picoos_uint8 ch); -picoos_uint8 picoktab_hasDiphthProp(const picoktab_Phones this, - const picoos_uint8 ch); -picoos_uint8 picoktab_hasGlottProp(const picoktab_Phones this, - const picoos_uint8 ch); -picoos_uint8 picoktab_hasNonsyllvowelProp(const picoktab_Phones this, - const picoos_uint8 ch); -picoos_uint8 picoktab_hasSyllconsProp(const picoktab_Phones this, - const picoos_uint8 ch); - -/* to speed up processing for often used combinations of properties - the following functions are provided, which check if the property - combination is true for 'ch' */ -picoos_bool picoktab_isSyllCarrier(const picoktab_Phones this, - const picoos_uint8 ch); - -/* some properties can be assigned to a single sym only, check if 'ch' - is a special sym, return TRUE if it is the special sym, FALSE - otherwise */ -picoos_bool picoktab_isPrimstress(const picoktab_Phones this, - const picoos_uint8 ch); -picoos_bool picoktab_isSecstress(const picoktab_Phones this, - const picoos_uint8 ch); -picoos_bool picoktab_isSyllbound(const picoktab_Phones this, - const picoos_uint8 ch); -picoos_bool picoktab_isWordbound(const picoktab_Phones this, - const picoos_uint8 ch); -picoos_bool picoktab_isPause(const picoktab_Phones this, - const picoos_uint8 ch); - -/* get specific sym values */ -picoos_uint8 picoktab_getPrimstressID(const picoktab_Phones this); -picoos_uint8 picoktab_getSecstressID(const picoktab_Phones this); -picoos_uint8 picoktab_getSyllboundID(const picoktab_Phones this); -picoos_uint8 picoktab_getWordboundID(const picoktab_Phones this); -picoos_uint8 picoktab_getPauseID(const picoktab_Phones this); - -/* ************************************************************/ -/* Pos type and functions */ -/* ************************************************************/ - -/* to be used by picorsrc only */ -pico_status_t picoktab_specializePosKnowledgeBase(picoknow_KnowledgeBase this, - picoos_Common common); - -typedef struct picoktab_pos *picoktab_Pos; - -#define PICOKTAB_MAXNRPOS_IN_COMB 8 - -/* return kb Pos for usage in PU */ -picoktab_Pos picoktab_getPos(picoknow_KnowledgeBase this); - -/* returns TRUE if 'pos' is the ID of a unique (ie. non-combined) POS, - returns FALSE otherwise */ -picoos_bool picoktab_isUniquePos(const picoktab_Pos this, - const picoos_uint8 pos); - -/* returns TRUE if the non-combined 'pos' is one of the POSes in the - combined POS group 'posgroup, returns FALSE otherwise. Note: if - 'posgroup' is itself non-combined, this function returns TRUE if it - matches with 'pos', and FALSE otherwise */ -picoos_bool picoktab_isPartOfPosGroup(const picoktab_Pos this, - const picoos_uint8 pos, - const picoos_uint8 posgroup); - -/* return the combined POS group ID that is a representative ID for - all the 'poslistlen' POSes (which can be combined themselves) in - poslist. Returns '0' in case of error. */ -picoos_uint8 picoktab_getPosGroup(const picoktab_Pos this, - const picoos_uint8 *poslist, - const picoos_uint8 poslistlen); - -#ifdef __cplusplus -} -#endif - - -#endif /*PICOKTAB_H_*/ diff --git a/lib/picoos.c b/lib/picoos.c deleted file mode 100644 index 4e2b439..0000000 --- a/lib/picoos.c +++ /dev/null @@ -1,2309 +0,0 @@ -/* - * 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 picoos.c - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#include -#include "picodefs.h" -#include "picopal.h" -#include "picoos.h" -#include "picodbg.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -#define picoos_SVOXFileHeader (picoos_char *)" (C) SVOX AG " - -/* ********************************************** - * default error and warning messages - * **********************************************/ - - -#define PICOOS_MSG_EXC_NUMBER_FORMAT (picoos_char *) "wrong number format" -#define PICOOS_MSG_EXC_MAX_NUM_EXCEED (picoos_char *) "number exceeded" -#define PICOOS_MSG_EXC_NAME_CONFLICT (picoos_char *) "name conflict" -#define PICOOS_MSG_EXC_NAME_UNDEFINED (picoos_char *) "name undefined" -#define PICOOS_MSG_EXC_NAME_ILLEGAL (picoos_char *) "illegal name" - -/* buffer interaction */ -#define PICOOS_MSG_EXC_BUF_OVERFLOW (picoos_char *) "buffer overflow" -#define PICOOS_MSG_EXC_BUF_UNDERFLOW (picoos_char *) "buffer underflow" -#define PICOOS_MSG_EXC_BUF_IGNORE (picoos_char *) "buffer error" - -/* memory allocation */ -#define PICOOS_MSG_EXC_OUT_OF_MEM (picoos_char *) "out of memory" - -/* files */ -#define PICOOS_MSG_EXC_CANT_OPEN_FILE (picoos_char *) "cannot open file" -#define PICOOS_MSG_EXC_UNEXPECTED_FILE_TYPE (picoos_char *) "unexpected file type" -#define PICOOS_MSG_EXC_FILE_CORRUPT (picoos_char *) "corrupt file" -#define PICOOS_MSG_EXC_FILE_NOT_FOUND (picoos_char *) "file not found" - -/* resources */ -#define PICOOS_MSG_EXC_RESOURCE_BUSY (picoos_char *) "resource is busy" -#define PICOOS_MSG_EXC_RESOURCE_MISSING (picoos_char *) "cannot find resource" - -/* knowledge bases */ -#define PICOOS_MSG_EXC_KB_MISSING (picoos_char *) "knowledge base missing" - -/* runtime exceptions (programming problems, usually a bug. E.g. trying to access null pointer) */ -#define PICOOS_MSG_ERR_NULLPTR_ACCESS (picoos_char *) "access violation" -#define PICOOS_MSG_ERR_INVALID_HANDLE (picoos_char *) "invalid handle value" -#define PICOOS_MSG_ERR_INVALID_ARGUMENT (picoos_char *) "invalid argument supplied" -#define PICOOS_MSG_ERR_INDEX_OUT_OF_RANGE (picoos_char *) "index out of range" - - -/* errors ("external" errors, e.g. hardware failure. Usually cannot be dealt with from inside pico.) */ -#define PICOOS_MSG_ERR_OTHER (picoos_char *) "other error" - -#define PICOOS_MSG_ERR_PU (picoos_char *) "error in processing unit" - -/* WARNINGS */ - -/* general */ -#define PICOOS_MSG_WARN_INCOMPLETE (picoos_char *) "incomplete output" -#define PICOOS_MSG_WARN_FALLBACK (picoos_char *) "using fall-back" -#define PICOOS_MSG_WARN_OTHER (picoos_char *) "other warning" - -/* resources */ -#define PICOOS_MSG_WARN_KB_OVERWRITE (picoos_char *) "overwriting knowledge base" -#define PICOOS_MSG_WARN_RESOURCE_DOUBLE_LOAD (picoos_char *) "resource already loaded" - -/* decision trees */ -#define PICOOS_MSG_WARN_INVECTOR (picoos_char *) "input vector not constructed" -#define PICOOS_MSG_WARN_CLASSIFICATION (picoos_char *) "output not classified" -#define PICOOS_MSG_WARN_OUTVECTOR (picoos_char *) "output vector not decomposed" - -/* processing units */ -#define PICOOS_MSG_WARN_PU_IRREG_ITEM (picoos_char *) "irregular item in processing unit" -#define PICOOS_MSG_WARN_PU_DISCARD_BUF (picoos_char *) "discarding processing unit buffer" - - -/* ********************************************** - * wrappers for picopal functions - * **********************************************/ - -picoos_int32 picoos_atoi(const picoos_char *s) -{ - return (picoos_int32)picopal_atoi((const picoos_char *)s); -} - - -picoos_int8 picoos_strcmp(const picoos_char *a, const picoos_char *b) -{ - picopal_int32 res = picopal_strcmp((const picopal_char *)a, - (const picopal_char *)b); - return (picoos_int8) ((res < 0) ? -1 : (res > 0) ? 1 : 0); -} -picoos_int8 picoos_strncmp(const picoos_char *a, const picoos_char *b, picoos_objsize_t siz) -{ - picopal_int32 res = picopal_strncmp((const picopal_char *)a, - (const picopal_char *)b, siz); - return (picoos_int8) ((res < 0) ? -1 : (res > 0) ? 1 : 0); -} - -picoos_uint32 picoos_strlen(const picoos_char *s) -{ - return (picoos_uint32)picopal_strlen((const picopal_char *)s); -} - -picoos_char *picoos_strchr(const picoos_char *s, picoos_char c) -{ - return (picoos_char *)picopal_strchr((const picopal_char *)s, - (picopal_char)c); -} - -picoos_char *picoos_strstr(const picoos_char *s, const picoos_char * substr) -{ - return (picoos_char *)picopal_strstr((const picopal_char *)s, - (const picopal_char *)substr); -} - -picoos_int16 picoos_slprintf(picoos_char * b, picoos_uint32 bsize, const picoos_char *f, ...) -{ - picopal_int16 i; - va_list args; - - va_start(args, (char *)f); - i = (picoos_int16)picopal_vslprintf((picoos_char *) b, bsize, (const picoos_char *)f, args); - va_end(args); - return i; -} - -picoos_char *picoos_strcpy(picoos_char *d, const picoos_char *s) -{ - return (picoos_char *)picopal_strcpy((picopal_char *)d, - (const picopal_char *)s); -} - -picoos_char *picoos_strcat(picoos_char *d, const picoos_char *s) -{ - return (picoos_char *)picopal_strcat((picopal_char *)d, - (const picopal_char *)s); -} - -picoos_objsize_t picoos_strlcpy(picoos_char *dst, const picoos_char *src, picoos_objsize_t siz) -{ - return (picoos_objsize_t) picopal_strlcpy((picopal_char *) dst, (const picopal_char *) src, (picopal_objsize_t) siz); -} - -/* copies 'length' bytes from 'src' to 'dest'. (regions may be overlapping) no error checks! */ -void * picoos_mem_copy(const void * src, void * dst, picoos_objsize_t length) -{ - return picopal_mem_copy(src,dst,(picopal_objsize_t) length); -} - -/* sets 'length' bytes starting at dest[0] to 'byte_val' */ -void * picoos_mem_set(void * dest, picoos_uint8 byte_val, picoos_objsize_t length) { - return picopal_mem_set(dest,(picopal_uint8)byte_val, (picopal_objsize_t)length); -} - - -picoos_double picoos_cos (const picoos_double cos_arg) -{ - return (picoos_double) picopal_cos ((picopal_double) cos_arg); -} - - -picoos_double picoos_sin (const picoos_double sin_arg) -{ - return (picoos_double) picopal_sin((picopal_double) sin_arg); -} -picoos_double picoos_fabs (const picoos_double fabs_arg) -{ - return (picoos_double) picopal_fabs((picopal_double) fabs_arg); -} - -picoos_double picoos_quick_exp(const picoos_double y) { - return (picoos_double) picopal_quick_exp ((picopal_double)y); -} - - -/* *****************************************************************/ -/* "Common" */ -/* *****************************************************************/ -/* picoos_common is a collection of basic functionalities that must be globally - * accessible from every "big" function. It includes pointers to the MemoryManasger, - * ExceptionManager and a system-wide list of open files. */ - -picoos_Common picoos_newCommon(picoos_MemoryManager mm) -{ - picoos_Common this = (picoos_Common) picoos_allocate(mm,sizeof(*this)); - if (NULL != this) { - /* initialize */ - this->em = NULL; - this->mm = NULL; - this->fileList = NULL; - } - return this; -} - -void picoos_disposeCommon(picoos_MemoryManager mm, picoos_Common * this) -{ - if (NULL != (*this)) { - /* terminate */ - picoos_deallocate(mm,(void *)this); - } -} - - -/* *****************************************************************/ -/* Memory Management */ -/* *****************************************************************/ - -typedef struct mem_block_hdr * MemBlockHdr; -typedef struct mem_block_hdr -{ - MemBlockHdr next; - byte_ptr_t data; - picoos_objsize_t size; -} mem_block_hdr_t; - -typedef struct mem_cell_hdr * MemCellHdr; -typedef struct mem_cell_hdr -{ - /* size may be <0 if used */ - picoos_ptrdiff_t size; - MemCellHdr leftCell; - MemCellHdr prevFree, nextFree; -} mem_cell_hdr_t; - -typedef struct memory_manager -{ - MemBlockHdr firstBlock, lastBlock; /* memory blockList */ - MemCellHdr freeCells, lastFree; /* free memory cells (first/last sentinel */ - /* "constants" */ - picoos_objsize_t fullCellHdrSize; /* aligned size of full cell header, including free-links */ - picoos_objsize_t usedCellHdrSize; /* aligned size of header part without free-links */ - picoos_objsize_t minContSize; /* minimum requestable application content size for allocation; - must hold free-list info; = fullCellHdrSize-usedCellHdrSize */ - picoos_objsize_t minCellSize; /* minimum remaining cell size when a free cell is split */ - picoos_bool protMem; /* true if memory protection is enabled */ - picoos_ptrdiff_t usedSize; - picoos_ptrdiff_t prevUsedSize; - picoos_ptrdiff_t maxUsedSize; -} memory_manager_t; - -/** allocates 'alloc_size' bytes at start of raw memory block ('raw_mem',raw_mem_size) - * and returns pointer to allocated region. Returns remaining (correctly aligned) raw memory block - * in ('rest_mem','rest_mem_size'). - * The allocated memory is not subject to memory management, so that it can never be freed again! - * - */ -void * picoos_raw_malloc(byte_ptr_t raw_mem, - picoos_objsize_t raw_mem_size, picoos_objsize_t alloc_size, - byte_ptr_t * rest_mem, picoos_objsize_t * rest_mem_size) -{ - picoos_ptrdiff_t rest; - if (raw_mem == NULL) { - return NULL; - } else { - if (alloc_size < 1) { - alloc_size = 1; - } - alloc_size = ((alloc_size + PICOOS_ALIGN_SIZE - 1) / PICOOS_ALIGN_SIZE) - * PICOOS_ALIGN_SIZE; - - rest = raw_mem_size - alloc_size; - if (rest < 0) { - return NULL; - } else { - *rest_mem_size = rest; - *rest_mem = raw_mem + alloc_size; - return (void *) raw_mem; - } - } -} - -/** initializes the last block of mm */ -static int os_init_mem_block(picoos_MemoryManager this) -{ - int isFirstBlock; - void * newBlockAddr; - picoos_objsize_t size; - MemCellHdr cbeg, cmid, cend; - - isFirstBlock = (this->freeCells == NULL); - newBlockAddr = (void *) this->lastBlock->data; - size = this->lastBlock->size; - cbeg = (MemCellHdr) newBlockAddr; - cmid = (MemCellHdr)((picoos_objsize_t)newBlockAddr + this->fullCellHdrSize); - cend = (MemCellHdr)((picoos_objsize_t)newBlockAddr + size - - this->fullCellHdrSize); - cbeg->size = 0; - - cbeg->leftCell = NULL; - cmid->size = size - 2 * this->fullCellHdrSize; - cmid->leftCell = cbeg; - cend->size = 0; - cend->leftCell = cmid; - if (isFirstBlock) { - cbeg->nextFree = cmid; - cbeg->prevFree = NULL; - cmid->nextFree = cend; - cmid->prevFree = cbeg; - cend->nextFree = NULL; - cend->prevFree = cmid; - this->freeCells = cbeg; - this->lastFree = cend; - } else { - /* add cmid to free cell list */ - cbeg->nextFree = NULL; - cbeg->prevFree = NULL; - cmid->nextFree = this->freeCells->nextFree; - cmid->prevFree = this->freeCells; - cmid->nextFree->prevFree = cmid; - cmid->prevFree->nextFree = cmid; - cend->nextFree = NULL; - cbeg->prevFree = NULL; - } - return PICO_OK; -} - - -picoos_MemoryManager picoos_newMemoryManager( - void *raw_memory, - picoos_objsize_t size, - picoos_bool enableMemProt) -{ - byte_ptr_t rest_mem; - picoos_objsize_t rest_mem_size; - picoos_MemoryManager this; - picoos_objsize_t size2; - mem_cell_hdr_t test_cell; - - this = picoos_raw_malloc(raw_memory, size, sizeof(memory_manager_t), - &rest_mem, &rest_mem_size); - if (this == NULL) { - return NULL; - } - - /* test if memory protection functionality is available on the current - platform (if not, picopal_mpr_alloc() always returns NULL) */ - if (enableMemProt) { - void *addr = picopal_mpr_alloc(100); - if (addr == NULL) { - enableMemProt = FALSE; - } else { - picopal_mpr_free(&addr); - } - } - - this->firstBlock = NULL; - this->lastBlock = NULL; - this->freeCells = NULL; - this->lastFree = NULL; - - this->protMem = enableMemProt; - this->usedSize = 0; - this->prevUsedSize = 0; - this->maxUsedSize = 0; - - /* get aligned full header size */ - this->fullCellHdrSize = ((sizeof(mem_cell_hdr_t) + PICOOS_ALIGN_SIZE - 1) - / PICOOS_ALIGN_SIZE) * PICOOS_ALIGN_SIZE; - /* get aligned size of header without free-list fields; the result may be compiler-dependent; - the size is therefore computed by inspecting the end addresses of the fields 'size' and 'leftCell'; - the higher of the ending addresses is used to get the (aligned) starting address - of the application contents */ - this->usedCellHdrSize = (picoos_objsize_t) &test_cell.size - - (picoos_objsize_t) &test_cell + sizeof(picoos_objsize_t); - size2 = (picoos_objsize_t) &test_cell.leftCell - (picoos_objsize_t) - &test_cell + sizeof(MemCellHdr); - if (size2 > this->usedCellHdrSize) { - this->usedCellHdrSize = size2; - } - /* get minimum application-usable size; must be large enough to hold remainder of - cell header (free-list links) when in free-list */ - this->minContSize = this->fullCellHdrSize - this->usedCellHdrSize; - /* get minimum required size of a cell remaining after a cell split */ - this->minCellSize = this->fullCellHdrSize + PICOOS_ALIGN_SIZE; - - /* install remainder of raw memory block as first block */ - raw_memory = rest_mem; - size = rest_mem_size; - this->firstBlock = this->lastBlock = picoos_raw_malloc(raw_memory, size, - sizeof(mem_block_hdr_t), &rest_mem, &rest_mem_size); - if (this->lastBlock == NULL) { - return NULL; - } - this->lastBlock->next = NULL; - this->lastBlock->data = rest_mem; - this->lastBlock->size = rest_mem_size; - - os_init_mem_block(this); - - return this; -} - -void picoos_disposeMemoryManager(picoos_MemoryManager * mm) -{ - *mm = NULL; -} - - -/* the following memory manager routines are for testing and - debugging purposes */ - - -void *picoos_allocProtMem(picoos_MemoryManager mm, picoos_objsize_t byteSize) -{ - if (mm->protMem) { - return picopal_mpr_alloc(byteSize); - } else { - return picoos_allocate(mm, byteSize); - } -} - - -void picoos_deallocProtMem(picoos_MemoryManager mm, void **addr) -{ - if (mm->protMem) { - picopal_mpr_free(addr); - } else { - picoos_deallocate(mm, addr); - } -} - - -void picoos_protectMem( - picoos_MemoryManager mm, - void *addr, - picoos_objsize_t len, - picoos_bool enable) -{ - if (mm->protMem) { - int prot = PICOPAL_PROT_READ; - if (!enable) { - prot |= PICOPAL_PROT_WRITE; - } - picopal_mpr_protect(addr, len, prot); - } else { - /* memory protection disabled; nothing to do */ - } -} - -#define PICOPAL_PROT_NONE 0 /* the memory cannot be accessed at all */ -#define PICOPAL_PROT_READ 1 /* the memory can be read */ -#define PICOPAL_PROT_WRITE 2 /* the memory can be written to */ - -void picoos_getMemUsage( - picoos_MemoryManager this, - picoos_bool resetIncremental, - picoos_int32 *usedBytes, - picoos_int32 *incrUsedBytes, - picoos_int32 *maxUsedBytes) -{ - *usedBytes = (picoos_int32) this->usedSize; - *incrUsedBytes = (picoos_int32) (this->usedSize - this->prevUsedSize); - *maxUsedBytes = (picoos_int32) this->maxUsedSize; - if (resetIncremental) { - this->prevUsedSize = this->usedSize; - } -} - - -void picoos_showMemUsage(picoos_MemoryManager this, picoos_bool incremental, - picoos_bool resetIncremental) -{ - picoos_int32 usedBytes, incrUsedBytes, maxUsedBytes; - - picoos_getMemUsage(this, resetIncremental, &usedBytes, &incrUsedBytes, - &maxUsedBytes); - if (incremental) { - PICODBG_DEBUG(("additional memory used: %d", incrUsedBytes)); - } else { - PICODBG_DEBUG(("memory used: %d, maximally used: %d", usedBytes, maxUsedBytes)); - } -} - - -void * picoos_allocate(picoos_MemoryManager this, - picoos_objsize_t byteSize) -{ - - picoos_objsize_t cellSize; - MemCellHdr c, c2, c2r; - void * adr; - - if (byteSize < this->minContSize) { - byteSize = this->minContSize; - } - byteSize = ((byteSize + PICOOS_ALIGN_SIZE - 1) / PICOOS_ALIGN_SIZE) - * PICOOS_ALIGN_SIZE; - - cellSize = byteSize + this->usedCellHdrSize; - /*PICODBG_TRACE(("allocating %d", cellSize));*/ - c = this->freeCells->nextFree; - while ( - (c != NULL) && - (c->size != (picoos_ptrdiff_t) cellSize) && - (c->size < (picoos_ptrdiff_t)(cellSize+ this->minCellSize))) { - c = c->nextFree; - } - if (c == NULL) { - return NULL; - } - if ((c->size == (picoos_ptrdiff_t) cellSize)) { - c->prevFree->nextFree = c->nextFree; - c->nextFree->prevFree = c->prevFree; - } else { - c2 = (MemCellHdr)((picoos_objsize_t)c + cellSize); - c2->size = c->size - cellSize; - c->size = cellSize; - c2->leftCell = c; - c2r = (MemCellHdr)((picoos_objsize_t)c2 + c2->size); - c2r->leftCell = c2; - c2->nextFree = c->nextFree; - c2->nextFree->prevFree = c2; - c2->prevFree = c->prevFree; - c2->prevFree->nextFree = c2; - } - - /* statistics */ - this->usedSize += cellSize; - if (this->usedSize > this->maxUsedSize) { - this->maxUsedSize = this->usedSize; - } - - c->size = -(c->size); - adr = (void *)((picoos_objsize_t)c + this->usedCellHdrSize); - return adr; -} - -void picoos_deallocate(picoos_MemoryManager this, void * * adr) -{ - MemCellHdr c; - MemCellHdr cr; - MemCellHdr cl; - MemCellHdr crr; - - - if ((*adr) != NULL) { - c = (MemCellHdr)((picoos_objsize_t)(*adr) - this->usedCellHdrSize); - c->size = -(c->size); - - /*PICODBG_TRACE(("deallocating %d", c->size));*/ - /* statistics */ - this->usedSize -= c->size; - - cr = (MemCellHdr)((picoos_objsize_t)c + c->size); - cl = c->leftCell; - if (cl->size > 0) { - if (cr->size > 0) { - crr = (MemCellHdr)((picoos_objsize_t)cr + cr->size); - crr->leftCell = cl; - cl->size = ((cl->size + c->size) + cr->size); - cr->nextFree->prevFree = cr->prevFree; - cr->prevFree->nextFree = cr->nextFree; - } else { - cl->size = (cl->size + c->size); - cr->leftCell = cl; - } - } else { - if ((cr->size > 0)) { - crr = (MemCellHdr)((picoos_objsize_t)cr + cr->size); - crr->leftCell = c; - c->size = (c->size + cr->size); - c->nextFree = cr->nextFree; - c->prevFree = cr->prevFree; - c->nextFree->prevFree = c; - c->prevFree->nextFree = c; - } else { - c->nextFree = this->freeCells->nextFree; - c->prevFree = this->freeCells; - c->nextFree->prevFree = c; - c->prevFree->nextFree = c; - } - } - } - *adr = NULL; -} - -/* *****************************************************************/ -/* Exception Management */ -/* *****************************************************************/ -/** object : exceptionManager - * shortcut : em - * - */ - -typedef picoos_char picoos_exc_msg[PICOOS_MAX_EXC_MSG_LEN]; -typedef picoos_char picoos_warn_msg[PICOOS_MAX_WARN_MSG_LEN]; - -typedef struct picoos_exception_manager -{ - picoos_int32 curExceptionCode; - picoos_exc_msg curExceptionMessage; - - picoos_uint8 curNumWarnings; - picoos_int32 curWarningCode[PICOOS_MAX_NUM_WARNINGS]; - picoos_warn_msg curWarningMessage[PICOOS_MAX_NUM_WARNINGS]; - -} picoos_exception_manager_t; - -void picoos_emReset(picoos_ExceptionManager this) -{ - this->curExceptionCode = PICO_OK; - this->curExceptionMessage[0] = '\0'; - this->curNumWarnings = 0; -} - -picoos_ExceptionManager picoos_newExceptionManager(picoos_MemoryManager mm) -{ - picoos_ExceptionManager this = (picoos_ExceptionManager) picoos_allocate( - mm, sizeof(*this)); - if (NULL != this) { - /* initialize */ - picoos_emReset(this); - } - return this; -} - -void picoos_disposeExceptionManager(picoos_MemoryManager mm, - picoos_ExceptionManager * this) -{ - if (NULL != (*this)) { - /* terminate */ - picoos_deallocate(mm, (void *)this); - } -} - -static void picoos_vSetErrorMsg(picoos_char * dst, picoos_objsize_t siz, - picoos_int16 code, picoos_char * base, const picoos_char *fmt, va_list args) -{ - picoos_uint16 bsize; - - if (NULL == base) { - switch (code) { - case PICO_EXC_NUMBER_FORMAT: - base = PICOOS_MSG_EXC_NUMBER_FORMAT; - break; - case PICO_EXC_MAX_NUM_EXCEED: - base = PICOOS_MSG_EXC_MAX_NUM_EXCEED; - break; - case PICO_EXC_NAME_CONFLICT: - base = PICOOS_MSG_EXC_NAME_CONFLICT; - break; - case PICO_EXC_NAME_UNDEFINED: - base = PICOOS_MSG_EXC_NAME_UNDEFINED; - break; - case PICO_EXC_NAME_ILLEGAL: - base = PICOOS_MSG_EXC_NAME_ILLEGAL; - break; - - /* buffer interaction */ - case PICO_EXC_BUF_OVERFLOW: - base = PICOOS_MSG_EXC_BUF_OVERFLOW; - break; - case PICO_EXC_BUF_UNDERFLOW: - base = PICOOS_MSG_EXC_BUF_UNDERFLOW; - break; - case PICO_EXC_BUF_IGNORE: - base = PICOOS_MSG_EXC_BUF_IGNORE; - break; - - /* memory allocation */ - case PICO_EXC_OUT_OF_MEM: - base = PICOOS_MSG_EXC_OUT_OF_MEM; - break; - - /* files */ - case PICO_EXC_CANT_OPEN_FILE: - base = PICOOS_MSG_EXC_CANT_OPEN_FILE; - break; - case PICO_EXC_UNEXPECTED_FILE_TYPE: - base = PICOOS_MSG_EXC_UNEXPECTED_FILE_TYPE; - break; - case PICO_EXC_FILE_CORRUPT: - base = PICOOS_MSG_EXC_FILE_CORRUPT; - break; - - case PICO_EXC_FILE_NOT_FOUND: - base = PICOOS_MSG_EXC_FILE_NOT_FOUND; - break; - - /* resources */ - case PICO_EXC_RESOURCE_BUSY: - base = PICOOS_MSG_EXC_RESOURCE_BUSY; - break; - case PICO_EXC_RESOURCE_MISSING: - base = PICOOS_MSG_EXC_RESOURCE_MISSING; - break; - - /* knowledge bases */ - case PICO_EXC_KB_MISSING: - fmt = PICOOS_MSG_EXC_KB_MISSING; - break; - - /* runtime exceptions (programming problems, usually a bug. E.g. trying to access null pointer) */ - case PICO_ERR_NULLPTR_ACCESS: - base = PICOOS_MSG_ERR_NULLPTR_ACCESS; - break; - case PICO_ERR_INVALID_HANDLE: - base = PICOOS_MSG_ERR_INVALID_HANDLE; - break; - case PICO_ERR_INVALID_ARGUMENT: - base = PICOOS_MSG_ERR_INVALID_ARGUMENT; - break; - case PICO_ERR_INDEX_OUT_OF_RANGE: - base = PICOOS_MSG_ERR_INDEX_OUT_OF_RANGE; - break; - - /* errors ("external" errors, e.g. hardware failure. Usually cannot be dealt with from inside pico.) */ - case PICO_ERR_OTHER: - base = PICOOS_MSG_ERR_OTHER; - break; - - /* other error inside pu */ - case PICO_STEP_ERROR: - base = PICOOS_MSG_ERR_PU; - break; - - /* WARNINGS */ - - /* general */ - case PICO_WARN_INCOMPLETE: - base = PICOOS_MSG_WARN_INCOMPLETE; - break; - case PICO_WARN_FALLBACK: - base = PICOOS_MSG_WARN_FALLBACK; - break; - - case PICO_WARN_OTHER: - base = PICOOS_MSG_WARN_OTHER; - break; - - /* resources */ - case PICO_WARN_KB_OVERWRITE: - base = PICOOS_MSG_WARN_KB_OVERWRITE; - break; - case PICO_WARN_RESOURCE_DOUBLE_LOAD: - base = PICOOS_MSG_WARN_RESOURCE_DOUBLE_LOAD; - break; - - /* decision trees */ - case PICO_WARN_INVECTOR: - base = PICOOS_MSG_WARN_INVECTOR; - break; - case PICO_WARN_CLASSIFICATION: - base = PICOOS_MSG_WARN_CLASSIFICATION; - break; - case PICO_WARN_OUTVECTOR: - base = PICOOS_MSG_WARN_OUTVECTOR; - break; - - /* processing units */ - case PICO_WARN_PU_IRREG_ITEM: - base = PICOOS_MSG_WARN_PU_IRREG_ITEM; - break; - case PICO_WARN_PU_DISCARD_BUF: - base = PICOOS_MSG_WARN_PU_DISCARD_BUF; - break; - - default: - base = (picoos_char *) "unknown error"; - break; - } - } - bsize = picoos_strlcpy(dst,base,siz); - if ((NULL != fmt) && (bsize < siz)) { /* there is something to add and more space to add it */ - if (bsize > 0) { - dst += bsize; - siz -= bsize; - bsize = picoos_strlcpy(dst,(picoos_char *)": ",siz); - } - if (bsize < siz) { - picopal_vslprintf((picopal_char *) dst + bsize, siz - bsize, (picopal_char *)fmt, args); - } - } -} - -void picoos_setErrorMsg(picoos_char * dst, picoos_objsize_t siz, - picoos_int16 code, picoos_char * base, const picoos_char *fmt, ...) -{ - va_list args; - va_start(args, (char *)fmt); - picoos_vSetErrorMsg(dst,siz, code, base, fmt,args); - va_end(args); -} - -/* For convenience, this function returns the resulting current exception code. The return value therefore is NOT the status of raising - * the error! */ -pico_status_t picoos_emRaiseException(picoos_ExceptionManager this, - pico_status_t exceptionCode, picoos_char * baseMessage, picoos_char * fmt, ...) -{ - va_list args; - - - if (PICO_OK == this->curExceptionCode && PICO_OK != exceptionCode) { - this->curExceptionCode = exceptionCode; - va_start(args, (char *)fmt); - picoos_vSetErrorMsg(this->curExceptionMessage,PICOOS_MAX_EXC_MSG_LEN, exceptionCode, baseMessage, fmt,args); - PICODBG_DEBUG(( - "exit with exception code=%i, exception message='%s'", - this->curExceptionCode, this->curExceptionMessage)); - - va_end(args); - - } - return this->curExceptionCode; -} - -pico_status_t picoos_emGetExceptionCode(picoos_ExceptionManager this) -{ - return this->curExceptionCode; -} - -void picoos_emGetExceptionMessage(picoos_ExceptionManager this, picoos_char * msg, picoos_uint16 maxsize) -{ - picoos_strlcpy(msg,this->curExceptionMessage,maxsize); -} - -void picoos_emRaiseWarning(picoos_ExceptionManager this, - pico_status_t warningCode, picoos_char * baseMessage, picoos_char * fmt, ...) -{ - va_list args; - if ((this->curNumWarnings < PICOOS_MAX_NUM_WARNINGS) && (PICO_OK != warningCode)) { - if (PICOOS_MAX_NUM_WARNINGS-1 == this->curNumWarnings) { - this->curWarningCode[this->curNumWarnings] = PICO_EXC_MAX_NUM_EXCEED; - picoos_strlcpy(this->curWarningMessage[this->curNumWarnings],(picoos_char *) "too many warnings",PICOOS_MAX_WARN_MSG_LEN); - } else { - this->curWarningCode[this->curNumWarnings] = warningCode; - va_start(args, (char *)fmt); - picoos_vSetErrorMsg(this->curWarningMessage[this->curNumWarnings],PICOOS_MAX_WARN_MSG_LEN, warningCode, baseMessage, fmt,args); - va_end(args); - } - this->curNumWarnings++; - } - PICODBG_DEBUG(( - "exit with code=%i and message='%s', resulting in #warnings=%i", - this->curWarningCode[this->curNumWarnings-1], - this->curWarningMessage[this->curNumWarnings-1], - this->curNumWarnings)); -} - -picoos_uint8 picoos_emGetNumOfWarnings(picoos_ExceptionManager this) -{ - return this->curNumWarnings; -} - -pico_status_t picoos_emGetWarningCode(picoos_ExceptionManager this, picoos_uint8 index) -{ - if (index < this->curNumWarnings) { - return this->curWarningCode[index]; - } else { - return PICO_OK; - } -} - -void picoos_emGetWarningMessage(picoos_ExceptionManager this, picoos_uint8 index, picoos_char * msg, picoos_uint16 maxsize) -{ - if (index < this->curNumWarnings) { - picoos_strlcpy(msg,this->curWarningMessage[index],maxsize); - } else { - msg[0] = NULLC; - } -} - - - - -/* *****************************************************************/ -/* File Access */ -/* *****************************************************************/ - -#define picoos_MagicNumber 192837465 -#define picoos_MaxBufSize 1000000 -#define picoos_MaxNrOfBuffers 1000000 -#define picoos_MaxBufLen 8192 -#define picoos_HashFuncId0 0 -#define picoos_HashTableSize0 101 -#define picoos_HashTableSize1 1731 -#define picoos_MaxHashTableSize HashTableSize1 - -#define cardinal_ptr_t picoos_uint32 * - -typedef struct picoos_buffer -{ - picoos_char * data; - int start; /* denotes the file position of the buffer beginning */ - int len; /* denotes the length of the buffer; -1 means invalid buffer */ - int pos; /* denotes the position in the buffer */ -} picoos_buffer_t; - -typedef picoos_buffer_t picoos_buffer_array_t[picoos_MaxNrOfBuffers]; -typedef picoos_int32 picoos_buffer_index_array_t[picoos_MaxNrOfBuffers]; - -/** object : File - * shortcut : f - * - */ -typedef struct picoos_file -{ - picoos_FileName name; - picoos_uint8 binary; - picoos_uint8 write; - - picopal_File nf; - - picoos_uint32 lFileLen; - picoos_uint32 lPos; - - picoos_File next; - picoos_File prev; - -} picoos_file_t; - -picoos_File picoos_newFile(picoos_MemoryManager mm) -{ - picoos_File this = (picoos_File) picoos_allocate(mm, sizeof(*this)); - if (NULL != this) { - /* initialize */ - } - return this; -} - -void picoos_disposeFile(picoos_MemoryManager mm, picoos_File * this) -{ - if (NULL != (*this)) { - /* terminate */ - picoos_deallocate(mm, (void *)this); - } -} - - -/* ************************************************************ - * low-level file operations - **************************************************************/ - -static picoos_int32 os_min(const picoos_int32 x, const picoos_int32 y) -{ - return (x < y) ? x : y; -} - -/* - static picoos_uint8 LReadChar (picoos_File f, picoos_char * ch); - - - static picoos_uint8 LSetPos (picoos_File f, unsigned int pos); - - - static picoos_uint8 LGetPos (picoos_File f, picoos_uint32 * pos); - - - static picoos_uint8 LEof (picoos_File f); - */ - -static picoos_bool LOpen(picoos_Common g, picoos_File * f, - picoos_char fileName[], picopal_access_mode mode) -{ - picoos_bool done = TRUE; - - *f = picoos_newFile(g->mm); - picopal_strcpy((*f)->name, fileName); - (*f)->write = ((mode == PICOPAL_TEXT_WRITE) || (mode - == PICOPAL_BINARY_WRITE)); - (*f)->binary = (mode - == PICOPAL_BINARY_WRITE); - (*f)->next = NULL; - (*f)->prev = NULL; - (*f)->nf = picopal_get_fnil(); - (*f)->lFileLen = 0; - (*f)->lPos = 0; - if (picopal_strlen((*f)->name)) { - (*f)->nf = picopal_fopen((*f)->name, mode); - done = !(picopal_is_fnil((*f)->nf)); - if (done) { - (*f)->lFileLen = picopal_flength((*f)->nf); - } - } - if (done) { - (*f)->next = g->fileList; - if (g->fileList != NULL) { - g->fileList->prev = (*f); - } - g->fileList = (*f); - } else { - picoos_disposeFile(g->mm, f); - (*f) = NULL; - } - return done; -} - -static picoos_bool LClose(picoos_Common g, picoos_File * f) -{ - - picoos_bool done; - - if (((*f) != NULL)) { - done = (PICO_OK == picopal_fclose((*f)->nf)); - if (((*f)->next != NULL)) { - (*f)->next->prev = (*f)->prev; - } - if (((*f)->prev != NULL)) { - (*f)->prev->next = (*f)->next; - } else { - g->fileList = (*f)->next; - } - picoos_disposeFile(g->mm, f); - - done = TRUE; - } else { - done = FALSE; - } - return done; - -} - -/* caller must ensure that bytes[] has at least len allocated bytes */ -static picoos_bool LReadBytes(picoos_File f, picoos_uint8 bytes[], - picoos_uint32 * len) -{ - picoos_bool done; - picoos_int32 res; - - PICODBG_TRACE(("trying to read %i bytes",*len)); - if ((f != NULL)) { - res = picopal_fread_bytes(f->nf, (void *) &bytes[(0)], 1, (*len)); - PICODBG_TRACE(("res = %i",res)); - if (res < 0) { /* non-ansi */ - (*len) = 0; - done = FALSE; - } else if (((picoos_uint32)res != (*len))) { - (*len) = res; - done = FALSE; - } else { - done = TRUE; - } - f->lPos = (f->lPos + (*len)); - } else { - (*len) = 0; - done = FALSE; - } - return done; -} - - static picoos_bool LWriteBytes(picoos_File f, const picoos_char bytes[], int * len) { - picoos_bool done; - int res; - /*int n; - void * bptr; */ - - if (f != NULL) { - res = picopal_fwrite_bytes(f->nf, (void *) bytes, 1, *len); - if ((res < 0)) { - (*len) = 0; - done = FALSE; - } else if ((res != (*len))) { - (*len) = res; - done = FALSE; - } else { - done = TRUE; - } - f->lPos = (f->lPos + (unsigned int) (*len)); - if ((f->lPos > f->lFileLen)) { - f->lFileLen = f->lPos; - } - } else { - (*len) = 0; - done = FALSE; - } - return done; -} - - -static picoos_bool LSetPos(picoos_File f, unsigned int pos) -{ - - picoos_bool done; - - if ((f != NULL)) { - if ((pos == f->lPos)) { - done = TRUE; - } else { - done = (PICO_OK == picopal_fseek(f->nf, pos, PICOPAL_SEEK_SET)); - if (done) { - f->lPos = pos; - } - } - } else { - done = FALSE; - } - return done; -} - -static picoos_bool LGetPos(picoos_File f, picoos_uint32 * pos) -{ - picoos_bool done = TRUE; - if ((f != NULL)) { - (*pos) = f->lPos; - } else { - done = FALSE; - (*pos) = 0; - } - return done; - -} - -static picoos_bool LEof(picoos_File f) -{ - picoos_bool isEof; - - if ((f != NULL)) { - isEof = picopal_feof(f->nf); - } else { - isEof = TRUE; - } - return isEof; - -} - -/* **************************************************************************************/ - - - -/* read a given string 'str' from file. If no match was found, the read position is advanced until and including the first - * non-matching character */ -static picoos_bool picoos_StrRead (picoos_File f, picoos_char str[]) -{ - picoos_uint32 i = 0; - picoos_bool done = TRUE; - picoos_char b; - - while (done && (str[i] != NULLC)) { - done = done && picoos_ReadByte(f,(picoos_char *)&b); - done = done && (b == str[i]); - i++; - } - return done; -} - -/* write 'str' to file */ -static picoos_bool picoos_WriteStr (picoos_File f, picoos_char str[]) -{ - picoos_uint32 i = 0; - picoos_bool done = TRUE; - - while (done && (str[i] != NULLC)) { - done = done && picoos_WriteByte(f,str[i]); - i++; - } - return done; -} - - - -/* **** Sequential binary file access ******/ - -/* Remark: 'ReadByte', 'ReadBytes' and 'ReadVar' may be mixed; - 'WriteByte', 'WriteBytes' and 'WriteVar' may be mixed. */ - -/* Open existing binary file for read access. Reading is buffered - * with 'nrOfBufs' buffers of size 'bufSize'. If 'nrOfBufs' or - * 'bufSize' is 0 reading is not buffered. - * If 'key' is not empty, the file is decrypted with 'key'. - * If the opened file is in an encrypted archive file, it - */ -picoos_uint8 picoos_OpenBinary(picoos_Common g, picoos_File * f, - picoos_char fileName[]) -{ - return LOpen(g, f, fileName, PICOPAL_BINARY_READ); -} - - -/* Read next byte from file 'f'. */ -picoos_bool picoos_ReadByte(picoos_File f, picoos_uint8 * by) -{ - picoos_uint32 n = 1; - - return picoos_ReadBytes(f, by, &n) && (n == 1); - -} - -/* Read next 'len' bytes from 'f' into 'bytes'; 'len' returns the - number of bytes actually read (may be smaller than requested - length if at end of file). bytes[] must be big enough to hold at least len bytes. -*/ -picoos_bool picoos_ReadBytes(picoos_File f, picoos_uint8 bytes[], - picoos_uint32 * len) -{ - picoos_bool done = TRUE; - /* unsigned int origPos; */ - - if ((f != NULL)) { - done = LReadBytes(f, bytes, len); - /*if ((f->keyLen > 0)) { - DecryptBytes(f->key,picoos_MaxKeyLen,f->keyLen,origPos,bytes,(*len)); - }*/ - } - - return done; -} - - -/* Create new binary file. - If 'key' is not empty, the file is encrypted with 'key'. */ -picoos_bool picoos_CreateBinary(picoos_Common g, picoos_File * f, - picoos_char fileName[]) -{ - return LOpen(g, f, fileName, PICOPAL_BINARY_WRITE); - -} - - -picoos_uint8 picoos_WriteByte(picoos_File f, picoos_char by) -{ - int n = 1; - - return picoos_WriteBytes(f, (picoos_char *) &by, &n); -} - - -/* Writes 'len' bytes from 'bytes' onto file 'f'; 'len' returns - the number of bytes actually written. */ -picoos_bool picoos_WriteBytes(picoos_File f, const picoos_char bytes[], picoos_int32 * len) { - picoos_bool done = FALSE; - - if (f != NULL) { - done = LWriteBytes(f, bytes, len); - } - - return done; -} - - - -/* Close previously opened binary file. */ -picoos_uint8 picoos_CloseBinary(picoos_Common g, picoos_File * f) -{ - return LClose(g, f); - -} - -/* **************************************************************************************/ -/* *** general routines *****/ - - -/* Returns whether end of file was encountered in previous - read operation. */ -picoos_bool picoos_Eof(picoos_File f) -{ - if ((NULL != f)) { - return LEof(f); - } else { - return TRUE; - } - -} - -/* sets the file pointer to - 'pos' bytes from beginning (first byte = byte 0). This - routine should only be used for binary files. */ -picoos_bool picoos_SetPos(picoos_File f, picoos_int32 pos) -{ - picoos_bool done = TRUE; - if ((NULL != f)) { - done = LSetPos(f, pos); - } else { - done = FALSE; - } - return done; - -} - -/* Get position from file 'f'. */ -picoos_bool picoos_GetPos(picoos_File f, picoos_uint32 * pos) -{ - if (NULL != f) { - /* if (f->bFile) { - (*pos) = BGetPos(f); - } else { */ - (*pos) = LGetPos(f, pos); - /* } */ - return TRUE; - } else { - (*pos) = 0; - return FALSE; - } -} - -/* Returns the length of the file in bytes. */ -picoos_bool picoos_FileLength(picoos_File f, picoos_uint32 * len) -{ - - if (NULL != f) { - *len = f->lFileLen; - return TRUE; - } else { - *len = 0; - return FALSE; - } -} - -/* Return full name of file 'f'. maxsize is the size of 'name[]' in bytes */ -picoos_bool picoos_Name(picoos_File f, picoos_char name[], picoos_uint32 maxsize) -{ - picoos_bool done = TRUE; - - if (NULL != f) { - done = (picoos_strlcpy(name, f->name,maxsize) < maxsize); - } else { - name[0] = (picoos_char)NULLC; - done = FALSE; - } - - return done; -} - -/* Returns whether file 'name' exists or not. */ -picoos_bool picoos_FileExists(picoos_Common g, picoos_char name[]) -{ - picoos_File f; - - if (picoos_OpenBinary(g, & f,name)) { - picoos_CloseBinary(g, & f); - return TRUE; - } else { - return FALSE; - } -} - - -/* ******************************************************************/ -/* Array conversion operations: all procedures convert 'nrElems' values from - 'src' starting with index 'srcStartInd' into corresponding (possibly - rounded) values in 'dst' starting at 'dstStartInd'. */ - -/* taking pi to be le, these are just the array versions of read_mem_pi_*int16 */ -typedef picoos_uint8 two_byte_t[2]; - -static void arr_conv_le_int16 (picoos_uint8 src[], picoos_uint32 srcShortStartInd, picoos_uint32 nrElems, picoos_int16 dst[], picoos_uint32 dstStartInd) -{ - two_byte_t * src_p = (two_byte_t *) (src + (srcShortStartInd * 2)); - picoos_int16 * dst_p = dst + dstStartInd; - picoos_uint32 i; - - for (i=0; i>8); - dst_p++; - } -} - -/* *****************************************************************/ -/* Sampled Data Files */ -/* *****************************************************************/ - -#define PICOOS_SDF_BUF_LEN 1024 - -#define PICOOS_INT16_MIN -32768 -#define PICOOS_INT16_MAX 32767 -#define PICOOS_UINT16_MAX 0xffff -#define PICOOS_INT32_MIN -2147483648 -#define PICOOS_INT32_MAX 2147483647 -#define PICOOS_UINT32_MAX 0xffffffff - -/** object : SDFile - * shortcut : sdf - * - */ -/* typedef struct picoos_sd_file * picoos_SDFile */ -typedef struct picoos_sd_file -{ - picoos_uint32 sf; - wave_file_type_t fileType; /* (acoustic) wav, au, raw, other */ - picoos_uint32 hdrSize; - picoos_encoding_t enc; - picoos_File file; - picoos_uint32 nrFileSamples; - picoos_int16 buf[PICOOS_SDF_BUF_LEN]; - picoos_int32 bufPos; - picoos_uint8 bBuf[2*PICOOS_SDF_BUF_LEN]; - picoos_bool aborted; -} picoos_sd_file_t; - - -/* Tries to read wav header at beginning of file 'f'; - returns sampling rate 'sf', encoding type 'enc', - nr of samples in file 'nrSamples', header size 'hdrSize', - and byte order 'bOrder'; returns whether a supported - wav header and format was found. */ -static picoos_bool picoos_readWavHeader(picoos_File f, picoos_uint32 * sf, - picoos_encoding_t * enc, picoos_uint32 * nrSamples, - picoos_uint32 * hdrSize) { - picoos_uint16 n16; - picoos_uint32 n32; - picoos_uint16 formatTag; - picoos_uint32 sampleRate; - picoos_uint32 bytesPerSec; - picoos_uint16 blockAlign; - picoos_uint16 sampleSize; - picoos_uint32 dataLength; - picoos_uint32 fileLen; - picoos_uint32 nrFileSamples; - picoos_bool done; - - - picoos_SetPos(f, 0); - picoos_FileLength(f, &fileLen); - done = picoos_StrRead(f, (picoos_char *) "RIFF"); - done = done && (PICO_OK == picoos_read_le_uint32(f, &n32)); /* length of riff chunk, unused */ - done = done && picoos_StrRead(f, (picoos_char *) "WAVE"); - done = done && picoos_StrRead(f, (picoos_char *) "fmt "); - done = done && (PICO_OK == picoos_read_le_uint32(f, &n32)); /* length of fmt chunk in bytes; must be 16 */ - done = done && (n32 == 16); - done = done && (PICO_OK == picoos_read_le_uint16(f, &formatTag)); - done = done && (PICO_OK == picoos_read_le_uint16(f, &n16)); /* number of channels; must be mono */ - done = done && (n16 == 1); - done = done && (PICO_OK == picoos_read_le_uint32(f, &sampleRate)); - done = done && (PICO_OK == picoos_read_le_uint32(f, &bytesPerSec)); - done = done && (PICO_OK == picoos_read_le_uint16(f, &blockAlign)); - done = done && (PICO_OK == picoos_read_le_uint16(f, &sampleSize)); - done = done && picoos_StrRead(f, (picoos_char *) "data"); - done = done && (PICO_OK == picoos_read_le_uint32(f, &dataLength)); /* length of data chunk in bytes */ - (*hdrSize) = 44; - if (done) { - (*sf) = sampleRate; - (*nrSamples) = 0; - switch (formatTag) { - case FORMAT_TAG_LIN: - (*enc) = PICOOS_ENC_LIN; - done = ((blockAlign == 2) && (sampleSize == 16)); - (*nrSamples) = (dataLength / 2); - nrFileSamples = ((fileLen - (*hdrSize)) / 2); - break; - case FORMAT_TAG_ULAW: - (*enc) = PICOOS_ENC_ULAW; - done = ((blockAlign == 1) && (sampleSize == 8)); - (*nrSamples) = dataLength; - nrFileSamples = (fileLen - (*hdrSize)); - break; - case FORMAT_TAG_ALAW: - (*enc) = PICOOS_ENC_ALAW; - done = ((blockAlign == 1) && (sampleSize == 8)); - (*nrSamples) = dataLength; - nrFileSamples = (fileLen - (*hdrSize)); - break; - default: - done = FALSE; - break; - } - if (!done) { - /* communicate "unsupported format" */ - PICODBG_WARN(("unsupported wav format")); - } else { - if (nrFileSamples != (*nrSamples)) { - /* warn "inconsistent number of samples" */ - PICODBG_WARN(("inconsistent number of samples in wav file: %d vs. %d",nrFileSamples,(*nrSamples))); - (*nrSamples) = nrFileSamples; - } - } - } - return done; -} - - - -extern picoos_bool picoos_sdfOpenIn(picoos_Common g, picoos_SDFile * sdFile, - picoos_char fileName[], picoos_uint32 * sf, picoos_encoding_t * enc, - picoos_uint32 * numSamples) -{ - picoos_bool done = FALSE; - picoos_sd_file_t * sdf = NULL; - wave_file_type_t fileType = FILE_TYPE_OTHER; - - (*sf) = 0; - (*numSamples) = 0; - (*enc) = PICOOS_ENC_LIN; - (*sdFile) = NULL; - - sdf = picoos_allocate(g->mm,sizeof(picoos_sd_file_t)); - if (NULL == sdf) { - picoos_emRaiseWarning(g->em,PICO_EXC_OUT_OF_MEM,NULL,NULL); - return FALSE; - } - - /* buffered access not supported, yet */ - if (picoos_OpenBinary(g,&(sdf->file),fileName)) { - if (picoos_has_extension(fileName,(picoos_char *) ".wav")) { - fileType = FILE_TYPE_WAV; - done = picoos_readWavHeader(sdf->file,&(sdf->sf),&(sdf->enc),&(sdf->nrFileSamples),&(sdf->hdrSize)); - } else { - /* we prefer not to treat other formats, rather than treat it as raw */ - /* fileType = FILE_TYPE_RAW; */ - fileType = FILE_TYPE_OTHER; - done = FALSE; - } - - if (FILE_TYPE_OTHER == fileType) { - picoos_emRaiseWarning(g->em,PICO_EXC_UNEXPECTED_FILE_TYPE,(picoos_char *)"unsupported filename suffix",NULL); - } else if (!done) { - picoos_emRaiseWarning(g->em,PICO_EXC_UNEXPECTED_FILE_TYPE,(picoos_char *)"non-conforming header",NULL); - } else { - (*numSamples) = sdf->nrFileSamples; - (*sf) = sdf->sf; - (*enc) = sdf->enc; - /* check whether sd file properties are supported */ - if (PICOOS_ENC_LIN != sdf->enc) { - done = FALSE; - picoos_emRaiseWarning(g->em,PICO_EXC_UNEXPECTED_FILE_TYPE,NULL,(picoos_char *)"encoding not supported"); - } - if (SAMPLE_FREQ_16KHZ != sdf->sf) { - done = FALSE; - picoos_emRaiseWarning(g->em,PICO_EXC_UNEXPECTED_FILE_TYPE,NULL,(picoos_char *)"sample frequency not supported"); - } - (*sdFile) = sdf; - } - if (!done){ - picoos_CloseBinary(g,&(sdf->file)); - } - } else { - picoos_emRaiseException(g->em,PICO_EXC_CANT_OPEN_FILE,NULL,NULL); - } - if (!done) { - picoos_deallocate(g->mm,(void *)&sdf); - (*sdFile) = NULL; - } - return done; -} - - -static void picoos_sdfLoadSamples(picoos_SDFile sdFile, - picoos_uint32 * nrSamples) { - picoos_uint32 len; - picoos_sd_file_t * sdf = sdFile; - - switch (sdFile->enc) { - case PICOOS_ENC_LIN: - if ((*nrSamples) > PICOOS_SDF_BUF_LEN) { - (*nrSamples) = PICOOS_SDF_BUF_LEN; - } - len = 2 * (*nrSamples); - picoos_ReadBytes(sdf->file, sdf->bBuf, &len); - (*nrSamples) = len / 2; - arr_conv_le_int16(sdf->bBuf, 0, (*nrSamples), sdf->buf, 0); - break; - /* @todo : may be useful */ - case PICOOS_ENC_ULAW: - case PICOOS_ENC_ALAW: - default: - (*nrSamples) = 0; - } - -} - -extern picoos_bool picoos_sdfGetSamples ( - picoos_SDFile sdFile, - picoos_uint32 start, - picoos_uint32 * nrSamples, - picoos_int16 samples[]) -{ - picoos_uint32 b; - picoos_uint32 rem; - picoos_uint32 n; - picoos_uint32 i; - picoos_uint32 j; - picoos_bool done = FALSE; - - if (NULL == sdFile) { - (*nrSamples) = 0; - } else { - if (start >= sdFile->nrFileSamples) { - if (start > sdFile->nrFileSamples) { - PICODBG_WARN(("start has to be <= sdFile->nrFileSamples")); - } - (*nrSamples) = 0; - } else { - if (((start + (*nrSamples)) > sdFile->nrFileSamples)) { - (*nrSamples) = (sdFile->nrFileSamples - start); - } - if ((sdFile->enc == PICOOS_ENC_LIN)) { - b = 2; - } else { - b = 1; - } - picoos_SetPos(sdFile->file,(sdFile->hdrSize + (b * start))); - j = 0; - rem = (*nrSamples); - n = rem; - while ((rem > 0) && (n > 0)) { - /* set n=min(rem,buffer_length) and try loading next n samples */ - n = (rem < PICOOS_SDF_BUF_LEN) ? rem : PICOOS_SDF_BUF_LEN; - picoos_sdfLoadSamples(sdFile, &n); - /* n may be smaller now */ - for (i = 0; i < n; i++) { - samples[j] = sdFile->buf[i]; - j++; - } - rem -= n; - start += n; - } - (*nrSamples) = j; - done = ((*nrSamples) > 0); - } - } - return done; -} - - -extern picoos_bool picoos_sdfCloseIn (picoos_Common g, picoos_SDFile * sdFile) -{ - if (NULL != (*sdFile)) { - picoos_CloseBinary(g,&((*sdFile)->file)); - picoos_deallocate(g->mm,(void *)sdFile); - } - return TRUE; -} - - -static picoos_bool picoos_writeWavHeader(picoos_File f, picoos_uint32 sf, - picoos_encoding_t enc, picoos_uint32 nrSamples, - picoos_uint32 * hdrSize) { - picoos_uint16 formatTag = FORMAT_TAG_LIN; - picoos_uint32 sampleRate; - picoos_uint32 bytesPerSec; - picoos_uint32 bytesPerSample = 2; - picoos_uint16 blockAlign; - picoos_uint16 sampleSize = 16; - picoos_uint32 dataLength; - picoos_bool done = TRUE; - - picoos_SetPos(f, 0); - - switch (enc) { - case PICOOS_ENC_LIN: - formatTag = FORMAT_TAG_LIN; - bytesPerSample = 2; - sampleSize = 16; - break; - case PICOOS_ENC_ULAW: - formatTag = FORMAT_TAG_ULAW; - bytesPerSample = 1; - sampleSize = 8; - break; - case PICOOS_ENC_ALAW: - formatTag = FORMAT_TAG_ALAW; - bytesPerSample = 1; - sampleSize = 8; - break; - default: - done = FALSE; - break; - } - - bytesPerSec = (sf * bytesPerSample); - blockAlign = bytesPerSample; - sampleRate = sf; - dataLength = (bytesPerSample * nrSamples); - done = done && picoos_WriteStr(f,(picoos_char *)"RIFF"); - done = done && picoos_write_le_uint32(f,dataLength + 36); - done = done && picoos_WriteStr(f,(picoos_char *)"WAVE"); - done = done && picoos_WriteStr(f,(picoos_char *)"fmt "); - done = done && picoos_write_le_uint32(f,16); - done = done && picoos_write_le_uint16(f,formatTag); - done = done && picoos_write_le_uint16(f,1); - done = done && picoos_write_le_uint32(f,sampleRate); - done = done && picoos_write_le_uint32(f,bytesPerSec); - done = done && picoos_write_le_uint16(f,blockAlign); - done = done && picoos_write_le_uint16(f,sampleSize); - done = done && picoos_WriteStr(f,(picoos_char *)"data"); - done = done && picoos_write_le_uint32(f,dataLength); - (*hdrSize) = 44; - return done; -} - - -#define DummyLen 100000000 - -extern picoos_bool picoos_sdfOpenOut(picoos_Common g, picoos_SDFile * sdFile, - picoos_char fileName[], int sf, picoos_encoding_t enc) -{ - picoos_bool done = TRUE; - picoos_sd_file_t * sdf = NULL; - - (*sdFile) = NULL; - sdf = picoos_allocate(g->mm, sizeof(picoos_sd_file_t)); - if (NULL == sdf) { - picoos_emRaiseWarning(g->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); - return FALSE; - } - sdf->sf = sf; - sdf->enc = enc; - /* check whether sd file properties are supported */ - if (PICOOS_ENC_LIN != sdf->enc) { - done = FALSE; - picoos_emRaiseWarning(g->em, PICO_EXC_UNEXPECTED_FILE_TYPE, NULL, - (picoos_char *) "encoding not supported"); - } - if (SAMPLE_FREQ_16KHZ != sdf->sf) { - done = FALSE; - picoos_emRaiseWarning(g->em, PICO_EXC_UNEXPECTED_FILE_TYPE, NULL, - (picoos_char *) "sample frequency not supported"); - } - if (done) { - sdf->nrFileSamples = 0; - sdf->bufPos = 0; - sdf->aborted = FALSE; - if (picoos_CreateBinary(g, &(sdf->file), fileName)) { - if (picoos_has_extension(fileName, (picoos_char *) ".wav")) { - sdf->fileType = FILE_TYPE_WAV; - done = picoos_writeWavHeader(sdf->file, sdf->sf, sdf->enc, - DummyLen, &(sdf->hdrSize)); - } else { - /* we prefer not to treat other formats, rather than treat it as raw */ - /* fileType = FILE_TYPE_RAW; */ - sdf->fileType = FILE_TYPE_OTHER; - done = FALSE; - } - - if (FILE_TYPE_OTHER == sdf->fileType) { - picoos_emRaiseWarning(g->em, PICO_EXC_UNEXPECTED_FILE_TYPE, - (picoos_char *) "unsupported filename suffix", NULL); - } else if (!done) { - picoos_emRaiseWarning(g->em, PICO_EXC_UNEXPECTED_FILE_TYPE, - (picoos_char *) "non-conforming header", NULL); - } else { - (*sdFile) = sdf; - } - if (!done) { - picoos_CloseBinary(g, &(sdf->file)); - } - } else { - picoos_emRaiseException(g->em, PICO_EXC_CANT_OPEN_FILE, NULL, NULL); - } - } - if (!done) { - picoos_deallocate(g->mm, (void *) &sdf); - (*sdFile) = NULL; - } - return done; -} - -static picoos_bool picoos_sdfFlushOutBuf(picoos_SDFile sdFile) -{ - picoos_bool done = FALSE; - picoos_int32 len; - picoos_int32 nrSamples; - - if (!(sdFile->aborted)) { - nrSamples = sdFile->bufPos; - switch (sdFile->enc) { - case PICOOS_ENC_LIN: - arr_conv_int16_le(sdFile->buf, 0, nrSamples, sdFile->bBuf, 0); - len = (nrSamples * 2); - done = picoos_WriteBytes(sdFile->file, sdFile->bBuf, &len) - && ((nrSamples * 2) == len); - break; - case PICOOS_ENC_ULAW: - case PICOOS_ENC_ALAW: - default: - nrSamples = 0; - break; - } - sdFile->nrFileSamples = (sdFile->nrFileSamples + nrSamples); - } - - sdFile->bufPos = 0; - return done; -} - -extern picoos_bool picoos_sdfFlushOutput(picoos_SDFile sdFile) -{ - if ((sdFile != NULL) && !(sdFile->aborted) && (sdFile->bufPos > 0)) { - return picoos_sdfFlushOutBuf(sdFile); - } - return TRUE; -} - - - -extern picoos_bool picoos_sdfPutSamples (picoos_SDFile sdFile, picoos_uint32 nrSamples, picoos_int16 samples[]) -{ - picoos_uint32 i; - picoos_int32 s; - picoos_bool done = FALSE; - - if ((sdFile != NULL) && !(sdFile->aborted)) { - done = TRUE; - for (i = 0; i < nrSamples; i++) { - s = samples[i]; - if ((s > PICOOS_INT16_MAX)) { - s = PICOOS_INT16_MAX; - } else if (s < PICOOS_INT16_MIN) { - s = PICOOS_INT16_MIN; - } - sdFile->buf[sdFile->bufPos++] = s; - if (sdFile->bufPos >= PICOOS_SDF_BUF_LEN) { - done = picoos_sdfFlushOutBuf(sdFile); - } - } - } else { - done = FALSE; - } - return done; -} - - -extern picoos_bool picoos_sdfCloseOut (picoos_Common g, picoos_SDFile * sdFile) -{ - - picoos_bool done = TRUE; - picoos_uint32 hdrSize; - - if (NULL != (*sdFile)) { - if (!((*sdFile)->aborted) && ((*sdFile)->bufPos > 0)) { - done = picoos_sdfFlushOutBuf(*sdFile); - } - if (FILE_TYPE_WAV == (*sdFile)->fileType) { - done = picoos_writeWavHeader((*sdFile)->file, (*sdFile)->sf, - (*sdFile)->enc, (*sdFile)->nrFileSamples, &hdrSize); - } - done = picoos_CloseBinary(g, &((*sdFile)->file)); - picoos_deallocate(g->mm, (void *) sdFile); - } - return done; -} - - -/* *****************************************************************/ -/* FileHeader */ -/* *****************************************************************/ - - - -pico_status_t picoos_clearHeader(picoos_FileHeader header) -{ - picoos_uint8 i; - for (i=0; i < PICOOS_MAX_NUM_HEADER_FIELDS; i++) { - header->field[i].key[0] = NULLC; - header->field[i].value[0] = NULLC; - header->field[i].op = PICOOS_FIELD_IGNORE; - } - header->numFields = 0; - return PICO_OK; -} - -pico_status_t picoos_setHeaderField(picoos_FileHeader header, - picoos_uint8 index, picoos_char * key, picoos_char * value, - picoos_compare_op_t op) -{ - if (index >= header->numFields) { - return PICO_ERR_INDEX_OUT_OF_RANGE; - } - header->field[index].op = op; - if ((picoos_strlcpy(header->field[index].key, key, - PICOOS_MAX_FIELD_STRING_LEN) < PICOOS_MAX_FIELD_STRING_LEN) - && (picoos_strlcpy(header->field[index].value, value, - PICOOS_MAX_FIELD_STRING_LEN)) < PICOOS_MAX_FIELD_STRING_LEN) { - return PICO_OK; - } else { - return PICO_ERR_INDEX_OUT_OF_RANGE; - } -} - - -/* caller has to make sure allocated space at key and value are large enough to hold a picoos_field_string */ -pico_status_t picoos_getHeaderField(picoos_FileHeader header, picoos_uint8 index, picoos_field_string_t key, picoos_field_string_t value, picoos_compare_op_t * op) -{ - if (index >= header->numFields) { - return PICO_ERR_INDEX_OUT_OF_RANGE; - } - *op = header->field[index].op; - if ((picoos_strlcpy(key,header->field[index].key, - PICOOS_MAX_FIELD_STRING_LEN) < PICOOS_MAX_FIELD_STRING_LEN) - && (picoos_strlcpy(value,header->field[index].value, - PICOOS_MAX_FIELD_STRING_LEN)) < PICOOS_MAX_FIELD_STRING_LEN) { - return PICO_OK; - } else { - return PICO_ERR_INDEX_OUT_OF_RANGE; - } - return PICO_OK; -} - - -/* check whether 'str' of length strlen matches contents in circular buffer buf, located in the first strlen bytes and ending - * position bufpos. */ -static picoos_uint8 os_matched( picoos_char * str, picoos_uint32 strlen, picoos_char * buf, picoos_int32 bufpos) { - picoos_int32 i = strlen-1; - while (i >= 0 && buf[bufpos] == str[i]) { - i--; - bufpos--; - if (bufpos < 0) { - bufpos = strlen-1; - } - } - return (i<0); -} - -pico_status_t picoos_getSVOXHeaderString(picoos_char * str, picoos_uint8 * len, picoos_uint32 maxlen) -{ - picoos_char * ch; - *len = picoos_strlcpy(str,picoos_SVOXFileHeader,maxlen); - if (*len < maxlen) { - ch = str; - /* SVOX header is made less readable */ - while (*ch) { - *ch -= ' '; - ch++; - } - return PICO_OK; - } else { - return PICO_ERR_OTHER; - } -} - -pico_status_t picoos_readPicoHeader(picoos_File f, picoos_uint32 * headerlen) -{ - picoos_char str[32]; - picoos_char buf[32]; - picoos_uint8 strlen, bufpos; - picoos_uint32 n; - picoos_uint8 done; - - picoos_getSVOXHeaderString(str,&strlen,32); - /* search for svox header somewhere near the file start. This allows for initial - * non-svox-header bytes for a customer-specific header and/or filling bytes for alignment */ - *headerlen = 0; - /* read in initial chunk of length strlen */ - n = strlen; - done = picoos_ReadBytes(f,(picoos_uint8 *)buf,&n) && (n == strlen); - if (done) { - *headerlen = n; - bufpos = strlen-1; /* last legal buf position */ - done = os_matched(str,strlen,buf,bufpos); - while (!done && *headerlen < PICO_MAX_FOREIGN_HEADER_LEN) { - n = 1; - bufpos = (bufpos + 1) % strlen; - done = picoos_ReadBytes(f,(picoos_uint8 *)buf+bufpos,&n) && 1 == n; - done = done && os_matched(str,strlen,buf,bufpos); - headerlen++; - } - } - if (done) { - return PICO_OK; - } else { - return PICO_EXC_UNEXPECTED_FILE_TYPE; - } -} - -picoos_uint8 picoos_get_str (picoos_char * fromStr, picoos_uint32 * pos, picoos_char * toStr, picoos_objsize_t maxsize) -{ - picoos_uint8 i = 0; - /* skip non-printables */ - - while ((fromStr[*pos] != NULLC) && (fromStr[*pos] <= ' ')) { - (*pos)++; - } - /* copy printable portion */ - while ((fromStr[*pos] != NULLC) && (fromStr[*pos] > ' ') && (i < maxsize-1)) { - toStr[i++] = fromStr[(*pos)++]; - } - toStr[i] = NULLC; - return (i > 0) && (fromStr[*pos] <= ' '); -} - -pico_status_t picoos_hdrParseHeader(picoos_FileHeader header, picoos_header_string_t str) -{ - picoos_uint32 curpos = 0; - picoos_uint8 i, numFields; - - - /* read number of fields */ - numFields = str[curpos++]; - numFields = os_min(numFields,PICOOS_MAX_NUM_HEADER_FIELDS); - /* read in all field pairs */ - PICODBG_DEBUG(("number of fields = %i", numFields)); - for (i = 0; i < numFields; i++) { - picoos_get_str(str,&curpos,header->field[i].key,PICOOS_MAX_FIELD_STRING_LEN); - picoos_get_str(str,&curpos,header->field[i].value,PICOOS_MAX_FIELD_STRING_LEN); - } - return PICO_OK; -} - - - - - -/* **************************************************************************/ -/* Read little-endian / platform-independent integers from file or memory */ -/* **************************************************************************/ - -/* read little-endian */ -pico_status_t picoos_read_le_uint16 (picoos_File file, picoos_uint16 * val) -{ - picoos_uint8 by[2]; - picoos_uint32 n = 2; - if (picoos_ReadBytes(file, by, &n) && 2 == n) { - /* little-endian */ - *val = (picoos_uint16) by[1] << 8 | (picoos_uint16) by[0]; - return PICO_OK; - } else { - *val = 0; - return PICO_ERR_OTHER; - } -} - -pico_status_t picoos_read_le_int16 (picoos_File file, picoos_int16 * val) -{ - return picoos_read_le_uint16(file, (picoos_uint16 *)val); -} - -pico_status_t picoos_read_le_uint32 (picoos_File file, picoos_uint32 * val) -{ - picoos_uint8 by[4]; - picoos_uint32 n = 4; - if (picoos_ReadBytes(file, by, &n) && (4 == n)) { - /* little-endian */ - PICODBG_TRACE(("reading uint 32: %i %i %i %i", - by[0], by[1], by[2], by[3])); - *val = (((picoos_uint32) by[3] << 8 | (picoos_uint32) by[2]) << 8 | (picoos_uint32) by[1]) << 8 | (picoos_uint32) by[0]; - PICODBG_TRACE(("uint 32: %i %i %i %i corresponds %i", - by[0], by[1], by[2], by[3], *val)); - return PICO_OK; - } else { - *val = 0; - return PICO_ERR_OTHER; - } -} - -/* platform-independent */ -/* our convention is that pi is little-endian. */ - -/** @todo : direct implementation if too slow */ - -pico_status_t picoos_read_pi_uint16 (picoos_File file, picoos_uint16 * val) -{ - return picoos_read_le_uint16(file,val); -} - -pico_status_t picoos_read_pi_uint32 (picoos_File file, picoos_uint32 * val) -{ - return picoos_read_le_uint32(file, val); -} - -pico_status_t picoos_read_pi_int32 (picoos_File file, picoos_int32 * val) -{ - return picoos_read_le_uint32(file, (picoos_uint32 *)val); -} - -/* read pi from memory */ - -pico_status_t picoos_read_mem_pi_uint16 (picoos_uint8 * data, picoos_uint32 * pos, picoos_uint16 * val) -{ - picoos_uint8 * by = data + *pos; - - /* little-endian */ - *val = (picoos_uint16) by[1] << 8 | (picoos_uint16) by[0]; - (*pos) += 2; - return PICO_OK; -} - -pico_status_t picoos_read_mem_pi_uint32 (picoos_uint8 * data, picoos_uint32 * pos, picoos_uint32 * val) -{ - picoos_uint8 * by = data + *pos; - - /* little-endian */ - *val = (((picoos_uint32) by[3] << 8 | (picoos_uint32) by[2]) << 8 | (picoos_uint32) by[1]) << 8 | (picoos_uint32) by[0]; - (*pos) += 4; - return PICO_OK; -} - -/* **************************************************************************/ -/* Write little-endian / platform-independent integers into file or memory */ -/* **************************************************************************/ -/* write little-endian */ -pico_status_t picoos_write_le_uint16 (picoos_File file, picoos_uint16 val) -{ - picoos_int32 len = 2; - picoos_uint8 by[2]; - - by[0] = (picoos_uint8)((val) & 0x00FF); - by[1] = (picoos_uint8)(((val) & 0xFF00)>>8); - return (picoos_WriteBytes(file,by,&len) && (2 == len)); -} -pico_status_t picoos_write_le_uint32 (picoos_File file, picoos_uint32 val) -{ - picoos_int32 len = 4; - picoos_uint8 by[4]; - - by[0] = (picoos_uint8)(val & 0x000000FF); - by[1] = (picoos_uint8)((val & 0x0000FF00)>>8); - by[2] = (picoos_uint8)((val & 0x00FF0000)>>16); - by[3] = (picoos_uint8)((val & 0xFF000000)>>24); - return (picoos_WriteBytes(file,by,&len) && (4 == len)); -} - -/* write pi to mem */ -pico_status_t picoos_write_mem_pi_uint16 (picoos_uint8 * data, picoos_uint32 * pos, picoos_uint16 val) -{ - picoos_uint8 * by = data + *pos; - /* little-endian */ - by[0] = (picoos_uint8)((val) & 0x00FF); - by[1] = (picoos_uint8)(((val) & 0xFF00)>>8); - (*pos) += 2; - return PICO_OK; -} - -/* *****************************************************************/ -/* String search and compare operations */ -/* *****************************************************************/ - -/* this function is case-sensitive */ -picoos_uint8 picoos_has_extension(const picoos_char *str, const picoos_char *suf) -{ - picoos_int32 istr = picoos_strlen(str)-1; - picoos_int32 isuf = picoos_strlen(suf)-1; - while ((istr >= 0) && (isuf >=0) && (str[istr] == suf[isuf])) { - istr--; - isuf--; - } - return (isuf < 0); -} - - -/* *****************************************************************/ -/* String/Number Conversions (may be moved to picopal) */ -/* *****************************************************************/ - -pico_status_t picoos_string_to_int32(picoos_char str[], - picoos_int32 * res) -{ - /* syntax: [+|-] dig {dig} */ - - int i; - int neg; - int val; - int err; - - err = 0; - i = 0; - while ((str[i] <= ' ') && (str[i] != '\0')) { - i++; - } - neg = 0; - if (str[i] == '-') { - neg = 1; - i++; - } else if (str[i] == '+') { - i++; - } - val = 0; - if ((str[i] < '0') || (str[i]> '9')) { - err = 1; - } - while ((str[i] >= '0') && (str[i] <= '9')) { - val = val * 10 + (str[i] - '0'); - i++; - } - while ((str[i] <= ' ') && (str[i] != '\0')) { - i++; - } - if (neg == 1) { - val = -val; - } - if ((err == 0) && (str[i] == '\0')) { - (*res) = val; - return PICO_OK; - } else { - (*res) = 0; - return PICO_EXC_NUMBER_FORMAT; - } -} - -pico_status_t picoos_string_to_uint32(picoos_char str[], - picoos_uint32 * res) -{ - /* syntax: [+] dig {dig} */ - - int i; - int val; - int err; - - err = 0; - i = 0; - while ((str[i] <= ' ') && (str[i] != '\0')) { - i++; - } - if (str[i] == '+') { - i++; - } - val = 0; - if ((str[i] < '0') || (str[i]> '9')) { - err = 1; - } - while ((str[i] >= '0') && (str[i] <= '9')) { - val = val * 10 + (str[i] - '0'); - i++; - } - while ((str[i] <= ' ') && (str[i] != '\0')) { - i++; - } - if ((err == 0) && (str[i] == '\0')) { - (*res) = val; - return PICO_OK; - } else { - (*res) = 0; - return PICO_EXC_NUMBER_FORMAT; - } -} - -/* 'stringlen' is the part of input string to be considered, - * possibly not containing NULLC (e.g. result of strlen). - * 'maxsize' is the maximal size of 'part' including a byte - * for the terminating NULLC! */ -void picoos_get_sep_part_str(picoos_char string[], - picoos_int32 stringlen, picoos_int32 * ind, picoos_char sepCh, - picoos_char part[], picoos_int32 maxsize, picoos_uint8 * done) -{ - - picoos_int32 j; - picoos_uint8 done1; - - if (((*ind) >= stringlen)) { - (*done) = 0; - part[0] = (picoos_char) NULLC; - } else { - done1 = 1; - j = 0; - while ((((*ind) < stringlen) && (string[(*ind)] != sepCh)) && (string[((*ind))] != (picoos_char)NULLC)) { - if ((j < maxsize-1)) { - part[(j)] = string[(*ind)]; - j++; - } else { - done1 = 0; - } - (*ind)++; - } - part[j] = (picoos_char)NULLC; - if ((*ind) < stringlen) { - if ((string[(*ind)] == sepCh)) { - (*ind)++; /* skip separator character */ - } else if (string[(*ind)] == (picoos_char)NULLC) { - /* reached end of input; set ind to stringlen so that no - more (empty) partial strings will be found */ - (*ind) = stringlen; - } - } - (*done) = done1; - } -} - -/* *****************************************************************/ -/* timer function */ -/* *****************************************************************/ - -extern void picoos_get_timer(picopal_uint32 * sec, picopal_uint32 * usec) -{ - picopal_get_timer(sec, usec); -} - -#ifdef __cplusplus -} -#endif - - -/* end */ diff --git a/lib/picoos.h b/lib/picoos.h deleted file mode 100644 index 859e176..0000000 --- a/lib/picoos.h +++ /dev/null @@ -1,550 +0,0 @@ -/* - * 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 picoos.h - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -/** - * @addtogroup picoos - - * Operating system generalization module \n - * -*/ - -#ifndef PICOOS_H_ -#define PICOOS_H_ - -#include "picodefs.h" -#include "picopal.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* some "switch" used in picopal and in picocep ... */ -#define PICOOS_DIV_USE_INV PICOPAL_DIV_USE_INV - -/* *************************************************/ -/* types */ -/* *************************************************/ - -typedef picopal_uint8 picoos_uint8; -typedef picopal_uint16 picoos_uint16; -typedef picopal_uint32 picoos_uint32; - -typedef picopal_int8 picoos_int8; -typedef picopal_int16 picoos_int16; -typedef picopal_int32 picoos_int32; - -typedef picopal_double picoos_double; -typedef picopal_single picoos_single; - -typedef picopal_char picoos_char; -typedef picopal_uchar picoos_uchar; - -typedef picopal_uint8 picoos_bool; - -typedef picopal_objsize_t picoos_objsize_t; -typedef picopal_ptrdiff_t picoos_ptrdiff_t; - -/* *************************************************/ -/* functions */ -/* *************************************************/ - - -picoos_int32 picoos_atoi(const picoos_char *); -picoos_int8 picoos_strcmp(const picoos_char *, const picoos_char *); -picoos_int8 picoos_strncmp(const picoos_char *a, const picoos_char *b, picoos_objsize_t siz); -picoos_uint32 picoos_strlen(const picoos_char *); -picoos_char * picoos_strchr(const picoos_char *, picoos_char); -picoos_char *picoos_strstr(const picoos_char *s, const picoos_char *substr); -picoos_int16 picoos_slprintf(picoos_char * b, picoos_uint32 bsize, const picoos_char *f, ...); -picoos_char * picoos_strcpy(picoos_char *, const picoos_char *); -picoos_char * picoos_strcat(picoos_char *, const picoos_char *); - -/* copies 'length' bytes from 'src' to 'dest'. (regions may be overlapping) no error checks! */ -void * picoos_mem_copy(const void * src, void * dst, picoos_objsize_t length); - -/* safe versions */ -picoos_objsize_t picoos_strlcpy(picoos_char *dst, const picoos_char *src, picoos_objsize_t siz); -void * picoos_mem_set(void * dest, picoos_uint8 byte_val, picoos_objsize_t length); - -picoos_double picoos_cos(const picoos_double cos_arg); -picoos_double picoos_sin(const picoos_double sin_arg); -picoos_double picoos_fabs(const picoos_double fabs_arg); - -picoos_double picoos_quick_exp(const picoos_double y); - - -void picoos_get_sep_part_str (picoos_char string[], picoos_int32 stringlen, picoos_int32 * ind, picoos_char sepCh, picoos_char part[], picoos_int32 maxsize, picoos_uint8 * done); -pico_status_t picoos_string_to_uint32 (picoos_char str[], picoos_uint32 * res); -pico_status_t picoos_string_to_int32 (picoos_char str[], picoos_int32 * res); - -/* *****************************************************************/ -/* "Common" */ -/* *****************************************************************/ -/* picoos_common is a collection of basic functionalities that must be globally accesible from every "big" function. - * It includes pointers to the MemoryManasger, ExceptionManager and a list of open files. */ - -typedef struct memory_manager * picoos_MemoryManager; -typedef struct picoos_exception_manager * picoos_ExceptionManager; -typedef struct picoos_file * picoos_File; - - -/** object : Common - * shortcut : common - * - */ -typedef struct picoos_common * picoos_Common; - -/* the picoos_common structure itself is exported so no access functions are needed. Handle with care! (might be changed later) */ -typedef struct picoos_common { - picoos_ExceptionManager em; - picoos_MemoryManager mm; - picoos_File fileList; -} picoos_common_t; - -picoos_Common picoos_newCommon(picoos_MemoryManager mm); - -void picoos_disposeCommon(picoos_MemoryManager mm, picoos_Common * this); - - -/* *****************************************************************/ -/* Memory Management */ -/* *****************************************************************/ - -typedef picoos_char * byte_ptr_t; - -#define PICOOS_ALIGN_SIZE 8 - - - -void * picoos_raw_malloc(byte_ptr_t raw_mem, - picoos_objsize_t raw_mem_size, picoos_objsize_t alloc_size, - byte_ptr_t * rest_mem, picoos_objsize_t * rest_mem_size); - -/** - * Creates a new memory manager object for the specified raw memory - * block. 'enableProtMem' enables or disables memory protection - * functionality; if disabled, picoos_protectMem() has no effect. - */ -picoos_MemoryManager picoos_newMemoryManager( - void *raw_memory, - picoos_objsize_t size, - picoos_bool enableMemProt); - - - -void picoos_disposeMemoryManager(picoos_MemoryManager * mm); - - -void * picoos_allocate(picoos_MemoryManager this, picoos_objsize_t byteSize); -void picoos_deallocate(picoos_MemoryManager this, void * * adr); - -/* the following memory manager routines are for testing and - debugging purposes */ - -/** - * Same as picoos_allocate, but write access to the memory block may be - * prohibited by a subsequent call to picoos_protectMem(). - */ -void *picoos_allocProtMem(picoos_MemoryManager mm, picoos_objsize_t byteSize); - -/** - * Releases a memory block previously allocated by picoos_allocProtMem(). - */ -void picoos_deallocProtMem(picoos_MemoryManager mm, void **addr); - -/** - * Enables or disables write protection of a memory block previously - * allocated by picoos_allocProtMem(). If write protection is enabled, - * any subsequent write access will cause a segmentation fault. - */ -void picoos_protectMem( - picoos_MemoryManager mm, - void *addr, - picoos_objsize_t len, - picoos_bool enable); - -void picoos_getMemUsage( - picoos_MemoryManager this, - picoos_bool resetIncremental, - picoos_int32 *usedBytes, - picoos_int32 *incrUsedBytes, - picoos_int32 *maxUsedBytes); - -void picoos_showMemUsage( - picoos_MemoryManager this, - picoos_bool incremental, - picoos_bool resetIncremental); - -/* *****************************************************************/ -/* Exception Management */ -/* *****************************************************************/ -/** object : ExceptionManager - * shortcut : em - * - */ - - -#define PICOOS_MAX_EXC_MSG_LEN 512 -#define PICOOS_MAX_WARN_MSG_LEN 64 -#define PICOOS_MAX_NUM_WARNINGS 8 - -void picoos_setErrorMsg(picoos_char * dst, picoos_objsize_t siz, - picoos_int16 code, picoos_char * base, const picoos_char *fmt, ...); - - -picoos_ExceptionManager picoos_newExceptionManager(picoos_MemoryManager mm); - -void picoos_disposeExceptionManager(picoos_MemoryManager mm, - picoos_ExceptionManager * this); - - -void picoos_emReset(picoos_ExceptionManager this); - -/* For convenience, this function returns the resulting exception code of 'this' - * (as would be returned by emGetExceptionCode). - * The return value therefore is NOT the status of raising - * the error! */ -pico_status_t picoos_emRaiseException(picoos_ExceptionManager this, - pico_status_t exceptionCode, picoos_char * baseMessage, picoos_char * fmt, ...); - -pico_status_t picoos_emGetExceptionCode(picoos_ExceptionManager this); - -void picoos_emGetExceptionMessage(picoos_ExceptionManager this, picoos_char * msg, picoos_uint16 maxsize); - -void picoos_emRaiseWarning(picoos_ExceptionManager this, - pico_status_t warningCode, picoos_char * baseMessage, picoos_char * fmt, ...); - -picoos_uint8 picoos_emGetNumOfWarnings(picoos_ExceptionManager this); - -pico_status_t picoos_emGetWarningCode(picoos_ExceptionManager this, picoos_uint8 warnNum); - -void picoos_emGetWarningMessage(picoos_ExceptionManager this, picoos_uint8 warnNum, picoos_char * msg, picoos_uint16 maxsize); - - - - -/* *****************************************************************/ -/* File Access */ -/* *****************************************************************/ - -#define picoos_MaxFileNameLen 512 -#define picoos_MaxKeyLen 512 -#define picoos_MaxPathLen 512 -#define picoos_MaxPathListLen 2048 - -typedef picoos_char picoos_Key[picoos_MaxKeyLen]; -typedef picoos_char picoos_FileName[picoos_MaxFileNameLen]; -typedef picoos_char picoos_Path[picoos_MaxPathLen]; -typedef picoos_char picoos_PathList[picoos_MaxPathListLen]; - - -/* ***** Sequential binary file access ******/ - -/* Remark: 'ReadByte', 'ReadBytes' and 'ReadVar' may be mixed; - 'WriteByte', 'WriteBytes' and 'WriteVar' may be mixed. */ - -/* Open existing binary file for read access. */ -picoos_uint8 picoos_OpenBinary(picoos_Common g, picoos_File * f, picoos_char name[]); - - -/* Read next byte from file 'f'. */ -picoos_uint8 picoos_ReadByte(picoos_File f, picoos_uint8 * by); - -/* Read next 'len' bytes from 'f' into 'bytes'; 'len' returns the - number of bytes actually read (may be smaller than requested - length if 'bytes' is too small to hold all bytes or at end of file). - Remark: 'bytes' is compabtible with any variable of any size. */ -picoos_uint8 picoos_ReadBytes(picoos_File f, picoos_uint8 bytes[], - picoos_uint32 * len); - - -/* Create new binary file. - If 'key' is not empty, the file is encrypted with 'key'. */ -picoos_uint8 picoos_CreateBinary(picoos_Common g, picoos_File * f, picoos_char name[]); - -picoos_uint8 picoos_WriteByte(picoos_File f, picoos_char by); - -/* Writes 'len' bytes from 'bytes' onto file 'f'; 'len' returns - the number of bytes actually written. */ -picoos_uint8 picoos_WriteBytes(picoos_File f, const picoos_char bytes[], - picoos_int32 * len); - - -/* Close previously opened binary file. */ -picoos_uint8 picoos_CloseBinary(picoos_Common g, picoos_File * f); - - - - - - -pico_status_t picoos_read_le_int16 (picoos_File file, picoos_int16 * val); -pico_status_t picoos_read_le_uint16 (picoos_File file, picoos_uint16 * val); -pico_status_t picoos_read_le_uint32 (picoos_File file, picoos_uint32 * val); - - -pico_status_t picoos_read_pi_uint16 (picoos_File file, picoos_uint16 * val); -pico_status_t picoos_read_pi_uint32 (picoos_File file, picoos_uint32 * val); - -pico_status_t picoos_write_le_uint16 (picoos_File file, picoos_uint16 val); -pico_status_t picoos_write_le_uint32 (picoos_File file, picoos_uint32 val); - -/* -pico_status_t picoos_write_pi_uint32 (picoos_File file, const picoos_uint32 val); - -pico_status_t picoos_write_pi_uint16 (picoos_File file, const picoos_uint16 val); -*/ - - -/* **************************************************************************************/ -/* *** general file routines *****/ - -/* Returns whether end of file was encountered in previous - read operation. */ -picoos_bool picoos_Eof(picoos_File f); - -/* sets the file pointer to - 'pos' bytes from beginning (first byte = byte 0). This - routine should only be used for binary files. */ -picoos_bool picoos_SetPos(picoos_File f, picoos_int32 pos); - -/* Get position from file 'f'. */ -picoos_bool picoos_GetPos(picoos_File f, picoos_uint32 * pos); - -/* Returns the length of the file in bytes. */ -picoos_bool picoos_FileLength(picoos_File f, picoos_uint32 * len); - -/* Return full name of file 'f'. */ -picoos_bool picoos_Name(picoos_File f, picoos_char name[], picoos_uint32 maxsize); - -/* Returns whether file 'name' exists or not. */ -picoos_bool picoos_FileExists(picoos_Common g, picoos_char name[] /*, picoos_char ckey[] */); - -/* Delete a file. */ -picoos_bool picoos_Delete(picoos_char name[]); - -/* Rename a file. */ -picoos_bool picoos_Rename(picoos_char oldName[], picoos_char newName[]); - - -/* *****************************************************************/ -/* Sampled Data Files */ -/* *****************************************************************/ - -#define SAMPLE_FREQ_16KHZ (picoos_uint32) 16000 - -typedef enum { - FILE_TYPE_WAV, - FILE_TYPE_AU, - FILE_TYPE_RAW, - FILE_TYPE_OTHER -} wave_file_type_t; - -typedef enum { - FORMAT_TAG_LIN = 1, /**< linear 16-bit encoding */ - FORMAT_TAG_ALAW = 6, /**< a-law encoding, 8 bit */ - FORMAT_TAG_ULAW = 7 /**< u-law encoding, 8 bit */ - /* there are many more */ -} wave_format_tag_t; - - -typedef enum { - /* values corresponding RIFF wFormatTag */ - PICOOS_ENC_LIN = FORMAT_TAG_LIN, /**< linear 16-bit encoding; standard */ - PICOOS_ENC_ALAW = FORMAT_TAG_ALAW, /**< a-law encoding, 8 bit */ - PICOOS_ENC_ULAW = FORMAT_TAG_ULAW, /**< u-law encoding, 8 bit */ - /* values outside RIFF wFormatTag values (above 4100) */ - PICOOS_ENC_OTHER = 5000 /**< other; (treated as raw) */ - } picoos_encoding_t; - -typedef struct picoos_sd_file * picoos_SDFile; - -/* SDFile input functions */ - -/* orig. comment from SDInOut.def - Opens sampled data file 'fileName' for input and returns - the encoding 'enc' of the file, sampling rate 'sf', - nr of samples 'nrSamples', and a handle to the opened file - in 'sdFile'. - - If 'fileName' is empty, the input is taken from the direct - acoustic input using the sampling rate specified by - "SetRawDefaults". In this case, 'encoding' returns 'EncLin', - and 'nrSamples' returns 0. - - The file format is taken from the file name extension: - ".wav" --> wav file - ".au" --> au file - other extensions --> headerless files - - For wav and au files, the sampling rate and encoding are taken - from the file header and returned in 'sf' and 'enc'. For - headerless files, 'sf' and 'enc' are taken from the - most recently set default values (procedure SetRawDefaults). - - 'done' returns whether the sampled data file was successfully - opened. */ -extern picoos_bool picoos_sdfOpenIn (picoos_Common g, picoos_SDFile * sdFile, picoos_char fileName[], picoos_uint32 * sf, picoos_encoding_t * enc, picoos_uint32 * nrSamples); - - -extern picoos_bool picoos_sdfGetSamples (picoos_SDFile sdFile, picoos_uint32 start, picoos_uint32 * nrSamples, picoos_int16 samples[]); - - -extern picoos_bool picoos_sdfCloseIn (picoos_Common g, picoos_SDFile * sdFile); - - -/* SDFile output functions*/ - -extern picoos_bool picoos_sdfOpenOut (picoos_Common g, picoos_SDFile * sdFile, picoos_char fileName[], int sf, picoos_encoding_t enc); - - -extern picoos_bool picoos_sdfPutSamples (picoos_SDFile sdFile, picoos_uint32 nrSamples, picoos_int16 samples[]); - -/* -extern picoos_bool picoos_AbortOutput (picoos_SDFile sdFile); - - -extern picoos_bool picoos_ResumeOutput (picoos_SDFile sdFile); - - -extern picoos_bool picoos_FlushOutput (picoos_SDFile sdFile); -*/ - -extern picoos_bool picoos_sdfCloseOut (picoos_Common g, picoos_SDFile * sdFile); - - -/* *****************************************************************/ -/* File Headers */ -/* *****************************************************************/ - -#define PICOOS_MAX_FIELD_STRING_LEN 32 /* including terminating char */ - -#define PICOOS_MAX_NUM_HEADER_FIELDS 10 -#define PICOOS_NUM_BASIC_HEADER_FIELDS 5 - -#define PICOOS_HEADER_NAME 0 -#define PICOOS_HEADER_VERSION 1 -#define PICOOS_HEADER_DATE 2 -#define PICOOS_HEADER_TIME 3 -#define PICOOS_HEADER_CONTENT_TYPE 4 - -#define PICOOS_MAX_HEADER_STRING_LEN (PICOOS_MAX_NUM_HEADER_FIELDS * (2 * PICOOS_MAX_FIELD_STRING_LEN)) - -typedef picoos_char picoos_field_string_t[PICOOS_MAX_FIELD_STRING_LEN]; - -typedef picoos_char picoos_header_string_t[PICOOS_MAX_HEADER_STRING_LEN]; - -typedef enum {PICOOS_FIELD_IGNORE, PICOOS_FIELD_EQUAL, PICOOS_FIELD_COMPAT} picoos_compare_op_t; - -/* private */ -typedef struct picoos_file_header_field { - picoos_field_string_t key; - picoos_field_string_t value; - picoos_compare_op_t op; -} picoos_file_header_field_t; - -/* public */ -typedef struct picoos_file_header * picoos_FileHeader; -typedef struct picoos_file_header { - picoos_uint8 numFields; - picoos_file_header_field_t field[PICOOS_MAX_NUM_HEADER_FIELDS]; -} picoos_file_header_t; - - -pico_status_t picoos_clearHeader(picoos_FileHeader header); - -pico_status_t picoos_setHeaderField(picoos_FileHeader header, picoos_uint8 index, picoos_char * key, picoos_char * value, picoos_compare_op_t op); - -/* caller has to make sure allocated space at key and value are large enough to hold a picoos_field_string */ -pico_status_t picoos_getHeaderField(picoos_FileHeader header, picoos_uint8 index, picoos_field_string_t key, picoos_field_string_t value, picoos_compare_op_t * op); - -/* caller has to make sure allocated space at str is large enough to hold the header in question */ -/* -pico_status_t picoos_hdrToString(picoos_FileHeader header, picoos_header_string_t str); -*/ - -pico_status_t picoos_hdrParseHeader(picoos_FileHeader header, picoos_header_string_t str); - -pico_status_t picoos_getSVOXHeaderString(picoos_char * str, picoos_uint8 * len, picoos_uint32 maxlen); - -pico_status_t picoos_readPicoHeader(picoos_File f, picoos_uint32 * headerlen); - - - -/* *****************************************************************/ -/* String search and compare operations */ -/* *****************************************************************/ - - -picoos_uint8 picoos_has_extension(const picoos_char *str, const picoos_char *suf); - -/* *****************************************************************/ -/* String/Number Manipulations (might be moved to picopal) */ -/* *****************************************************************/ - -pico_status_t picoos_string_to_int32(picoos_char str[], - picoos_int32 * res); - -pico_status_t picoos_string_to_uint32(picoos_char str[], - picoos_uint32 * res); - -/* 'stringlen' is the part of input string to be considered, possibly not containing NULLC (e.g. result of strlen). - * 'maxsize' is the maximal size of 'part' including a byte for the terminating NULLC! */ -void picoos_get_sep_part_str(picoos_char string[], - picoos_int32 stringlen, picoos_int32 * ind, picoos_char sepCh, - picoos_char part[], picoos_int32 maxsize, picoos_uint8 * done); - -/* searches for the first contiguous string of printable characters (> ' ') inside fromStr, possibly skipping - * chars <= ' ') and returns it in toStr. - * fromStr is assumed to be NULLC terminated and toStr is forced to be NULLC terminated within maxsize. - * The search is started at *pos inside fromStr and at return, *pos is the position within fromStr after the - * found string, or the position after the end of fromStr, if no string was found. - * the function returns TRUE if a string was found and fitted toStr, or FALSE otherwise. */ -picoos_uint8 picoos_get_str (picoos_char * fromStr, picoos_uint32 * pos, picoos_char * toStr, picoos_objsize_t maxsize); - - -pico_status_t picoos_read_mem_pi_uint16 (picoos_uint8 * data, picoos_uint32 * pos, picoos_uint16 * val); - -pico_status_t picoos_read_mem_pi_uint32 (picoos_uint8 * data, picoos_uint32 * pos, picoos_uint32 * val); - -pico_status_t picoos_write_mem_pi_uint16 (picoos_uint8 * data, picoos_uint32 * pos, picoos_uint16 val); - - -/* *****************************************************************/ -/* timer function */ -/* *****************************************************************/ - -void picoos_get_timer(picopal_uint32 * sec, picopal_uint32 * usec); - -#ifdef __cplusplus -} -#endif - - -#endif /*PICOOS_H_*/ diff --git a/lib/picopal.c b/lib/picopal.c deleted file mode 100644 index db05e2b..0000000 --- a/lib/picopal.c +++ /dev/null @@ -1,554 +0,0 @@ -/* - * 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 picopal.c - * - * pico platform abstraction layer - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -/* GCC does not supporte #pragma message */ -#if !defined(__GNUC__) -#define PRAGMA_MESSAGE -#endif - -#if defined(PRAGMA_MESSAGE) && defined(PICO_PLATFORM) -#pragma message("PICO_PLATFORM : is defined externally") -#endif - -#if defined(PRAGMA_MESSAGE) && defined(_WIN32) -#pragma message("_WIN32 : is defined") -#endif - -#if defined(PRAGMA_MESSAGE) && defined(__APPLE__) -#pragma message("__APPLE__ : is defined") -#endif - -#if defined(PRAGMA_MESSAGE) && defined(__MACH__) -#pragma message("__MACH__ : is defined") -#endif - -#if defined(PRAGMA_MESSAGE) && defined(macintosh) -#pragma message("macintosh : is defined") -#endif - -#if defined(PRAGMA_MESSAGE) && defined(linux) -#pragma message("linux : is defined") -#endif -#if defined(PRAGMA_MESSAGE) && defined(__linux__) -#pragma message("__linux__ : is defined") -#endif -#if defined(PRAGMA_MESSAGE) && defined(__linux) -#pragma message("__linux : is defined") -#endif - - -#include -#include -#include -#include - -#include "picodefs.h" -#include "picopal.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -#if PICO_PLATFORM == PICO_Windows -/* use high-resolution timer functions on Windows platform */ -#define USE_CLOCK 0 -#else -/* use clock() function instead of high-resolution timer on - non-Windows platforms */ -#define USE_CLOCK 1 -#endif - -#include -#if PICO_PLATFORM == PICO_Windows -#include -#endif - -#if defined(PRAGMA_MESSAGE) -#pragma message("PICO_PLATFORM : " PICO_PLATFORM_STRING) -#endif - - -picopal_int32 picopal_atoi(const picopal_char *s) { - return (picopal_int32)atoi((const char *)s); -} - -picopal_int32 picopal_strcmp(const picopal_char *a, const picopal_char *b) { - return (picopal_int32)strcmp((const char *)a, (const char *)b); -} - -picopal_int32 picopal_strncmp(const picopal_char *a, const picopal_char *b, picopal_objsize_t siz) { - return (picopal_int32)strncmp((const char *)a, (const char *)b, (size_t) siz); -} - -picopal_objsize_t picopal_strlen(const picopal_char *s) { - return (picopal_objsize_t)strlen((const char *)s); -} - -picopal_char *picopal_strchr(const picopal_char *s, picopal_char c) { - return (picopal_char *)strchr((const char *)s, (int)c); -} - -picopal_char *picopal_strstr(const picopal_char *s, const picopal_char *substr) { - return (picopal_char *)strstr((const char *)s, (const char *)substr); -} - -picopal_char *picopal_strcpy(picopal_char *d, const picopal_char *s) { - return (picopal_char *)strcpy((char *)d, (const char *)s); -} - -picopal_char *picopal_strcat(picopal_char *dest, const picopal_char *src) { - return (picopal_char *)strcat((char *)dest, (const char *)src); -} - - -/* copy src into dst, but make sure that dst is not accessed beyond its size 'siz' and is allways NULLC-terminated. - * 'siz' is the number of bytes of the destination, including one byte for NULLC! - * returns the full length of the input string, not including termination NULLC (strlen(src)). - * the copy is successfull without truncation if picopal_strlcpy(dst,src,siz) < siz */ -picopal_objsize_t picopal_strlcpy(picopal_char *dst, const picopal_char *src, picopal_objsize_t siz) -{ - picopal_char *d = dst; - const picopal_char *s = src; - picopal_objsize_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0) { - while (--n != 0) { - if ((*(d++) = *(s++)) == NULLC) { - break; - } - } - } - - /* Not enough room in dst, add NULLC and traverse rest of src */ - if (n == 0) { - if (siz != 0) { - *d = NULLC; /* NULLC-terminate dst */ - } - while (*(s++)) {} - ; - } - - return(s - src - 1); /* count does not include NULLC */ -} - - -picopal_int16 picopal_sprintf(picopal_char * dst, const picopal_char *fmt, ...) -{ - picopal_int16 i; - va_list args; - - va_start(args, (char *)fmt); - i = (picopal_int16)vsprintf((char *) dst, (const char *)fmt, args); - va_end(args); - return i; -} - - -picopal_objsize_t picopal_vslprintf(picopal_char * dst, picopal_objsize_t siz, const picopal_char *fmt, va_list args) { - picopal_char buf[21]; - picopal_char *d = dst; - const picopal_char *f = fmt; - picopal_char * b; - picopal_objsize_t len, nnew, n = siz; - picopal_int32 ival; - picopal_char cval; - picopal_objsize_t i = 0; - - if (!f) { - f = (picopal_char *) ""; - } - while (*f) { - if (*f == '%') { - switch (*(++f)) { - case 'i': - f++; - ival = va_arg(args,int); - picopal_sprintf(buf,(picopal_char *)"%i",ival); - b = buf; - break; - case 'c': - f++; - cval = va_arg(args,int); - picopal_sprintf(buf,(picopal_char *)"%c",cval); - b = buf; - break; - case 's': - f++; - b = (picopal_char *) va_arg(args, char*); - break; - default: - if (n > 0) { - (*d++) = '%'; - n--; - } - i++; - b = NULL; - break; - } - if (b) { - len = picopal_strlcpy(d,b,n); /* n1 is the actual length of sval */ - i += len; - nnew = (n > len) ? n-len : 0; /* nnew is the new value of n */ - d += (n - nnew); - n = nnew; - } - } else { - if (n) { - (*d++) = (*f); - n--; - } - i++; - f++; - } - } - - return i; -} - -picopal_objsize_t picopal_slprintf(picopal_char * dst, picopal_objsize_t siz, const picopal_char *fmt, /*args*/ ...) { - picopal_objsize_t i; - va_list args; - - va_start(args, (char *)fmt); - i = picopal_vslprintf(dst, siz, fmt, args); - va_end(args); - return i; - -} - - -/* copies 'length' bytes from 'src' to 'dest'. (regions may be overlapping) no error checks! */ -void * picopal_mem_copy(const void * src, void * dst, picopal_objsize_t length) -{ - return memmove(dst, src, (size_t) length); -} - -/* sets 'length' bytes starting at dest[0] to 'byte_val' */ -void * picopal_mem_set(void * dest, picopal_uint8 byte_val, picopal_objsize_t length) -{ - return memset(dest, (int) byte_val, (size_t) length); -} - -/* *************************************************/ -/* fixed-point math */ -/* *************************************************/ - -/* *************************************************/ -/* transcendent math */ -/* *************************************************/ - - -picopal_double picopal_cos(const picopal_double cos_arg) -{ - return (picopal_double) cos((double)cos_arg); -} -picopal_double picopal_sin(const picopal_double sin_arg) -{ - return (picopal_double) sin((double) sin_arg); -} -picopal_double picopal_fabs(const picopal_double fabs_arg) -{ - return (picopal_double) fabs((double) fabs_arg); -} - - -/* *************************************************/ -/* file access */ -/* *************************************************/ -#define PICOPAL_EOL '\n' - -picopal_char picopal_eol(void) -{ - return PICOPAL_EOL; -} - -/* 'fopen' opens the file with name 'filename'. Depending on - 'mode' : - 'PICOPAL_TEXT_READ' : Opens an existing text file for reading. - The file is positioned at the beginning of the file. - 'PICOPAL_TEXT_WRITE' : Opens and truncates an existing file or creates a new - text file for writing. The file is positioned at the - beginning. - 'PICOPAL_BIN_READ' : Opens an existing binary file for reading. - The file is positioned at the beginning of the file. - 'PICOPAL_BIN_WRITE' : Opens and truncates an existing file or creates a new - binary file for writing. The file is positioned at the - beginning. - If the opening of the file is successful a file pointer is given - back. Otherwise a NIL-File is given back. -*/ -picopal_File picopal_fopen (picopal_char filename[], picopal_access_mode mode) -{ - picopal_File res; - - switch (mode) { - case PICOPAL_TEXT_READ : - res = (picopal_File) fopen((char *)filename, (char *)"r"); - break; - case PICOPAL_TEXT_WRITE : - res = (picopal_File) fopen((char *)filename, (char *)"w"); - break; - case PICOPAL_BINARY_READ : - res = (picopal_File) fopen((char *)filename, (char *)"rb"); - break; - case PICOPAL_BINARY_WRITE : - res = (picopal_File) fopen((char *)filename, (char *)"wb"); - break; - default : - res = (picopal_File) NULL; - } - return res; - -} - - -picopal_File picopal_get_fnil (void) -{ - return (picopal_File) NULL; -} - - -picopal_int8 picopal_is_fnil (picopal_File f) -{ - return (NULL == f); -} - -pico_status_t picopal_fflush (picopal_File f) -{ - return (0 == fflush((FILE *)f)) ? PICO_OK : PICO_EOF; -} - - -pico_status_t picopal_fclose (picopal_File f) -{ - return (0 == fclose((FILE *)f)) ? PICO_OK : PICO_EOF; -} - - - -picopal_uint32 picopal_flength (picopal_File stream) -{ - fpos_t fpos; - picopal_int32 len; - - fgetpos((FILE *)stream,&fpos); - picopal_fseek(stream,0,SEEK_END); - len = ftell((FILE *)stream); - fsetpos((FILE *)stream,&fpos); - clearerr((FILE *)stream); - return len; - -} - -picopal_uint8 picopal_feof (picopal_File stream) -{ - return (0 != feof((FILE *)stream)); - -} - -pico_status_t picopal_fseek (picopal_File f, picopal_uint32 offset, picopal_int8 seekmode) -{ - return (0 == fseek((FILE *)f, offset, seekmode)) ? PICO_OK : PICO_EOF; -} - -pico_status_t picopal_fget_char (picopal_File f, picopal_char * ch) -{ - picopal_int16 res; - - res = fgetc((FILE *)f); - if (res >= 0) { - *ch = (picopal_char) res; - } - else { - *ch = '\0'; - } - return (res >= 0) ? PICO_OK : PICO_EOF; -} - -picopal_objsize_t picopal_fread_bytes (picopal_File f, void * ptr, picopal_objsize_t objsize, picopal_uint32 nobj) -{ - return (picopal_objsize_t) fread(ptr, objsize, nobj, (FILE *)f); -} - -picopal_objsize_t picopal_fwrite_bytes (picopal_File f, void * ptr, picopal_objsize_t objsize, picopal_uint32 nobj){ return (picopal_objsize_t) fwrite(ptr, objsize, nobj, (FILE *)f);} -/* *************************************************/ -/* functions for debugging/testing purposes only */ -/* *************************************************/ - -void *picopal_mpr_alloc(picopal_objsize_t size) -{ -#if PICO_PLATFORM == PICO_Windows - return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); -#else - /* not yet implemented for other platforms; corresponding - function on UNIX systems is pvalloc */ - return NULL; -#endif - size = size; /* avoid warning "var not used in this function"*/ - -} - -void picopal_mpr_free(void **p) -{ -#if PICO_PLATFORM == PICO_Windows - VirtualFree(*p, 0, MEM_RELEASE); -#else - /* not yet implemented for other platforms */ -#endif - *p = NULL; -} - -pico_status_t picopal_mpr_protect(void *addr, picopal_objsize_t len, picopal_int16 prot) -{ - pico_status_t status = PICO_OK; - -#if PICO_PLATFORM == PICO_Windows - DWORD dwNewProtect, dwOldProtect; - dwNewProtect = PICOPAL_PROT_NONE; - if (prot & PICOPAL_PROT_READ) { - if (prot & PICOPAL_PROT_WRITE) { - dwNewProtect = PAGE_READWRITE; - } else { - dwNewProtect = PAGE_READONLY; - } - } else if (prot & PICOPAL_PROT_WRITE) { - /* under Windows write-only is not possible */ - dwNewProtect = PAGE_READWRITE; - } - if (!VirtualProtect(addr, len, dwNewProtect, &dwOldProtect)) { - status = PICO_ERR_OTHER; - } -#else - /* not yet implemented for other platforms */ - addr = addr; /* avoid warning "var not used in this function"*/ - len = len; /* avoid warning "var not used in this function"*/ - prot = prot; /* avoid warning "var not used in this function"*/ - -#endif - return status; -} -/* - * Reference: - * A Fast, Compact Approximation of the Exponential Function by Nicol N. Schraudolph in Neural Computation, 11,853-862 (1999) - * See also: http://www-h.eng.cam.ac.uk/help/tpl/programs/Matlab/mex.html - * - */ -picopal_double picopal_quick_exp(const picopal_double y) { - union { - picopal_double d; - struct { - #if PICO_ENDIANNESS == ENDIANNESS_LITTLE /* little endian */ - picopal_int32 j,i; - #else - picopal_int32 i,j; - #endif - } n; - - } _eco; - _eco.n.i = (picopal_int32)(1512775.3951951856938297995605697f * y) + 1072632447; - return _eco.d; -} - - -/* *************************************************/ -/* timer */ -/* *************************************************/ - -#if IMPLEMENT_TIMER - -#define USEC_PER_SEC 1000000 - -typedef clock_t picopal_clock_t; - - -#if USE_CLOCK -picopal_clock_t startTime; -#else -int timerInit = 0; -LARGE_INTEGER startTime; -LARGE_INTEGER timerFreq; -#endif - - -picopal_clock_t picopal_clock(void) -{ - return (picopal_clock_t)clock(); -} - -#endif /* IMPLEMENT_TIMER */ - -void picopal_get_timer(picopal_uint32 * sec, picopal_uint32 * usec) -{ -#if IMPLEMENT_TIMER -#if USE_CLOCK - picopal_clock_t dt; - dt = picopal_clock() - startTime; - *sec = dt / CLOCKS_PER_SEC; - *usec = USEC_PER_SEC * (dt % CLOCKS_PER_SEC) / CLOCKS_PER_SEC; -#else - LARGE_INTEGER now; - if (!timerInit) { - QueryPerformanceFrequency(&timerFreq); - timerInit = 1; - } - if (QueryPerformanceCounter(&now) && 0) { -/* - LONGLONG dt, tf; - dt = now.QuadPart - GLOB(startTime).QuadPart; - tf = GLOB(timerFreq).QuadPart; - *sec = (unsigned int) (dt / tf); - *usec = (unsigned int) (USEC_PER_SEC * (dt % tf) / tf); -*/ - double dt, tf; - dt = (double)(now.QuadPart - startTime.QuadPart); - tf = (double)(timerFreq.QuadPart); - *sec = (unsigned int) (dt /tf); - *usec = (unsigned int) ((double)USEC_PER_SEC * (dt / tf)) % USEC_PER_SEC; - } else { - /* high freq counter not supported by system */ - DWORD dt; - dt = GetTickCount() - startTime.LowPart; - *sec = dt / 1000; - *usec = 1000 * (dt % 1000); - } -#endif /* USE_CLOCK */ -#else - *sec = 0; - *usec = 0; -#endif /* IMPLEMENT_TIMER */ -} - -#ifdef __cplusplus -} -#endif - -/* End picopal.c */ diff --git a/lib/picopal.h b/lib/picopal.h deleted file mode 100644 index acfc8e0..0000000 --- a/lib/picopal.h +++ /dev/null @@ -1,288 +0,0 @@ -/* - * 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 picopal.h - * - * pico plattform abstraction layer - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -/** - * @addtogroup picoos - - * Operating system Platform Specific implementation module \n - * -*/ -#ifndef PICOPAL_H_ -#define PICOPAL_H_ - -#include -#include -#include -#include -#include -#include "picopltf.h" -#include "picodefs.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* *********************************************************/ -/* general defines and typedefs (used to be in picodefs.h) */ -/* *********************************************************/ - -#define TRUE 1 -#define FALSE 0 - -#ifndef NULL -#define NULL 0 -#endif - -#define NULLC '\000' - - -/* "strange" defines to switch variants... */ -#define PICOPAL_DIV_USE_INV 0 - - -/*---------------Externals-----------------------*/ -/* used by picocep*/ -#if defined(PICO_DEBUG) - extern int numlongmult, numshortmult; -#endif - - -typedef signed int pico_status_t; - - -/* unfortunately, ANSI-C uses eof for results and exceptional results .. */ -/* in the context of reading from a CharBuffer, eof means "no more - input available FOR NOW" */ - -#define PICO_EOF (pico_status_t) -1 - - -/* *************************************************/ -/* constants */ -/* *************************************************/ - - - /* operating system identifications */ -#define PICOPAL_OS_NIL 0 /* just an unchangeable first value */ -#define PICOPAL_OS_WINDOWS 1 -/* ... */ -#define PICOPAL_OS_GENERIC 99 /* must always be the last value */ - -/* *************************************************/ -/* types */ -/* *************************************************/ - -typedef unsigned char picopal_uint8; -typedef unsigned short picopal_uint16; -typedef unsigned int picopal_uint32; - -typedef signed char picopal_int8; -typedef signed short picopal_int16; -typedef signed int picopal_int32; - -typedef float picopal_single; -typedef double picopal_double; - -typedef unsigned char picopal_char; - -typedef unsigned char picopal_uchar; - -typedef size_t picopal_objsize_t; -typedef ptrdiff_t picopal_ptrdiff_t; - -/* *************************************************/ -/* functions */ -/* *************************************************/ - -picopal_int32 picopal_atoi(const picopal_char *); - -picopal_int32 picopal_strcmp(const picopal_char *, const picopal_char *); -picopal_int32 picopal_strncmp(const picopal_char *a, const picopal_char *b, picopal_objsize_t siz); -picopal_objsize_t picopal_strlen(const picopal_char *); -picopal_char * picopal_strchr(const picopal_char *, picopal_char); -picopal_char * picopal_strcpy(picopal_char *d, const picopal_char *s); -picopal_char *picopal_strstr(const picopal_char *s, const picopal_char *substr); -picopal_char *picopal_strcat(picopal_char *dest, const picopal_char *src); -picopal_int16 picopal_sprintf(picopal_char * dst, const picopal_char *fmt, ...); - -/* copies 'length' bytes from 'src' to 'dest'. (regions may be overlapping) no error checks! */ -void * picopal_mem_copy(const void * src, void * dst, picopal_objsize_t length); - -/* sets 'length' bytes starting at dest[0] to 'byte_val' */ -void * picopal_mem_set(void * dest, picopal_uint8 byte_val, picopal_objsize_t length); - -/* safe versions */ -picopal_objsize_t picopal_vslprintf(picopal_char * dst, picopal_objsize_t siz, const picopal_char *fmt, va_list args); -picopal_objsize_t picopal_slprintf(picopal_char * dst, picopal_objsize_t siz, const picopal_char *fmt, /*args*/ ...); -picopal_objsize_t picopal_strlcpy(picopal_char *dst, const picopal_char *src, picopal_objsize_t siz); - -/*Fixed point computation*/ -/* -picopal_int32 picopal_fixptdiv(picopal_int32 a, picopal_int32 b, picopal_uint8 bigpow); -picopal_int32 picopal_fixptmult(picopal_int32 x, picopal_int32 y, picopal_uint8 bigpow); -picopal_int32 picopal_fixptdivORinv(picopal_int32 a, picopal_int32 b, picopal_int32 invb, picopal_uint8 bigpow); -picopal_int32 picopal_fixptmultdouble(picopal_int32 x, picopal_int32 y, picopal_uint8 bigpow); -picopal_uint8 picopal_highestBit(picopal_int32 x); -*/ - -/* *************************************************/ -/* math */ -/* *************************************************/ - -picopal_double picopal_cos (const picopal_double cos_arg); -picopal_double picopal_sin (const picopal_double sin_arg); -picopal_double picopal_fabs (const picopal_double fabs_arg); - - - - -/* *************************************************/ -/* file access */ -/* *************************************************/ - -extern picopal_char picopal_eol(void); - -#define picopal_FILE FILE - - -/* seek modes to be used with the 'FSeek' procedure */ -#define PICOPAL_SEEK_SET 0 /* absolut seek position */ -#define PICOPAL_SEEK_CUR 1 /* relative to current */ -#define PICOPAL_SEEK_END 2 /* relative to the end of the file */ - - -typedef enum {PICOPAL_BINARY_READ, PICOPAL_BINARY_WRITE, PICOPAL_TEXT_READ, PICOPAL_TEXT_WRITE} picopal_access_mode; - -typedef picopal_FILE * picopal_File; - -extern picopal_File picopal_fopen (picopal_char fileName[], picopal_access_mode mode); -/* 'FOpen' opens the file with name 'filename'. Depending on - 'mode' : - 'TextRead' : Opens an existing text file for reading. - The file is positioned at the beginning of the file. - 'TextWrite' : Opens and truncates an existing file or creates a new - text file for writing. The file is positioned at the - beginning. - 'BinaryRead' : Opens an existing binary file for reading. - The file is positioned at the beginning of the file. - 'BinaryWrite' : Opens and truncates an existing file or creates a new - binary file for writing. The file is positioned at the - beginning. - If the opening of the file is successful a file pointer is given - back. Otherwise a NIL-File is given back. -*/ - - -extern picopal_File picopal_get_fnil (void); - - -extern picopal_int8 picopal_is_fnil (picopal_File f); - - -extern pico_status_t picopal_fclose (picopal_File f); - - -extern picopal_uint32 picopal_flength (picopal_File f); - - -extern picopal_uint8 picopal_feof (picopal_File f); - - -extern pico_status_t picopal_fseek (picopal_File f, picopal_uint32 offset, picopal_int8 seekmode); - - -extern pico_status_t picopal_fget_char (picopal_File f, picopal_char * ch); - - -extern picopal_objsize_t picopal_fread_bytes (picopal_File f, void * ptr, picopal_objsize_t objsize, picopal_uint32 nobj); - -extern picopal_objsize_t picopal_fwrite_bytes (picopal_File f, void * ptr, picopal_objsize_t objsize, picopal_uint32 nobj); - - -extern pico_status_t picopal_fflush (picopal_File f); - -/* -extern pico_status_t picopal_fput_char (picopal_File f, picopal_char ch); -*/ - - -/* -extern pico_status_t picopal_remove (picopal_char filename[]); - - -extern pico_status_t picopal_rename (picopal_char oldname[], picopal_char newname[]); - -*/ - -/* *************************************************/ -/* functions for debugging/testing purposes only */ -/* *************************************************/ - -/** - * Returns a pointer to a newly allocated chunk of 'size' bytes, aligned - * to the system page size. - * Memory allocated by this routine may be protected by calling function - * picopal_mrp_protect(). - */ -void *picopal_mpr_alloc(picopal_objsize_t size); - -/** - * Releases the chunk of memory pointed to by '*p'. 'p' must be previously - * allocated by a call to picopal_mpr_alloc(). - */ -void picopal_mpr_free(void **p); - -#define PICOPAL_PROT_NONE 0 /* the memory cannot be accessed at all */ -#define PICOPAL_PROT_READ 1 /* the memory can be read */ -#define PICOPAL_PROT_WRITE 2 /* the memory can be written to */ - -/** - * Specifies the desired protection 'prot' for the memory page(s) containing - * part or all of the interval [addr, addr+len-1]. If an access is disallowed - * by the protection given it, the program receives a SIGSEGV. - */ -pico_status_t picopal_mpr_protect(void *addr, picopal_objsize_t len, picopal_int16 prot); - -/* Fast, Compact Approximation of the Exponential Function */ -picopal_double picopal_quick_exp(const picopal_double y); - -/* *************************************************/ -/* types functions for time measurement */ -/* *************************************************/ - -extern void picopal_get_timer(picopal_uint32 * sec, picopal_uint32 * usec); - -#ifdef __cplusplus -} -#endif - - -#endif /*PICOPAL_H_*/ diff --git a/lib/picopam.c b/lib/picopam.c deleted file mode 100644 index 02e5cc2..0000000 --- a/lib/picopam.c +++ /dev/null @@ -1,4803 +0,0 @@ -/* - * 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 picopam.c - * - * Phonetic to Acoustic Mapping 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 "picopam.h" -#include "picokdt.h" -#include "picokpdf.h" -#include "picoktab.h" -#include "picokdbg.h" -#include "picodsp.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -#define PICOPAM_IN_BUFF_SIZE PICODATA_BUFSIZE_PAM /*input buffer size for PAM */ -#define PICOPAM_OUT_PAM_SIZE PICODATA_BUFSIZE_PAM /*output buffer size for PAM*/ -#define PICOPAM_DT_NRLFZ 5 /* nr of lfz decision trees per phoneme */ -#define PICOPAM_DT_NRMGC 5 /* nr of mgc decision trees per phoneme */ -#define PICOPAM_NRSTPF 5 /* nr of states per phone */ - -#define PICOPAM_COLLECT 0 -#define PICOPAM_SCHEDULE 1 -#define PICOPAM_IMMEDIATE 2 -#define PICOPAM_FORWARD 3 -#define PICOPAM_FORWARD_FORCE_TERM 4 -#define PICOPAM_PROCESS 5 -#define PICOPAM_PLAY 6 -#define PICOPAM_FEED 7 - -#define PICOPAM_CONTINUE 100 -#define PICOPAM_GOTO_SCHEDULE 1 -#define PICOPAM_FLUSH_RECEIVED 6 -#define PICOPAM_GOTO_FEED 7 -#define PICOPAM_PRE_SYLL_ENDED 10 - -#define PICOPAM_BREAK_ADD_SIZE 4 /*syllable feature vector increment dued to BREAK and SILENCE*/ -#define PICOPAM_VECT_SIZE 64+PICOPAM_BREAK_ADD_SIZE /*syllable feature vector size (bytes)*/ -#define PICOPAM_INVEC_SIZE 60 /*phone feature vector size */ -#define PICOPAM_MAX_SYLL_PER_SENT 100 /*maximum number of syllables per sentece*/ -#define PICOPAM_MAX_PH_PER_SENT 400 /*maximum number of phonemes per sentece*/ -#define PICOPAM_MAX_ITEM_PER_SENT 255 /*maximum number of attached items per sentence*/ -#define PICOPAM_MAX_ITEM_SIZE_PER_SENT 4096 /*maximum size of attached items per sentence*/ - -#define PICOPAM_READY 20 /*PAM could start backward processing*/ -#define PICOPAM_MORE 21 /*PAM has still to collect */ -#define PICOPAM_NA 22 /*PAM has not to deal with this item*/ -#define PICOPAM_ERR 23 /*input item is not a valid item*/ - -/*sentence types:cfr pam_map_sentence_type*/ -#define PICOPAM_DECLARATIVE 0 -#define PICOPAM_INTERROGATIVE 1 -#define PICOPAM_EXCLAMATIVE 2 - -#define PICOPAM_T 0 -#define PICOPAM_P 1 -#define PICOPAM_p 2 -#define PICOPAM_Y 3 - -#if 1 -#define PAM_PHR2_WITH_PR1 1 /*deal with PHR2 boundaries as with PHR1*/ -#else -#define PAM_PHR2_WITH_PR3 1 /*deal with PHR2 boundaries as with PHR3*/ -#endif - -#define PICOPAM_DONT_CARE_VALUE 250 /*don't care value for tree printout */ -#define PICOPAM_DONT_CARE_VAL 10 /*don't care value for tree feeding */ -#define PICOPAM_PH_DONT_CARE_VAL 7 /*don't care value for tree feeding (phonetic)*/ - -#define PICOPAM_MAX_STATES_PER_PHONE 5 /*number of states per phone */ -#define PICOPAM_STATE_SIZE_IN_ITEM 6 /*size of a state in frame item */ -#define PICOPAM_FRAME_ITEM_SIZE 4+PICOPAM_MAX_STATES_PER_PHONE*PICOPAM_STATE_SIZE_IN_ITEM - -#define PICOPAM_DIR_FORW 0 /*forward adapter processing*/ -#define PICOPAM_DIR_BACK 1 /*backward adapter processing*/ -#define PICOPAM_DIR_SIL 2 /*final silence attributes*/ - -#define PICOPAM_SYLL_PAUSE 0 /*syllable but containing a pause phone*/ -#define PICOPAM_SYLL_SYLL 1 /*a real syllable with phonemes*/ - -#define PICOPAM_EVENT_P_BOUND 0 /*primary boundary*/ -#define PICOPAM_EVENT_S_BOUND 1 /*secondary boundary*/ -#define PICOPAM_EVENT_W_BOUND 3 /*word boundary*/ -#define PICOPAM_EVENT_SYLL 4 /*syllable*/ - -/* ----- CONSTANTS FOR BREAK COMMAND SUPPORT ----- */ -#define PICOPAM_PWIDX_SBEG 0 -#define PICOPAM_PWIDX_PHR1 1 -#define PICOPAM_PWIDX_PHR2 2 -#define PICOPAM_PWIDX_SEND 3 -#define PICOPAM_PWIDX_DEFA 4 -#define PICOPAM_PWIDX_SIZE 5 - -/*----------------------------------------------------------------*/ -/*structure related to the feature vectors for feeding the trees */ -/*NOTE : the same data structure is used to manage the syllables */ -/* Using the first 8 fields for marking the boundaries */ -/* and using the last 4 bytes as follows */ -/* byte 61 : 1st attached non PAM item id(0=no item attached) */ -/* in the "sSyllItemOffs" data structure */ -/* byte 62 : last attached non PAM item id(0=no item attached)*/ -/* in the "sSyllItemOffs" data structure */ -/* byte 63..64 : offset of the start of the syllable in */ -/* the "sPhIds" data structure */ -typedef struct -{ - picopal_uint8 phoneV[PICOPAM_VECT_SIZE]; -} sFtVect, *pSftVect; - -/*---------------------------------------------------------- - Name : pam_subobj - Function: subobject definition for the pam processing - Shortcut: pam - ---------------------------------------------------------*/ -typedef struct pam_subobj -{ - /*----------------------PU voice management------------------------------*/ - /* picorsrc_Voice voice; */ - /*----------------------PU state management------------------------------*/ - picoos_uint8 procState; /* where to take up work at next processing step */ - picoos_uint8 retState; /* where to go back from feed state at next p.s. */ - picoos_uint8 needMoreInput; /* more data necessary to start processing */ - /*----------------------PU input management------------------------------*/ - picoos_uint8 inBuf[PICOPAM_IN_BUFF_SIZE]; /* internal input buffer */ - picoos_uint16 inBufSize; /* actually allocated size */ - picoos_uint16 inReadPos, inWritePos; /* next pos to read/write from/to inBuf*/ - /*----------------------PU output management-----------------------------*/ - picoos_uint8 outBuf[PICOPAM_OUT_PAM_SIZE]; /* internal output buffer */ - picoos_uint16 outBufSize; /* actually allocated size */ - picoos_uint16 outReadPos, outWritePos; /* next pos to read/write from/to outBuf*/ - /*---------------------- adapter working buffers --------------------*/ - picoos_uint8 *sPhFeats; /*feature vector for a single phone */ - sFtVect *sSyllFeats; /*Syllable feature vector set for the - full sentence */ - picoos_uint8 *sPhIds; /*phone ids for the full sentence */ - picoos_uint8 *sSyllItems; /*items attached to the syllable */ - picoos_int16 *sSyllItemOffs;/*offset of items attached to the syllable*/ - /*---------------------- adapter general variables ---------------------*/ - picoos_int16 nTotalPhonemes; /*number of phonemes in the sentence*/ - picoos_int16 nCurrPhoneme; /*current phoneme in the sentence */ - picoos_int16 nSyllPhoneme; /*current phoneme in the syllable */ - picoos_int16 nCurrSyllable; /*current syllable in the sentence */ - picoos_int16 nTotalSyllables; /*number of syllables in the sentence -> J1*/ - picoos_uint8 nLastAttachedItemId;/*last attached item id*/ - picoos_uint8 nCurrAttachedItem; /*current attached item*/ - picoos_int16 nAttachedItemsSize; /*total size of the attached items*/ - picoos_uint8 sType; /*Sentence type*/ - picoos_uint8 pType; /*Phrase type*/ - picoos_single pMod; /*pitch modifier*/ - picoos_single dMod; /*Duration modifier*/ - picoos_single dRest; /*Duration modifier rest*/ - /*---------------------- adapter specific component variables ----------*/ - picoos_uint8 a3_overall_syllable; /* A3 */ - picoos_uint8 a3_primary_phrase_syllable; - picoos_uint8 b4_b5_syllable; /* B4,B5 */ - picoos_uint8 b6_b7_syllable; /* B6,B7 */ - picoos_uint8 b6_b7_state; - picoos_uint8 b8_b9_stressed_syllable; /* B8,B9 */ - picoos_uint8 b10_b11_accented_syllable; /* B10,B11 */ - picoos_uint8 b12_b13_syllable; /* B12,B13 */ - picoos_uint8 b12_b13_state; - picoos_uint8 b14_b15_syllable; /* B14,B15 */ - picoos_uint8 b14_b15_state; - picoos_uint8 b17_b19_syllable; /* B17,B19 */ - picoos_uint8 b17_b19_state; - picoos_uint8 b18_b20_b21_syllable; /* B18,B20,B21 */ - picoos_uint8 b18_b20_b21_state; - picoos_uint8 c3_overall_syllable; /* C3 */ - picoos_uint8 c3_primary_phrase_syllable; - picoos_uint8 d2_syllable_in_word; /* D2 */ - picoos_uint8 d2_prev_syllable_in_word; - picoos_uint8 d2_current_primary_phrase_word; - picoos_int8 e1_syllable_word_start; /* E1 */ - picoos_int8 e1_syllable_word_end; - picoos_uint8 e1_content; - picoos_int8 e2_syllable_word_start; /* E2 */ - picoos_int8 e2_syllable_word_end; - picoos_uint8 e3_e4_word; /* E3,E4 */ - picoos_uint8 e3_e4_state; - picoos_uint8 e5_e6_content_word; /* E5,E6 */ - picoos_uint8 e5_e6_content; - picoos_uint8 e7_e8_word; /* E7,E8 */ - picoos_uint8 e7_e8_content; - picoos_uint8 e7_e8_state; - picoos_uint8 e9_e11_word; /* E9,E11 */ - picoos_uint8 e9_e11_saw_word; - picoos_uint8 e9_e11_state; - picoos_uint8 e10_e12_e13_word; /* E10,E12,E13 */ - picoos_uint8 e10_e12_e13_state; - picoos_uint8 e10_e12_e13_saw_word; - picoos_uint8 f2_overall_word; /* F2 */ - picoos_uint8 f2_word_syllable; - picoos_uint8 f2_next_word_syllable; - picoos_uint8 f2_current_primary_phrase_word; - picoos_int8 g1_current_secondary_phrase_syllable; /*G1 */ - picoos_int8 g1_current_syllable; - picoos_int8 g2_current_secondary_phrase_word; /*G2 */ - picoos_int8 g2_current_word; - picoos_uint8 h1_current_secondary_phrase_syll; /*H1 */ - picoos_uint8 h2_current_secondary_phrase_word; /*H2 */ - picoos_uint8 h3_h4_current_secondary_phrase_word; /*H3,H4 */ - picoos_uint8 h5_current_phrase_type; /*H5 */ - - picoos_uint8 h5_syllable; /* H5 */ - picoos_uint8 h5_state; - - picoos_uint8 i1_secondary_phrase_syllable; /*I1 */ - picoos_uint8 i1_next_secondary_phrase_syllable; - picoos_uint8 i2_secondary_phrase_word; /*I2 */ - picoos_uint8 i2_next_secondary_phrase_word; - picoos_uint8 j1_utterance_syllable; /*J1 */ - picoos_uint8 j2_utterance_word; /*J2 */ - picoos_uint8 j3_utterance_sec_phrases; /*J3 */ - /*---------------------- constant data -------------------*/ - picoos_uint16 sil_weights[PICOPAM_PWIDX_SIZE][PICOPAM_MAX_STATES_PER_PHONE]; - /*---------------------- LINGWARE related data -------------------*/ - picokdt_DtPAM dtdur; /* dtdur knowledge base */ - picokdt_DtPAM dtlfz[PICOPAM_DT_NRLFZ]; /* dtlfz knowledge bases */ - picokdt_DtPAM dtmgc[PICOPAM_DT_NRMGC]; /* dtmgc knowledge bases */ - /*---------------------- Pdfs related data -------------------*/ - picokpdf_PdfDUR pdfdur; /* pdfdur knowledge base */ - picokpdf_PdfMUL pdflfz; /* pdflfz knowledge base */ - /*---------------------- Tree traversal related data -------------------*/ - picoos_uint16 durIndex; - picoos_uint8 numFramesState[PICOPAM_DT_NRLFZ]; - picoos_uint16 lf0Index[PICOPAM_DT_NRLFZ]; - picoos_uint16 mgcIndex[PICOPAM_DT_NRMGC]; - /*---------------------- temps for updating the feature vector ---------*/ - picoos_uint16 phonDur; - picoos_single phonF0[PICOPAM_DT_NRLFZ]; - /*---------------------- Phones related data -------------------*/ - picoktab_Phones tabphones; -} pam_subobj_t; - - -/* ----- CONSTANTS FOR FEATURE VECTOR BUILDING (NOT PREFIXED WITH "PICOPAM_" FOR BREVITY) ----- */ -#define P1 0 /*field 1 of the input vector*/ -#define P2 1 -#define P3 2 -#define P4 3 -#define P5 4 -#define P6 5 -#define P7 6 -#define bnd 6 /*boundary type item associated to the syllable = P7 */ -#define P8 7 -#define A3 8 -#define B1 9 -#define B2 10 -#define B3 11 -#define B4 12 -#define B5 13 -#define B6 14 -#define B7 15 -#define B8 16 -#define B9 17 -#define B10 18 -#define B11 19 -#define B12 20 -#define B13 21 -#define B14 22 -#define B15 23 -#define B16 24 -#define B17 25 -#define B18 26 -#define B19 27 -#define B20 28 -#define B21 29 -#define C3 30 -#define D2 31 -#define E1 32 -#define E2 33 -#define E3 34 -#define E4 35 -#define E5 36 -#define E6 37 -#define E7 38 -#define E8 39 -#define E9 40 -#define E10 41 -#define E11 42 -#define E12 43 -#define E13 44 -#define F2 45 -#define G1 46 -#define G2 47 -#define H1 48 -#define H2 49 -#define H3 50 -#define H4 51 -#define H5 52 -#define I1 53 -#define I2 54 -#define J1 55 -#define J2 56 -#define J3 57 -#define DUR 58 /*duration component*/ -#define F0 59 /*F0 component*/ -#define ITM 60 /*Item Offset into sSyllItems item list*/ -#define itm 61 /*second byte of the Item Offset */ -#define FID 62 /*Phoneme offset in the sPhIds phoneme list*/ -#define fid 63 /*second byte of the Phoneme offset */ -#define Min 64 /*offset to min syllable duration (uint 16,pauses)*/ -#define Max 66 /*offset to max syllable duration (uint 16,pauses)*/ -/* ------------------------------------------------------------------- - PAM feature vector indices position changes, - ------------------------------------------------------------------- */ -#define T_B1 8 -#define T_B2 9 -#define T_B3 10 -#define T_B4 11 -#define T_B5 12 -#define T_B6 13 -#define T_B7 14 -#define T_B8 15 -#define T_B9 16 -#define T_B10 17 -#define T_B11 18 -#define T_B12 19 -#define T_B13 20 -#define T_B14 21 -#define T_B15 22 -#define T_B16 23 -#define T_B17 24 -#define T_B18 25 -#define T_B19 26 -#define T_B20 27 -#define T_B21 28 -#define T_E1 29 -#define T_E2 30 -#define T_E3 31 -#define T_E4 32 -#define T_E5 33 -#define T_E6 34 -#define T_E7 35 -#define T_E8 36 -#define T_E9 37 -#define T_E10 38 -#define T_E11 39 -#define T_E12 40 -#define T_E13 41 -#define T_A3 42 -#define T_C3 43 -#define T_D2 44 -#define T_F2 45 -#define T_G1 46 -#define T_I1 47 -#define T_G2 48 -#define T_I2 49 -#define T_H1 50 -#define T_H2 51 -#define T_H3 52 -#define T_H4 53 -#define T_H5 54 - -/*------------------------------------------------------------------ - Service routines : - ------------------------------------------------------------------*/ -static pico_status_t pam_initialize(register picodata_ProcessingUnit this); -static pico_status_t pam_terminate(register picodata_ProcessingUnit this); -static pico_status_t pam_allocate(picoos_MemoryManager mm, pam_subobj_t *pam); -static void pam_deallocate(picoos_MemoryManager mm, pam_subobj_t *pam); -static pico_status_t pam_subobj_deallocate(register picodata_ProcessingUnit this, - picoos_MemoryManager mm); -/*------------------------------------------------------------------ - Processing routines : - ------------------------------------------------------------------*/ -static picodata_step_result_t pam_step(register picodata_ProcessingUnit this, - picoos_int16 mode, picoos_uint16 * numBytesOutput); -static pico_status_t pam_deal_with(const picoos_uint8 *item); -/*Utility*/ -static picoos_uint8 pam_get_vowel_name(register picodata_ProcessingUnit this, - picoos_uint8 *item, picoos_uint8 *pos); -static picoos_uint8 pam_get_pause_id(register picodata_ProcessingUnit this); - -static picoos_uint8 pam_map_sentence_type(picoos_uint8 iteminfo1, - picoos_uint8 iteminfo2); -static picoos_uint8 pam_map_phrase_type(picoos_uint8 iteminfo1, - picoos_uint8 iteminfo2); - -/*Adapter*/ -static pico_status_t pam_reset_processors(register picodata_ProcessingUnit this); -static pico_status_t pam_reset_processors_back( - register picodata_ProcessingUnit this); -static pico_status_t pam_create_syllable(register picodata_ProcessingUnit this, - picoos_uint8 syllType, picoos_uint8 *sContent, picoos_uint8 sentType, - picoos_uint8 phType, picoos_uint8 uBoundType, picoos_uint16 uMin, - picoos_uint16 uMax); -static pico_status_t pam_process_event_feature( - register picodata_ProcessingUnit this, picoos_uint8 nFeat, - picoos_uint8 event_type, picoos_uint8 direction); -static pico_status_t pam_process_event(register picodata_ProcessingUnit this, - picoos_uint8 event_type, picoos_uint8 direction); -static pico_status_t pam_adapter_forward_step( - register picodata_ProcessingUnit this, picoos_uint8 *itemBase); -static pico_status_t pam_adapter_backward_step( - register picodata_ProcessingUnit this); -static pico_status_t pam_do_pause(register picodata_ProcessingUnit this); -static pico_status_t pam_adapter_do_pauses(register picodata_ProcessingUnit this); -/*-------------- tree traversal ---------------------------------------*/ -static pico_status_t pam_expand_vector(register picodata_ProcessingUnit this); -static picoos_uint8 pam_do_tree(register picodata_ProcessingUnit this, - const picokdt_DtPAM dtpam, const picoos_uint8 *invec, - const picoos_uint8 inveclen, picokdt_classify_result_t *dtres); -static pico_status_t pam_get_f0(register picodata_ProcessingUnit this, - picoos_uint16 *lf0Index, picoos_uint8 nState, picoos_single *phonF0); -static pico_status_t pam_get_duration(register picodata_ProcessingUnit this, - picoos_uint16 durIndex, picoos_uint16 *phonDur, - picoos_uint8 *numFramesState); -static pico_status_t pam_update_vector(register picodata_ProcessingUnit this); -/*-------------- FINAL ITEM FEEDING -----------------------------------------*/ -static pico_status_t pam_put_item(register picodata_ProcessingUnit this, - picoos_uint8 *outBuff, picoos_uint16 outWritePos, - picoos_uint8 *bytesWr); - -static pico_status_t pam_put_term(picoos_uint8 *outBuff, - picoos_uint16 outWritePos, picoos_uint8 *bytesWr); - -static pico_status_t is_pam_command(const picoos_uint8 *qItem); - -static void get_default_boundary_limit(picoos_uint8 uBoundType, - picoos_uint16 *uMinDur, picoos_uint16 *uMaxDur); - -/* ------------------------------------------------------------- - * Pico System functions - * ------------------------------------------------------------- - */ - -/** - * allocation for PAM memory on pam PU - * @param mm : handle to engine memory manager - * @param pam : handle to a pam struct - * @return PICO_OK : allocation successful - * @return PICO_ERR_OTHER : allocation errors - * @callgraph - * @callergraph - */ -static pico_status_t pam_allocate(picoos_MemoryManager mm, pam_subobj_t *pam) -{ - picoos_uint8 *data; - picoos_int16 *dataI; - - pam->sSyllFeats = NULL; - pam->sPhIds = NULL; - pam->sPhFeats = NULL; - pam->sSyllItems = NULL; - pam->sSyllItemOffs = NULL; - - /*----------------------------------------------------------------- - * PAM Local buffers ALLOCATION - ------------------------------------------------------------------*/ - /*PAM Local buffers*/ - data = (picopal_uint8 *) picoos_allocate(mm, sizeof(sFtVect) - * PICOPAM_MAX_SYLL_PER_SENT); - if (data == NULL) - return PICO_ERR_OTHER; - pam->sSyllFeats = (sFtVect*) data; - - data = (picopal_uint8 *) picoos_allocate(mm, sizeof(picopal_uint8) - * PICOPAM_MAX_PH_PER_SENT); - if (data == NULL) { - pam_deallocate(mm, pam); - return PICO_ERR_OTHER; - } - pam->sPhIds = (picopal_uint8*) data; - - data = (picopal_uint8 *) picoos_allocate(mm, sizeof(picopal_uint8) - * PICOPAM_VECT_SIZE); - if (data == NULL) { - pam_deallocate(mm, pam); - return PICO_ERR_OTHER; - } - pam->sPhFeats = (picopal_uint8*) data; - - data = (picopal_uint8 *) picoos_allocate(mm, sizeof(picopal_uint8) - * PICOPAM_MAX_ITEM_SIZE_PER_SENT); - if (data == NULL) { - pam_deallocate(mm, pam); - return PICO_ERR_OTHER; - } - pam->sSyllItems = (picopal_uint8*) data; - - dataI = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) - * PICOPAM_MAX_ITEM_PER_SENT); - if (data == NULL) { - pam_deallocate(mm, pam); - return PICO_ERR_OTHER; - } - pam->sSyllItemOffs = (picoos_int16*) dataI; - - return PICO_OK; -}/*pam_allocate*/ - -/** - * frees allocation for DSP memory on PAM PU - * @param mm : memory manager - * @param pam : pam PU internal sub-object - * @return void - * @remarks modified and inserted in sub obj removal PP 15.09.08 - * @callgraph - * @callergraph - */ -static void pam_deallocate(picoos_MemoryManager mm, pam_subobj_t *pam) -{ - /*----------------------------------------------------------------- - * Memory de-allocations - * ------------------------------------------------------------------*/ - if (pam->sSyllFeats != NULL) - picoos_deallocate(mm, (void *) &pam->sSyllFeats); - if (pam->sPhIds != NULL) - picoos_deallocate(mm, (void *) &pam->sPhIds); - if (pam->sPhFeats != NULL) - picoos_deallocate(mm, (void *) &pam->sPhFeats); - if (pam->sSyllItems != NULL) - picoos_deallocate(mm, (void *) &pam->sSyllItems); - if (pam->sSyllItemOffs != NULL) - picoos_deallocate(mm, (void *) &pam->sSyllItemOffs); - -}/*pam_deallocate*/ - -/** - * initialization of a pam PU - * @param this : handle to a PU struct - * @return PICO_OK : init OK - * @return PICO_ERR_OTHER : error on getting pkbs addresses - * @callgraph - * @callergraph - */ -static pico_status_t pam_initialize(register picodata_ProcessingUnit this) -{ - pico_status_t nI, nJ; - pam_subobj_t *pam; - - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - pam = (pam_subobj_t *) this->subObj; - pam->inBufSize = PICOPAM_IN_BUFF_SIZE; - pam->outBufSize = PICOPAM_OUT_PAM_SIZE; - pam->inReadPos = 0; - pam->inWritePos = 0; - pam->outReadPos = 0; - pam->outWritePos = 0; - pam->needMoreInput = 0; - pam->procState = 0; - - /*----------------------------------------------------------------- - * MANAGE INTERNAL INITIALIZATION - ------------------------------------------------------------------*/ - /*init the syllable structure*/ - for (nI = 0; nI < PICOPAM_MAX_SYLL_PER_SENT; nI++) - for (nJ = 0; nJ < PICOPAM_VECT_SIZE; nJ++) - pam->sSyllFeats[nI].phoneV[nJ] = 0; - - for (nI = 0; nI < PICOPAM_MAX_PH_PER_SENT; nI++) - pam->sPhIds[nI] = 0; - - for (nI = 0; nI < PICOPAM_VECT_SIZE; nI++) - pam->sPhFeats[nI] = 0; - - for (nI = 0; nI < PICOPAM_MAX_ITEM_SIZE_PER_SENT; nI++) - pam->sSyllItems[nI] = 0; - - for (nI = 0; nI < PICOPAM_MAX_ITEM_PER_SENT; nI++) - pam->sSyllItemOffs[nI] = 0; - - /*Other variables*/ - pam_reset_processors(this); - pam->nLastAttachedItemId = pam->nCurrAttachedItem = 0; - pam->nAttachedItemsSize = 0; - - /*pitch and duration modifiers*/ - pam->pMod = 1.0f; - pam->dMod = 1.0f; - pam->dRest = 0.0f; - - - /* constant tables */ - { - picoos_uint8 i, j; - picoos_uint16 tmp_weights[PICOPAM_PWIDX_SIZE][PICOPAM_MAX_STATES_PER_PHONE] = { - {10, 10, 10, 10, 1 }, /*SBEG*/ - { 1, 4, 8, 4, 1 }, /*PHR1*/ - { 1, 4, 8, 4, 1 }, /*PHR2*/ - { 1, 10, 10, 10, 10 },/*SEND*/ - { 1, 1, 1, 1, 1 } /*DEFAULT*/ - }; - for (i = 0; i < PICOPAM_PWIDX_SIZE; i++) { - for (j = 0; j < PICOPAM_PWIDX_SIZE; j++) { - pam->sil_weights[j][j] = tmp_weights[i][j]; - } - } - } -/*----------------------------------------------------------------- - * MANAGE LINGWARE INITIALIZATION IF NEEDED - ------------------------------------------------------------------*/ - /* kb dtdur */ - pam->dtdur = picokdt_getDtPAM(this->voice->kbArray[PICOKNOW_KBID_DT_DUR]); - if (pam->dtdur == NULL) { - picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL, - NULL); - return PICO_ERR_OTHER; - }PICODBG_DEBUG(("got dtdur")); - - /* kb dtlfz* */ - pam->dtlfz[0] = picokdt_getDtPAM( - this->voice->kbArray[PICOKNOW_KBID_DT_LFZ1]); - pam->dtlfz[1] = picokdt_getDtPAM( - this->voice->kbArray[PICOKNOW_KBID_DT_LFZ2]); - pam->dtlfz[2] = picokdt_getDtPAM( - this->voice->kbArray[PICOKNOW_KBID_DT_LFZ3]); - pam->dtlfz[3] = picokdt_getDtPAM( - this->voice->kbArray[PICOKNOW_KBID_DT_LFZ4]); - pam->dtlfz[4] = picokdt_getDtPAM( - this->voice->kbArray[PICOKNOW_KBID_DT_LFZ5]); - for (nI = 0; nI < PICOPAM_DT_NRLFZ; nI++) { - if (pam->dtlfz[nI] == NULL) { - picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - return PICO_ERR_OTHER; - }PICODBG_DEBUG(("got dtlfz%d", nI+1)); - } - - /* kb dtmgc* */ - pam->dtmgc[0] = picokdt_getDtPAM( - this->voice->kbArray[PICOKNOW_KBID_DT_MGC1]); - pam->dtmgc[1] = picokdt_getDtPAM( - this->voice->kbArray[PICOKNOW_KBID_DT_MGC2]); - pam->dtmgc[2] = picokdt_getDtPAM( - this->voice->kbArray[PICOKNOW_KBID_DT_MGC3]); - pam->dtmgc[3] = picokdt_getDtPAM( - this->voice->kbArray[PICOKNOW_KBID_DT_MGC4]); - pam->dtmgc[4] = picokdt_getDtPAM( - this->voice->kbArray[PICOKNOW_KBID_DT_MGC5]); - for (nI = 0; nI < PICOPAM_DT_NRMGC; nI++) { - if (pam->dtmgc[nI] == NULL) { - picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - return PICO_ERR_OTHER; - }PICODBG_DEBUG(("got dtmgc%d", nI+1)); - } - - /* kb pdfdur* */ - pam->pdfdur = picokpdf_getPdfDUR( - this->voice->kbArray[PICOKNOW_KBID_PDF_DUR]); - if (pam->pdfdur == NULL) { - picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL, - NULL); - return PICO_ERR_OTHER; - }PICODBG_DEBUG(("got pdfdur")); - - /* kb pdflfz* */ - pam->pdflfz = picokpdf_getPdfMUL( - this->voice->kbArray[PICOKNOW_KBID_PDF_LFZ]); - if (pam->pdflfz == NULL) { - picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL, - NULL); - return PICO_ERR_OTHER; - }PICODBG_DEBUG(("got pdflfz")); - - /* kb tabphones */ - pam->tabphones = picoktab_getPhones( - this->voice->kbArray[PICOKNOW_KBID_TAB_PHONES]); - if (pam->tabphones == NULL) { - picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL, - NULL); - return PICO_ERR_OTHER; - }PICODBG_DEBUG(("got tabphones")); - - return PICO_OK; -}/*pam_initialize*/ - -/** - * termination of a pam PU - * @param this : handle to a pam PU struct - * @return PICO_OK - * @callgraph - * @callergraph - */ -static pico_status_t pam_terminate(register picodata_ProcessingUnit this) -{ - - pam_subobj_t *pam; - - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - pam = (pam_subobj_t *) this->subObj; - - return PICO_OK; -}/*pam_terminate*/ - -/** - * deallocaton of a pam PU - * @param this : handle to a pam PU struct - * @param mm : engine memory manager - * @return PICO_OK - * @callgraph - * @callergraph - */ -static pico_status_t pam_subobj_deallocate(register picodata_ProcessingUnit this, - picoos_MemoryManager mm) -{ - - pam_subobj_t* pam; - - if (NULL != this) { - pam = (pam_subobj_t *) this->subObj; - mm = mm; /* avoid warning "var not used in this function"*/ - /*----------------------------------------------------------------- - * Memory de-allocations - * ------------------------------------------------------------------*/ - if (pam->sSyllFeats != NULL) { - picoos_deallocate(this->common->mm, (void *) &pam->sSyllFeats); - } - if (pam->sPhIds != NULL) { - picoos_deallocate(this->common->mm, (void *) &pam->sPhIds); - } - if (pam->sPhFeats != NULL) { - picoos_deallocate(this->common->mm, (void *) &pam->sPhFeats); - } - if (pam->sSyllItems != NULL) { - picoos_deallocate(this->common->mm, (void *) &pam->sSyllItems); - } - if (pam->sSyllItemOffs != NULL) { - picoos_deallocate(this->common->mm, (void *) &pam->sSyllItemOffs); - } - picoos_deallocate(this->common->mm, (void *) &this->subObj); - } - - return PICO_OK; -}/*pam_subobj_deallocate*/ - -/** - * creates a new pam processing unit - * @param mm : engine memory manager - * @param common : engine common object pointer - * @param cbIn : pointer to input buffer - * @param cbOut : pointer to output buffer - * @param voice : pointer to voice structure - * @return this : pam PU handle if success - * @return NULL : if error - * @callgraph - * @callergraph - */ -picodata_ProcessingUnit picopam_newPamUnit(picoos_MemoryManager mm, - picoos_Common common, picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, picorsrc_Voice voice) -{ - - register pam_subobj_t * pam; - - picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, - cbOut, voice); - if (this == NULL) { - return NULL; - } - this->initialize = pam_initialize; - - PICODBG_DEBUG(("picotok_newPamUnit -- set this->step to pam_step")); - - this->step = pam_step; - this->terminate = pam_terminate; - this->subDeallocate = pam_subobj_deallocate; - this->subObj = picoos_allocate(mm, sizeof(pam_subobj_t)); - if (this->subObj == NULL) { - PICODBG_ERROR(("Error in Pam Object allocation")); - picoos_deallocate(mm, (void*) &this); - return NULL; - }; - - /*----------------------------------------------------------------- - * Allocate internal memory for PAM (only at PU creation time) - * ------------------------------------------------------------------*/ - pam = (pam_subobj_t *) this->subObj; - if (PICO_OK != pam_allocate(mm, pam)) { - PICODBG_ERROR(("Error in Pam buffers Allocation")); - picoos_deallocate(mm, (void *) &this->subObj); - picoos_deallocate(mm, (void *) &this); - return NULL; - } - - /*----------------------------------------------------------------- - * Initialize memory for PAM (this may be re-used elsewhere, e.g.Reset) - * ------------------------------------------------------------------*/ - if (PICO_OK != pam_initialize(this)) { - PICODBG_ERROR(("problem initializing the pam sub-object")); - } - return this; -}/*picopam_newPamUnit*/ - -/*------------------------------------------------------------------------------- - PROCESSING AND INTERNAL FUNCTIONS - --------------------------------------------------------------------------------*/ - -/** - * initializes default duration limits for boundary items - * @param uBoundType : type of input boundary type - * @param *uMinDur, *uMaxDur : addresses of values to initialize - * @return void - * @remarks so far initializes to 0 both values; this will leave the values given by tree prediction - * @callgraph - * @callergraph - */ -static void get_default_boundary_limit(picoos_uint8 uBoundType, - picoos_uint16 *uMinDur, picoos_uint16 *uMaxDur) -{ - switch (uBoundType) { - case PICODATA_ITEMINFO1_BOUND_SBEG: - *uMinDur = 0; - *uMaxDur = 20; - break; - case PICODATA_ITEMINFO1_BOUND_SEND: - *uMinDur = 550; - *uMaxDur = 650; - break; - case PICODATA_ITEMINFO1_BOUND_TERM: - *uMinDur = 0; - *uMaxDur = 0; - break; - case PICODATA_ITEMINFO1_BOUND_PHR0: - *uMinDur = 0; - *uMaxDur = 0; - break; - case PICODATA_ITEMINFO1_BOUND_PHR1: - *uMinDur = 275; - *uMaxDur = 325; - break; - case PICODATA_ITEMINFO1_BOUND_PHR2: - *uMinDur = 4; - *uMaxDur = 60; - break; - case PICODATA_ITEMINFO1_BOUND_PHR3: - *uMinDur = 0; - *uMaxDur = 0; - break; - default: - break; - } - -}/*get_default_boundary_limit*/ - -/** - * checks if "neededSize" is available on "nCurrPhoneme" - * @param pam : pam subobj - * @param neededSize : the requested size - * @return PICO_OK : size is available - * @return !=PICO_OK : size not available - * @callgraph - * @callergraph - */ -static pico_status_t check_phones_size(pam_subobj_t *pam, - picoos_int16 neededSize) -{ - if ((pam->nCurrPhoneme + neededSize) > PICOPAM_MAX_PH_PER_SENT - 1) { - return PICO_ERR_OTHER; - } - return PICO_OK; -}/*check_phones_size*/ - -/** - * checks if neededSize is available on "nCurrSyllable" - * @param pam : pam subobj - * @param neededSize : the requested size - * @return PICO_OK : size is available - * @return !=PICO_OK : size not available - * @callgraph - * @callergraph - */ -static pico_status_t check_syllables_size(pam_subobj_t *pam, - picoos_int16 neededSize) -{ - if ((pam->nCurrSyllable + neededSize) > PICOPAM_MAX_SYLL_PER_SENT - 1) { - return PICO_ERR_OTHER; - } - return PICO_OK; -}/*check_syllables_size*/ - -/** - * verifies that local storage has enough space to receive 1 item - * @param this : pointer to current PU struct - * @param item : pointer to current item head - * @return TRUE : resource limits would be reached during processing of input item - * @return FALSE : item could be processed normally - * @remarks item pointed to by *item should be already valid - * @callgraph - * @callergraph - */ -static pico_status_t pamCheckResourceLimits( - register picodata_ProcessingUnit this, const picoos_uint8 *item) -{ - register pam_subobj_t * pam; - picodata_itemhead_t head; - pico_status_t sResult; - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - pam = (pam_subobj_t *) this->subObj; - sResult = TRUE; /*default : resource limits reached*/ - head.type = item[0]; - head.info1 = item[1]; - head.info2 = item[2]; - head.len = item[3]; - - switch (head.type) { - /*commands that generate syllables/phonemes*/ - case PICODATA_ITEM_SYLLPHON: - if (pam->nCurrSyllable >= PICOPAM_MAX_SYLL_PER_SENT - 2) { - return sResult; /*no room for more syllables*/ - } - if ((pam->nCurrPhoneme + head.len) >= PICOPAM_MAX_PH_PER_SENT - 2) { - return sResult; /*no room for more phoneme*/ - } - break; - case PICODATA_ITEM_BOUND: - if ((head.info1 == PICODATA_ITEMINFO1_BOUND_SBEG) || (head.info1 - == PICODATA_ITEMINFO1_BOUND_SEND) || (head.info1 - == PICODATA_ITEMINFO1_BOUND_TERM) || (head.info1 - == PICODATA_ITEMINFO1_BOUND_PHR1) -#ifdef PAM_PHR2_WITH_PR1 - || (head.info1 == PICODATA_ITEMINFO1_BOUND_PHR2) -#endif - ) { - - if (pam->nCurrSyllable >= PICOPAM_MAX_SYLL_PER_SENT - 2) { - return sResult; /*no room for more syllables*/ - } - if ((pam->nCurrPhoneme + 1) >= PICOPAM_MAX_PH_PER_SENT - 2) { - return sResult; /*no room for more phoneme*/ - } - } - break; - - default: - /*all other commands has to be queued*/ - if ((pam->nAttachedItemsSize + head.len) - >= PICOPAM_MAX_ITEM_SIZE_PER_SENT - 1) { - return sResult; /*no room for more items*/ - } - break; - } - return FALSE; /*no resource limits apply to current item*/ -} /*pamCheckResourceLimits*/ - -/** - * selects items to be sent to next PU immedately - * @param this : pointer to current PU struct - * @param item : pointer to current item head - * @return TRUE : item should be passed on next PU NOW - * @return FALSE : item should not be passed on next PU now but should be processed - * @remarks item pointed to by *item should be already valid - * @callgraph - * @callergraph - */ -static pico_status_t pam_check_immediate(register picodata_ProcessingUnit this, - const picoos_uint8 *item) -{ - register pam_subobj_t * pam; - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - pam = (pam_subobj_t *) this->subObj; - - if (pam->nCurrSyllable <= -1) { - if (item[0] == PICODATA_ITEM_SYLLPHON) - return FALSE; - if ((item[0] == PICODATA_ITEM_BOUND) && (item[1] - == PICODATA_ITEMINFO1_BOUND_SBEG)) - return FALSE; - if (is_pam_command((picoos_uint8 *) item) == TRUE) - return FALSE; - return TRUE; /*no need to process data : send it*/ - } - return FALSE; /*syllable struct not void : do standard processing*/ - -} /*pam_check_immediate*/ - -/** - * checks if the input item has to be queued in local storage for later resynch - * @param this : pointer to current PU struct - * @param item : pointer to current item head - * @return TRUE : item should be queued - * @return FALSE : item should not be queued - * @remarks item pointed to by *item should be already valid - * @callgraph - * @callergraph - */ -static pico_status_t pam_hastobe_queued(register picodata_ProcessingUnit this, - const picoos_uint8 *item) -{ - register pam_subobj_t * pam; - picodata_itemhead_t head; - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - pam = (pam_subobj_t *) this->subObj; - head.type = item[0]; - head.info1 = item[1]; - - switch (head.type) { - /*commands that generate syllables/phonemes*/ - case PICODATA_ITEM_SYLLPHON: - return FALSE; /*no queue needed*/ - break; - case PICODATA_ITEM_BOUND: - if ((head.info1 == PICODATA_ITEMINFO1_BOUND_PHR3) -#ifdef PAM_PHR2_WITH_PR3 - ||(head.info1==PICODATA_ITEMINFO1_BOUND_PHR2) -#endif - || (head.info1 == PICODATA_ITEMINFO1_BOUND_PHR0)) { - return FALSE; /*no queue needed*/ - } - break; - - default: - /*all other items has to be queued*/ - break; - } - return TRUE; /*item has to be queued*/ -} /*pam_hastobe_queued*/ - -/** - * queue item in local storage for later resynch - * @param this : pointer to current PU struct - * @param item : pointer to current item head - * @return TRUE : item queued - * @return FALSE : item not queued because of errors - * @remarks item pointed to by *item should be already valid - * @callgraph - * @callergraph - */ -static pico_status_t pam_queue(register picodata_ProcessingUnit this, - const picoos_uint8 *item) -{ - register pam_subobj_t * pam; - picodata_itemhead_t head; - picoos_uint8 nI; - pico_status_t sResult; - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - pam = (pam_subobj_t *) this->subObj; - sResult = TRUE; /*default : item queued*/ - head.type = item[0]; - head.info1 = item[1]; - head.info2 = item[2]; - head.len = item[3]; - - /*test condition on enough room to store current item in the "sSyllItems" area*/ - if ((pam->nAttachedItemsSize + head.len + sizeof(picodata_itemhead_t)) - >= PICOPAM_MAX_ITEM_SIZE_PER_SENT - 1) { - return FALSE; /*resource limit reached*/ - } - /*store current offset*/ - pam->sSyllItemOffs[pam->nLastAttachedItemId] = pam->nAttachedItemsSize; - /*store the item to the "sSyllItems" area*/ - for (nI = 0; nI < (head.len + sizeof(picodata_itemhead_t)); nI++) { - pam->sSyllItems[pam->nAttachedItemsSize + nI] = item[nI]; - } - /*increment the attached items area*/ - pam->nAttachedItemsSize += nI; - - /*increment id*/ - pam->nLastAttachedItemId++; - /*set start(if not initialized) and end ids of queued items in sSyllFeats*/ - if (pam->nCurrSyllable > -1) { - /*normal case : the item is attached to current syllable*/ - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] == 0) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] - = pam->nLastAttachedItemId; - } - pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] - = pam->nLastAttachedItemId; - } else { - /*special case : an item is requested to be queued even if no - syllables has been assigned to the sentence structure : - -->> use syll 0*/ - if (pam->sSyllFeats[0].phoneV[ITM] == 0) { - pam->sSyllFeats[0].phoneV[ITM] = pam->nLastAttachedItemId; - } - pam->sSyllFeats[0].phoneV[itm] = pam->nLastAttachedItemId; - } - return TRUE; /*item queued successfully*/ -} /*pam_queue*/ - -/** - * selects items to be dealth with by the PU processing - * @param item : pointer to current item head - * @return TRUE : item should be processed - * @return FALSE : item should not be processed (maybe it ontains commands or items for other PUs) - * @remarks item pointed to by *item should be already valid - * @callgraph - * @callergraph - */ -static pico_status_t pam_deal_with(const picoos_uint8 *item) -{ - picodata_itemhead_t head; - pico_status_t sResult; - sResult = FALSE; - head.type = item[0]; - head.info1 = item[1]; - head.info2 = item[2]; - head.len = item[3]; - switch (head.type) { - case PICODATA_ITEM_SYLLPHON: - case PICODATA_ITEM_BOUND: - sResult = TRUE; - break; - default: - break; - } - return sResult; -} /*pam_deal_with*/ - -/** - * returns true if more items has to be produced for current syllable - * @param this : Pam object pointer - * @return TRUE : item is to be produced - * @return FALSE : item is not to be produced - * @remarks item pointed to by *item should be already valid - * @callgraph - * @callergraph - */ -static picoos_uint8 pamHasToProcess(register picodata_ProcessingUnit this) -{ - register pam_subobj_t * pam; - picoos_uint8 nCond1, nCond2, nCond3; - - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - pam = (pam_subobj_t *) this->subObj; - /*conditions originating a "NOT to be processed" result */ - nCond1 = pam->nCurrSyllable <= -1; - nCond2 = pam->nCurrSyllable >= pam->nTotalSyllables; - nCond3 = pam->nSyllPhoneme - >= pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3]; - - if ((nCond1) || (nCond2) || (nCond3)) - return FALSE; - - return TRUE; -} /*pamHasToProcess*/ - -/** - * modifies the process flags in order to point to next valid syllable phone or item to be produced - * @param this : Pam object pointer - * @return TRUE : item has to be produced - * @return FALSE : item has not to be produced - * @callgraph - * @callergraph - */ -static pico_status_t pamUpdateProcess(register picodata_ProcessingUnit this) -{ - register pam_subobj_t * pam; - - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - pam = (pam_subobj_t *) this->subObj; - - if (pam->nCurrSyllable == -1) { - /*this to be able to manage sudden PU cleanup after FLUSH CMD*/ - return PICO_OK; - } - /*check number of phonemes for current syllable*/ - if (pam->nSyllPhoneme < pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] - 1) { - pam->nSyllPhoneme++; - return PICO_OK; - } - if (pam->nSyllPhoneme == pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] - 1) { - /*this helps in identifyng the end of syllable condition in PamHasToProcess*/ - pam->nSyllPhoneme++; - } - /*previous syllable phonemes are complete: test if any items are tied to this syllable*/ - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] > 0) { - /*there are items tied to this syllable*/ - if (pam->nCurrAttachedItem == 0) { - /*if it is the first item to be regenerated initialize it*/ - pam->nCurrAttachedItem - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM]; - return PICO_OK; - } else { - /*not the first item : check if more*/ - if (pam->nCurrAttachedItem - < pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]) { - /*more tied items to be regenerated*/ - pam->nCurrAttachedItem++; - return PICO_OK; - } - } - } - /*previous syllable phonemes and items are complete: switch to next syllable*/ - if (pam->nCurrSyllable < pam->nTotalSyllables - 1) { - pam->nCurrSyllable++; - pam->nSyllPhoneme = 0; - pam->nCurrAttachedItem = 0; - return PICO_OK; - } - /*no more phonemes or items to be produced*/ - pam->nCurrSyllable++; - pam->nSyllPhoneme = 0; - return PICO_ERR_OTHER; - -} /*pamUpdateProcess*/ - -/** - * returns true if more items has to be popped for current syllable - * @param this : Pam object pointer - * @return TRUE : item has to be popped - * @return FALSE : item has not to be popped - * @callgraph - * @callergraph - */ -static picoos_uint8 pamHasToPop(register picodata_ProcessingUnit this) -{ - register pam_subobj_t * pam; - - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - pam = (pam_subobj_t *) this->subObj; - - /*Preliminary condition : at least 1 syllable*/ - if (pam->nCurrSyllable <= -1) - return FALSE; - - /*Preliminary condition : not maximum number of syllables*/ - if (pam->nCurrSyllable >= pam->nTotalSyllables) - return FALSE; - - /*Preliminary condition : start and end offset in current item > 0 */ - if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] <= 0) - || (pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] <= 0)) - return FALSE; - - /*Final condition : current popped item less or eq to maximum*/ - if (pam->nCurrAttachedItem - > pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]) - return FALSE; - - return TRUE; -} /*pamHasToPop*/ - -/** - * returns the address of an item to be popped from the current syllable queue - * @param this : Pam object pointer - * @return pop_address : item address - * @return NULL : item not poppable - * @callgraph - * @callergraph - */ -static picoos_uint8 *pamPopItem(register picodata_ProcessingUnit this) -{ - register pam_subobj_t * pam; - picoos_uint8 nItem; - if (NULL == this || NULL == this->subObj) { - return NULL; - } - pam = (pam_subobj_t *) this->subObj; - - /*Preliminary condition : at least 1 syllable*/ - if (pam->nCurrSyllable <= -1) - return NULL; - - /*Preliminary condition : not maximum number of syllables*/ - if (pam->nCurrSyllable >= pam->nTotalSyllables) - return NULL; - - /*Preliminary condition : start and end offset in current item > 0 */ - if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] <= 0) - || (pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] <= 0)) - return NULL; - - /*Final condition : current popped item less than maximum*/ - if (pam->nCurrAttachedItem - > pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]) - return NULL; - - nItem = pam->nCurrAttachedItem; - /*please note : nItem-1 should match with actions performed in function "pam_queue(..)" */ - return &(pam->sSyllItems[pam->sSyllItemOffs[nItem - 1]]); - -} /*pamPopItem*/ - -/** - * returns the address of an item popped from the syllable 0 queue - * @param this : Pam object pointer - * @return pop_address : item address - * @return NULL : item not poppable - * @remarks the item is popped only if it has been inserted in the queue before the first - * @remarks item assigned to the syllable 0 i.e. - * @remarks AttachedItem<=pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]-1 - * @callgraph - * @callergraph - */ -static picoos_uint8 *pamPopAttachedSy0(register picodata_ProcessingUnit this) -{ - register pam_subobj_t * pam; - picoos_uint8 nItem; - if (NULL == this || NULL == this->subObj) { - return NULL; - } - pam = (pam_subobj_t *) this->subObj; - - /*should be syllable 0*/ - if (pam->nCurrSyllable != 0) - return NULL; - - /*start and end offset in current item > 0 */ - if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] <= 0) - || (pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] <= 0)) - return NULL; - - /*if current popped item is > 0 test end condition*/ - if (pam->nCurrAttachedItem > 0) { - /*Other condition : current popped item less than maximum*/ - if (pam->nCurrAttachedItem - > pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] - 1) - return NULL; - } - nItem = pam->nCurrAttachedItem; - return &(pam->sSyllItems[pam->sSyllItemOffs[nItem]]); - -} /*pamPopAttachedSy0*/ - -/** - * pdf access for duration - * @param this : Pam object pointer - * @param durIndex : index of duration in the pdf - * @param phonDur : pointer to base of array where to store the duration values - * @param numFramesState : pointer to base of array where to store the number of frames per state - * @return PICO_OK : pdf retrieved - * @return PICO_ERR_OTHER : pdf not retrieved - * @remarks Modifies phonDur (the requested duration value) - * @remarks Modifies numFramesState (the requested number of frames per state (vector)) - * @callgraph - * @callergraph - */ -static pico_status_t pam_get_duration(register picodata_ProcessingUnit this, - picoos_uint16 durIndex, picoos_uint16 *phonDur, - picoos_uint8 *numFramesState) -{ - pam_subobj_t *pam; - picokpdf_PdfDUR pdf; - picoos_uint8 *durItem; - picoos_uint16 nFrameSize, nI; - picoos_single fValue; - pam = (pam_subobj_t *) this->subObj; - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - pdf = pam->pdfdur; - /*make the index 0 based*/ - if (durIndex > 0) - durIndex--; - - /* check */ - if (durIndex > pdf->numframes - 1) { - PICODBG_ERROR(("PAM durPdf access error, index overflow -> index: %d , numframes: %d", durIndex, pdf->numframes)); - return PICO_ERR_OTHER; - } - /* base pointer */ - durItem = &(pdf->content[durIndex * pdf->vecsize]); - if (durItem == NULL) { - PICODBG_ERROR(("PAM durPdf access error , frame pointer = NULL")); - return PICO_ERR_OTHER; - } - nFrameSize = pdf->sampperframe / 16; - *phonDur = ((pdf->phonquant[((*durItem) & 0xF0) >> 4]) * nFrameSize); - numFramesState[0] = pdf->statequant[((*durItem) & 0x0F)]; - durItem++; - numFramesState[1] = pdf->statequant[((*durItem) & 0xF0) >> 4]; - numFramesState[2] = pdf->statequant[((*durItem) & 0x0F)]; - durItem++; - numFramesState[3] = pdf->statequant[((*durItem) & 0xF0) >> 4]; - numFramesState[4] = pdf->statequant[((*durItem) & 0x0F)]; - - /*modification of the duration information based on the duration modifier*/ - *phonDur = (picoos_uint16) (((picoos_single) * phonDur) * pam->dMod); - for (nI = 0; nI < 5; nI++) { - fValue = pam->dRest + (picoos_single) numFramesState[nI] * pam->dMod; - numFramesState[nI] = (picoos_uint8) (fValue); - pam->dRest = fValue - (picoos_single) numFramesState[nI]; - } - return PICO_OK; -}/*pam_get_duration*/ - -/** - * pdf access for pitch - * @param this : Pam object pointer - * @param lf0Index : pointer to variable to receive index of pitch in the pdf - * @param nI : number of the phone's state - * @param phonF0 : pointer to variable to receive the pitch value - * @return PICO_OK : pdf retrieved - * @return PICO_ERR_OTHER : pdf not retrieved - * @remarks Modifies phonDur (the requested duration value) - * @remarks Modifies phonF0 (the requested pitch value (scalar)) - * @callgraph - * @callergraph - */ -static pico_status_t pam_get_f0(register picodata_ProcessingUnit this, - picoos_uint16 *lf0Index, picoos_uint8 nI, picoos_single *phonF0) -{ - pam_subobj_t *pam; - picoos_uint8 *lfItem, numstreams; - picoos_uint16 lf0IndexOffset, sTemp; - picoos_single lfum, lfivar, lfz; - - pam = (pam_subobj_t *) this->subObj; - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - lf0IndexOffset = lf0Index[nI]; - - /*make the index 0 based*/ - if (lf0IndexOffset > 0) - lf0IndexOffset--; - - lf0IndexOffset += pam->pdflfz->stateoffset[nI]; - if (lf0IndexOffset > pam->pdflfz->numframes - 1) { - PICODBG_ERROR(("PAM flfzPdf access error, index overflow -> index: %d , numframes: %d", lf0Index, pam->pdflfz->numframes)); - return PICO_ERR_OTHER; - } - /* base pointer */ - lf0IndexOffset *= pam->pdflfz->vecsize; - - lfItem = &(pam->pdflfz->content[lf0IndexOffset]); - sTemp = (picoos_uint16) (((lfItem[1] << 8)) | lfItem[0]); - - lfum = (picoos_single) (sTemp << (pam->pdflfz->meanpowUm[0])); - numstreams = 3; - lfivar = (picoos_single) (((picoos_uint16) lfItem[numstreams * 2]) - << pam->pdflfz->ivarpow[0]); - lfz = (picoos_single) lfum / (picoos_single) lfivar; - lfz = (picoos_single) exp((double) lfz); - phonF0[nI] = (picoos_single) lfz; - - /*pitch modoification*/ - phonF0[nI] *= pam->pMod; - return PICO_OK; -}/*pam_get_f0*/ - -/** - * elementary rounding function - * @param fIn : (real) input value - * @return the rounded value - * @callgraph - * @callergraph - */ -static picoos_single f_round(picoos_single fIn) -{ - picoos_int32 iVal; - picoos_single fVal; - - iVal = (picoos_int32) fIn; - fVal = (picoos_single) iVal; - - if (fIn > (picoos_single) 0.0f) { - if ((fIn - fVal) < (picoos_single) 0.5f) - return fVal; - else - return fVal + (picoos_single) 1.0f; - } else { - if ((fVal - fIn) < (picoos_single) 0.5f) - return fVal; - else - return fVal - (picoos_single) 1.0f; - } -}/*f_round*/ - -/** - * updates the input vector for PAM - * @param this : Pam object pointer - * @return PICO_OK : update successful - * @return PICO_ERR_OTHER : errors on retrieving the PU pointer - * @remarks Modifies pam->sPhFeats[] - * @callgraph - * @callergraph - */ -static pico_status_t pam_update_vector(register picodata_ProcessingUnit this) -{ - pam_subobj_t *pam; - picoos_uint8 numstates, nI; - picoos_single fDur, f0avg, f0quant, minf0, maxf0, durquant1, durquant2, - mindur, maxdur1, maxdur2; - - pam = (pam_subobj_t *) this->subObj; - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - /*default init*/ - pam->sPhFeats[DUR] = 0; - pam->sPhFeats[F0] = 0; - /* - Hard coded parameters for quantization - */ - numstates = PICOPAM_NRSTPF; - f0quant = 30.0f; - minf0 = 90.0f; - maxf0 = 360.0f; - - durquant1 = 20.0f; - durquant2 = 100.0f; - mindur = 40.0f; - maxdur1 = 160.0f; - maxdur2 = 600.0f; - f0avg = 0.0f; - for (nI = 0; nI < numstates; nI++) - f0avg += pam->phonF0[nI]; - f0avg /= (picoos_single) numstates; - - f0avg = f_round(f0avg / f0quant) * f0quant; - if (f0avg < minf0) - f0avg = minf0; - if (f0avg > maxf0) - f0avg = maxf0; - - /*make initial silence of sentence shorter (see also pam_put_item)*/ - if ((pam->nCurrSyllable == 0) && (pam->nSyllPhoneme == 0)) { - pam->phonDur = 2 * 4; - } - - fDur = (picoos_single) pam->phonDur; - fDur = f_round(fDur / durquant1) * durquant1; - if (fDur < mindur) - fDur = mindur; - if (fDur > maxdur1) { - fDur = f_round(fDur / durquant2) * durquant2; - if (fDur > maxdur2) - fDur = maxdur2; - } - pam->sPhFeats[DUR] = (picoos_uint8) (fDur / (picoos_single) 10.0f); - pam->sPhFeats[F0] = (picoos_uint8) (f0avg / (picoos_single) 10.0f); - - return PICO_OK; -}/*pam_update_vector*/ - -/** - * compress a single feature in the range 0..9 - * @param inVal : the value to be compressed - * @return compVal : the compressed value - * @callgraph - * @callergraph - */ -static picoos_uint8 pamCompressComponent(picoos_uint8 inVal) -{ - if (inVal <= 5) - return inVal; - if ((5 < inVal) && (inVal <= 10)) - return 6; - if ((10 < inVal) && (inVal <= 20)) - return 7; - if ((20 < inVal) && (inVal <= 30)) - return 8; - return 9; -}/*pamCompressComponent*/ - -/** - * prepares the input vector for tree feeding - * @param this : Pam object pointer - * @return PICO_OK : vector expanded - * @return PICO_ERR_OTHER : errors on expansion or retrieving the PU pointer - * @remarks Modifies pam->sPhFeats[] - * @callgraph - * @callergraph - */ -static pico_status_t pam_expand_vector(register picodata_ProcessingUnit this) -{ - pam_subobj_t *pam; - picoos_uint8 *inVect, *phonVect, *outVect, nI; - picoos_int16 nOffs, nOffs1, nLen; - pam = (pam_subobj_t *) this->subObj; - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - inVect = &(pam->sSyllFeats[pam->nCurrSyllable].phoneV[0]); - phonVect = &(pam->sPhIds[0]); - outVect = &(pam->sPhFeats[0]); - /*just copy back*/ - for (nI = 0; nI < PICOPAM_INVEC_SIZE; nI++) - outVect[nI] = inVect[nI]; - /*now fill missing fields*/ - picoos_mem_copy((void*) &(inVect[FID]), &nOffs, sizeof(nOffs)); - /*offset to first phone of current syllable*/ - nOffs = nOffs + pam->nSyllPhoneme; /*offset to current phone of current syllable*/ - nLen = inVect[B3]; /*len of current syllable*/ - if (pam->nSyllPhoneme >= nLen) { - /*error on addressing current phone*/ - return PICO_ERR_OTHER; - } - /*previous of the previous phone*/ - nOffs1 = nOffs - 2; - if (nOffs1 >= 0) - outVect[P1] = phonVect[nOffs1]; - else - outVect[P1] = PICOPAM_PH_DONT_CARE_VAL; - /*previous phone*/ - nOffs1 = nOffs - 1; - if (nOffs1 >= 0) - outVect[P2] = phonVect[nOffs1]; - else - outVect[P2] = PICOPAM_PH_DONT_CARE_VAL; - /*^current phone*/ - outVect[P3] = phonVect[nOffs]; - - /*next phone*/ - nOffs1 = nOffs + 1; - if (nOffs1 < pam->nTotalPhonemes) - outVect[P4] = phonVect[nOffs1]; - else - outVect[P4] = PICOPAM_PH_DONT_CARE_VAL; - /*next of the next phone*/ - nOffs1 = nOffs + 2; - if (nOffs1 < pam->nTotalPhonemes) - outVect[P5] = phonVect[nOffs1]; - else - outVect[P5] = PICOPAM_PH_DONT_CARE_VAL; - /*pos of curr phone with respect to left syllable boundary*/ - outVect[P6] = pam->nSyllPhoneme + 1; - /*pos of curr phone with respect to right syllable boundary*/ - outVect[P7] = nLen - pam->nSyllPhoneme; - /*is current phone in consonant syllable boundary? (1:yes)*/ - if (pam->nSyllPhoneme < inVect[P8]) - outVect[P8] = 1; - else - outVect[P8] = 0; - return PICO_OK; -}/*pam_expand_vector*/ - -/** - * compresses the input vector for PAM - * @param this : Pam object pointer - * @return PICO_OK : compression successful - * @return PICO_ERR_OTHER : errors on retrieving the PU pointer - * @remarks Modifies pam->sPhFeats[] - * @callgraph - * @callergraph - */ -static pico_status_t pamCompressVector(register picodata_ProcessingUnit this) -{ - pam_subobj_t *pam; - picoos_uint8 *outVect, nI; - pam = (pam_subobj_t *) this->subObj; - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - outVect = &(pam->sPhFeats[0]); - for (nI = 0; nI < PICOPAM_INVEC_SIZE; nI++) { - switch (nI) { - case P1: - case P2: - case P3: - case P4: - case P5: - case B1: - case B2: - case B16: - case E1: - case H5: - /*don't do any compression*/ - break; - default: - /*do compression*/ - if (outVect[nI] != PICOPAM_DONT_CARE_VALUE) - outVect[nI] = pamCompressComponent(outVect[nI]); - else - outVect[nI] = PICOPAM_DONT_CARE_VAL; - break; - } - } - return PICO_OK; -}/*pamCompressVector*/ - -/** - * reorganizes the input vector for PAM - * @param this : Pam object pointer - * @return PICO_OK : reorganization successful - * @return PICO_ERR_OTHER : errors on retrieving the PU pointer - * @remarks Modifies pam->sPhFeats[] - * @callgraph - * @callergraph - */ -static pico_status_t pamReorgVector(register picodata_ProcessingUnit this) -{ - pam_subobj_t *pam; - picoos_uint8 *outVect, inVect[60], nI; - pam = (pam_subobj_t *) this->subObj; - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - outVect = &(pam->sPhFeats[0]); - for (nI = 0; nI < PICOPAM_INVEC_SIZE; nI++) inVect[nI] = outVect[nI]; - /*reorganize*/ - for (nI = T_B1; nI <= T_H5; nI++) { - switch (nI) { - case T_B1: - outVect[T_B1] = inVect[B1]; - break; - case T_B2: - outVect[T_B2] = inVect[B2]; - break; - case T_B3: - outVect[T_B3] = inVect[B3]; - break; - case T_B4: - outVect[T_B4] = inVect[B4]; - break; - case T_B5: - outVect[T_B5] = inVect[B5]; - break; - case T_B6: - outVect[T_B6] = inVect[B6]; - break; - case T_B7: - outVect[T_B7] = inVect[B7]; - break; - case T_B8: - outVect[T_B8] = inVect[B8]; - break; - case T_B9: - outVect[T_B9] = inVect[B9]; - break; - case T_B10: - outVect[T_B10] = inVect[B10]; - break; - case T_B11: - outVect[T_B11] = inVect[B11]; - break; - case T_B12: - outVect[T_B12] = inVect[B12]; - break; - case T_B13: - outVect[T_B13] = inVect[B13]; - break; - case T_B14: - outVect[T_B14] = inVect[B14]; - break; - case T_B15: - outVect[T_B15] = inVect[B15]; - break; - case T_B16: - outVect[T_B16] = inVect[B16]; - break; - case T_B17: - outVect[T_B17] = inVect[B17]; - break; - case T_B18: - outVect[T_B18] = inVect[B18]; - break; - case T_B19: - outVect[T_B19] = inVect[B19]; - break; - case T_B20: - outVect[T_B20] = inVect[B20]; - break; - case T_B21: - outVect[T_B21] = inVect[B21]; - break; - - case T_E1: - outVect[T_E1] = inVect[E1]; - break; - case T_E2: - outVect[T_E2] = inVect[E2]; - break; - case T_E3: - outVect[T_E3] = inVect[E3]; - break; - case T_E4: - outVect[T_E4] = inVect[E4]; - break; - case T_E5: - outVect[T_E5] = inVect[E5]; - break; - case T_E6: - outVect[T_E6] = inVect[E6]; - break; - case T_E7: - outVect[T_E7] = inVect[E7]; - break; - case T_E8: - outVect[T_E8] = inVect[E8]; - break; - case T_E9: - outVect[T_E9] = inVect[E9]; - break; - case T_E10: - outVect[T_E10] = inVect[E10]; - break; - case T_E11: - outVect[T_E11] = inVect[E11]; - break; - case T_E12: - outVect[T_E12] = inVect[E12]; - break; - case T_E13: - outVect[T_E13] = inVect[E13]; - break; - - case T_A3: - outVect[T_A3] = inVect[A3]; - break; - case T_C3: - outVect[T_C3] = inVect[C3]; - break; - case T_D2: - outVect[T_D2] = inVect[D2]; - break; - case T_F2: - outVect[T_F2] = inVect[F2]; - break; - - case T_G1: - outVect[T_G1] = inVect[G1]; - break; - case T_I1: - outVect[T_I1] = inVect[I1]; - break; - - case T_G2: - outVect[T_G2] = inVect[G2]; - break; - case T_I2: - outVect[T_I2] = inVect[I2]; - break; - - case T_H1: - outVect[T_H1] = inVect[H1]; - break; - case T_H2: - outVect[T_H2] = inVect[H2]; - break; - case T_H3: - outVect[T_H3] = inVect[H3]; - break; - case T_H4: - outVect[T_H4] = inVect[H4]; - break; - case T_H5: - outVect[T_H5] = inVect[H5]; - break; - } - } - return PICO_OK; -}/*pamReorgVector*/ - -/** - * puts a PAM item into PU output buffer - * @param this : Pam object pointer - * @param outBuff : output buffer base pointer - * @param outWritePos : offset in output buffer - * @param *bytesWr : actual bytes written - * @return PICO_OK : put successful - * @return PICO_ERR_OTHER : errors on retrieving the PU pointer - * @callgraph - * @callergraph - */ -static pico_status_t pam_put_item(register picodata_ProcessingUnit this, - picoos_uint8 *outBuff, picoos_uint16 outWritePos, picoos_uint8 *bytesWr) -{ - pam_subobj_t *pam; - picoos_uint8 *sDest, nI, nType, nIdx, fde; - picoos_uint32 pos, pos32; - picoos_int16 ft, dt; - picoos_uint16 uMinDur, uMaxDur; - pam = (pam_subobj_t *) this->subObj; - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - sDest = &(outBuff[outWritePos]); - sDest[0] = PICODATA_ITEM_PHONE; /*Item type*/ - sDest[1] = pam->sPhFeats[P3]; /*phonetic id*/ - sDest[2] = PICOPAM_NRSTPF; /*number of states per phone*/ - sDest[3] = sizeof(picoos_uint16) * PICOPAM_NRSTPF * 3; /*size of the item*/ - pos = 4; - /*make initial silence of sentence shorter (see also UpdateVector)*/ - if ((pam->nCurrSyllable == 0) && (pam->nSyllPhoneme == 0)) { - for (nI = 0; nI < PICOPAM_NRSTPF - 1; nI++) - pam->numFramesState[nI] = 0; - pam->numFramesState[nI] = 2; - } else { - /*manage silence syllables with prescribed durations*/ - pos32 = Min; - picoos_read_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV, - &pos32, &uMinDur); - pos32 = Max; - picoos_read_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV, - &pos32, &uMaxDur); - - if (uMaxDur > 0) { - /* Select weights*/ - nType = pam->sSyllFeats[pam->nCurrSyllable].phoneV[bnd]; - switch (nType) { - case PICODATA_ITEMINFO1_BOUND_SBEG: - nIdx = PICOPAM_PWIDX_SBEG; - break; - case PICODATA_ITEMINFO1_BOUND_PHR1: - nIdx = PICOPAM_PWIDX_PHR1; - break; - case PICODATA_ITEMINFO1_BOUND_PHR2: - nIdx = PICOPAM_PWIDX_PHR2; - break; - case PICODATA_ITEMINFO1_BOUND_SEND: - case PICODATA_ITEMINFO1_BOUND_TERM: - nIdx = PICOPAM_PWIDX_SEND; - break; - default: - nIdx = PICOPAM_PWIDX_DEFA; - break; - } - fde = 2; - ft = 0; - dt = 0; - picodata_transformDurations( - fde, /* 2's exponent of frame duration in ms, e.g. 2 for 4ms, 3 for 8ms */ - PICOPAM_NRSTPF, /* number of states per phone */ - &(pam->numFramesState[0]), /* estimated durations */ - pam->sil_weights[nIdx], /* integer weights */ - uMinDur, /* minimum target duration in ms */ - uMaxDur, /* maximum target duration in ms */ - ft, /* factor to be multiplied to get the target */ - &dt /* in/out, rest in ms */ - ); - } - } - /*put data*/ - for (nI = 0; nI < PICOPAM_NRSTPF; nI++) { - picoos_write_mem_pi_uint16(sDest, &pos, - (picoos_uint16) pam->numFramesState[nI]); - picoos_write_mem_pi_uint16(sDest, &pos, - (picoos_uint16) pam->lf0Index[nI]); - picoos_write_mem_pi_uint16(sDest, &pos, - (picoos_uint16) pam->mgcIndex[nI]); - } - *bytesWr = sizeof(picodata_itemhead_t) + sizeof(picoos_uint16) - * PICOPAM_NRSTPF * 3; - return PICO_OK; -}/*pam_put_item*/ - -/** - * puts a non PAM (queued) item into PU output buffer - * @param qItem : pointer to item to put - * @param outBuff : output buffer base pointer - * @param outWritePos : offset in output buffer - * @param *bytesWr : actual bytes written - * @return PICO_OK : put successful - * @return PICO_ERR_OTHER : errors on retrieving the PU pointer - * @callgraph - * @callergraph - */ -static pico_status_t pam_put_qItem(picoos_uint8 *qItem, picoos_uint8 *outBuff, - picoos_uint16 outWritePos, picoos_uint8 *bytesWr) -{ - picoos_uint8 *sDest, nI; - sDest = &(outBuff[outWritePos]); - *bytesWr = sizeof(picodata_itemhead_t); - for (nI = 0; nI < (sizeof(picodata_itemhead_t) + qItem[3]); nI++) { - sDest[nI] = qItem[nI]; - } - *bytesWr = nI; - return PICO_OK; -}/*pam_put_qItem*/ - -/** - * tells if an item is a PAM command (except play) - * @param qItem : input item to test - * @return TRUE : qItem is a PAM command (except play) - * @return FALSE : qItem not a PAM command - * @callgraph - * @callergraph - */ -static pico_status_t is_pam_command(const picoos_uint8 * qItem) -{ - switch (qItem[0]) { - - case PICODATA_ITEM_CMD: - switch (qItem[1]) { - case PICODATA_ITEMINFO1_CMD_FLUSH: - /* flush is for all PU's and as such it is also for PAM*/ - case PICODATA_ITEMINFO1_CMD_PITCH: - case PICODATA_ITEMINFO1_CMD_SPEED: - return TRUE; - break; - default: - break; - } - } - return FALSE; -}/*is_pam_command*/ - -/** - * tells if an item is a PAM PLAY command - * @param qItem : input item to test - * @return TRUE : qItem is a PAM PLAY command - * @return FALSE : qItem not a PAM PLAY command - * @callgraph - * @callergraph - */ -static pico_status_t is_pam_play_command(picoos_uint8 *qItem) -{ - switch (qItem[0]) { - - case PICODATA_ITEM_CMD: - switch (qItem[1]) { - case PICODATA_ITEMINFO1_CMD_PLAY: - if (qItem[2] == PICODATA_ITEMINFO2_CMD_TO_PAM) - return TRUE; - break; - default: - break; - } - } - return FALSE; -}/*is_pam_play_command*/ - -/** - * command processor for PAM pu - * @param this : Pam item subobject - * @param qItem : input item pointer - * @return PICOPAM_FLUSH_RECEIVED : when a FLUSH is received - * @return PICOPAM_CONTINUE : normal command processing - * @return PICODATA_PU_ERROR : errors in accessing data - * @callgraph - * @callergraph - */ -static pico_status_t pamDoCommand(register picodata_ProcessingUnit this, - picoos_uint8 *qItem) -{ - pam_subobj_t *pam; - picoos_single fValue; - picoos_uint16 nValue; - picoos_uint32 nPos; - pam = (pam_subobj_t *) this->subObj; - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - if (qItem[0] == PICODATA_ITEM_CMD) { - switch (qItem[1]) { - case PICODATA_ITEMINFO1_CMD_FLUSH: - /* flush is for all PU's and as such it is also for PAM : implement the flush!!*/ - pam_reset_processors(this); - pam->nLastAttachedItemId = pam->nCurrAttachedItem = 0; - pam->nAttachedItemsSize = 0; - return PICOPAM_FLUSH_RECEIVED; - break; - - case PICODATA_ITEMINFO1_CMD_PITCH: - case PICODATA_ITEMINFO1_CMD_SPEED: - nPos = 4; - picoos_read_mem_pi_uint16(qItem, &nPos, &nValue); - if (qItem[2] == 'a') { - /*absloute modifier*/ - fValue = (picoos_single) nValue / (picoos_single) 100.0f; - if (qItem[1] == PICODATA_ITEMINFO1_CMD_PITCH) - pam->pMod = fValue; - if (qItem[1] == PICODATA_ITEMINFO1_CMD_SPEED) - pam->dMod = (1.0f / fValue); - } - if (qItem[2] == 'r') { - /*relative modifier*/ - fValue = (picoos_single) nValue / (picoos_single) 1000.0f; - if (qItem[1] == PICODATA_ITEMINFO1_CMD_PITCH) - pam->pMod *= (1.0f / fValue); - if (qItem[1] == PICODATA_ITEMINFO1_CMD_SPEED) - pam->dMod *= (1.0f / fValue); - } - return PICOPAM_CONTINUE; - break; - - default: - break; - }/*end switch switch (qItem[1])*/ - }/*end if (qItem[0]==PICODATA_ITEM_CMD)*/ - return PICOPAM_CONTINUE; -}/*pamDoCommand*/ - -/** - * defines if an item has to be sent to following PUs - * @param qItem : input item pointer - * @return TRUE : item has to be transmitted to following PUs - * @return FALSE : item has to be consumed internallz on PAM - * @callgraph - * @callergraph - */ -static pico_status_t isItemToPut(picoos_uint8 *qItem) -{ - switch (qItem[0]) { - case PICODATA_ITEM_CMD: - /* is a command*/ - if (PICODATA_ITEMINFO1_CMD_SPEED == qItem[1]) { - /* SPEED consumed here*/ - return FALSE; - } - break; - case PICODATA_ITEM_BOUND: - switch (qItem[1]) { - case PICODATA_ITEMINFO1_BOUND_SBEG: - case PICODATA_ITEMINFO1_BOUND_PHR0: - case PICODATA_ITEMINFO1_BOUND_PHR1: - case PICODATA_ITEMINFO1_BOUND_PHR2: - case PICODATA_ITEMINFO1_BOUND_PHR3: - /*boudary items consumed here except SEND,TERM*/ - return FALSE; - break; - default: - break; - } - break; - default: - break; - } - /*all other items not explicitly mentioned here - are transmitted to next PUs*/ - return TRUE; -}/*isItemToPut*/ - -/** - * pushes a boundary TERM item into some buffer - * @param outBuff : output buffer base pointer - * @param outWritePos : offset in output buffer - * @param *bytesWr : actual bytes written - * @return PICO_OK - * @remarks used while forcing TERM input items in forward processing - * @callgraph - * @callergraph - */ -static pico_status_t pam_put_term(picoos_uint8 *outBuff, - picoos_uint16 outWritePos, picoos_uint8 *bytesWr) -{ - picoos_uint8 *sDest; - sDest = &(outBuff[outWritePos]); - sDest[0] = PICODATA_ITEM_BOUND; /*Item type*/ - sDest[1] = PICODATA_ITEMINFO1_BOUND_TERM; - sDest[2] = PICODATA_ITEMINFO2_BOUNDTYPE_T; - sDest[3] = 0; /*item size*/ - *bytesWr = 4; - return PICO_OK; -}/*pam_put_term*/ - -/** - * translates one full phone into a PHONE Item including DT Dur, F0 and CEP trees feature generation and traversal - * @param this : Pam item subobject pointer - * @return PICO_OK : processing successful - * @return PICODATA_PU_ERROR : error accessing PAM object - * @return !=PICO_OK : processing errors - * @callgraph - * @callergraph - */ -static pico_status_t pamPhoneProcess(register picodata_ProcessingUnit this) -{ - pam_subobj_t *pam; - pico_status_t sResult; - picokdt_classify_result_t dTreeResult; - picoos_uint8 nI, bWr; - - pam = (pam_subobj_t *) this->subObj; - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - /*expands current phone in current syllable in the corresponding vector pam->sPhFeats[]*/ - sResult = pam_expand_vector(this); - sResult = pamCompressVector(this); - sResult = pamReorgVector(this); - - /*tree traversal for duration*/ - if (!pam_do_tree(this, pam->dtdur, &(pam->sPhFeats[0]), PICOPAM_INVEC_SIZE, - &dTreeResult)) { - PICODBG_WARN(("problem using pam tree dtdur, using fallback value")); - dTreeResult.class = 0; - } - pam->durIndex = dTreeResult.class; - sResult = pam_get_duration(this, pam->durIndex, &(pam->phonDur), - &(pam->numFramesState[0])); - - /*tree traversal for pitch*/ - for (nI = 0; nI < PICOPAM_MAX_STATES_PER_PHONE; nI++) { - if (!pam_do_tree(this, pam->dtlfz[nI], &(pam->sPhFeats[0]), - PICOPAM_INVEC_SIZE, &dTreeResult)) { - PICODBG_WARN(("problem using pam tree lf0Tree, using fallback value")); - dTreeResult.class = 0; - } - pam->lf0Index[nI] = dTreeResult.class; - } - - /*pdf access for pitch*/ - for (nI = 0; nI < PICOPAM_MAX_STATES_PER_PHONE; nI++) { - sResult = pam_get_f0(this, &(pam->lf0Index[0]), nI, &(pam->phonF0[0])); - } - - /*update vector with duration and pitch for cep tree traversal*/ - sResult = pam_update_vector(this); - /*cep tree traversal*/ - for (nI = 0; nI < PICOPAM_MAX_STATES_PER_PHONE; nI++) { - - if (!pam_do_tree(this, pam->dtmgc[nI], &(pam->sPhFeats[0]), - PICOPAM_INVEC_SIZE, &dTreeResult)) { - PICODBG_WARN(("problem using pam tree lf0Tree, using fallback value")); - dTreeResult.class = 0; - } - pam->mgcIndex[nI] = dTreeResult.class; - } - /*put item to output buffer*/ - sResult = pam_put_item(this, pam->outBuf, pam->outWritePos, &bWr); - if (sResult == PICO_OK) - pam->outWritePos += bWr; - else - return sResult; - return PICO_OK; -}/*pamPhoneProcess*/ - -/** - * manages first syllable attached items when seen before SBEG - * @param this : Pam item subobject pointer - * @return PICO_OK (0) : default return code --> means no more items to be processed before 1st syllable - * @return PICOPAM_GOTO_FEED : go to feed state after this - * @return PICOPAM_GOTO_SCHEDULE : flush received - * @return PICODATA_PU_ERROR : errors - * @callgraph - * @callergraph - */ -static pico_status_t pamDoPreSyll(register picodata_ProcessingUnit this) -{ - pam_subobj_t *pam; - pico_status_t sResult; - picoos_uint8 bWr, nRc; - picoos_uint8 *qItem; - nRc = PICOPAM_PRE_SYLL_ENDED; - pam = (pam_subobj_t *) this->subObj; - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - /*regenerate initial items before the phonemes*/ - if (((qItem = pamPopAttachedSy0(this)) != NULL) && !((qItem[0] - == PICODATA_ITEM_BOUND) && (qItem[1] - == PICODATA_ITEMINFO1_BOUND_SBEG))) { - if (isItemToPut(qItem)) { - pam_put_qItem(qItem, pam->outBuf, pam->outWritePos, &bWr);/*popped item has to be sent to next PU*/ - pam->outWritePos += bWr; - nRc = PICOPAM_GOTO_FEED; - } - - if (is_pam_command(qItem) == TRUE) { - nRc = pamDoCommand(this, qItem); /*popped item is a PAM command : do it NOW!!*/ - if ((nRc == PICOPAM_FLUSH_RECEIVED) || (nRc == PICODATA_PU_ERROR)) { - /*FLUSH command RECEIVED or errors: stop ALL PROCESSING*/ - return nRc; - } - } - pam->nCurrAttachedItem++; - if (nRc == 0) - return PICOPAM_CONTINUE; - else - return nRc; - } - /*SBEG item management*/ - if ((qItem != NULL) && (qItem[0] == PICODATA_ITEM_BOUND) && (qItem[1] - == PICODATA_ITEMINFO1_BOUND_SBEG)) { - sResult = pam_put_qItem(qItem, pam->outBuf, pam->outWritePos, &bWr); - pam->outWritePos += bWr; - pam->nCurrAttachedItem++; - nRc = PICOPAM_GOTO_FEED; - } - return nRc; -}/*pamDoPreSyll*/ - -/** - * performs a step of the pam processing - * @param this : Pam item subobject pointer - * @param mode : mode for the PU - * @param *numBytesOutput : pointer to output number fo bytes produced - * @return PICODATA_PU_IDLE : nothing to do - * @return PICODATA_PU_BUSY : still tasks undergoing - * @return PICODATA_PU_ERROR : errors on processing - * @callgraph - * @callergraph - */ -static picodata_step_result_t pam_step(register picodata_ProcessingUnit this, - picoos_int16 mode, picoos_uint16 * numBytesOutput) -{ - - register pam_subobj_t * pam; - - pico_status_t sResult; - picoos_uint16 blen, numinb, numoutb; - pico_status_t rv; - picoos_uint8 bWr; - picoos_uint8 bForcedItem[4]; - picoos_uint8 *qItem; - - numinb = 0; - numoutb = 0; - rv = PICO_OK; - - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - pam = (pam_subobj_t *) this->subObj; - mode = mode; /* avoid warning "var not used in this function"*/ - /*Init number of output bytes*/ - *numBytesOutput = 0; - - while (1) { /* exit via return */ - - PICODBG_DEBUG(("pam_step -- doing state %i",pam->procState)); - - switch (pam->procState) { - - case PICOPAM_COLLECT: - /* *************** item collector ***********************************/ - /*collecting items from the PU input buffer*/ - sResult = picodata_cbGetItem(this->cbIn, - &(pam->inBuf[pam->inWritePos]), pam->inBufSize - - pam->inWritePos, &blen); - if (sResult != PICO_OK) { - if (sResult == PICO_EOF) { - /*no items available : remain in state 0 and return idle*/ - return PICODATA_PU_IDLE; - } else { - /*errors : remain in state 0 and return error*/ - PICODBG_DEBUG(("pam_step(PICOPAM_COLLECT) -- Errors on item buffer input, status: %d",sResult)); - return PICODATA_PU_ERROR; - } - } - - PICODBG_DEBUG(("pam_step -- got item, status: %d",sResult)); - sResult = picodata_is_valid_item( - &(pam->inBuf[pam->inWritePos]), blen); - if (sResult != TRUE) { - /*input item is not valid : consume the input item and stay in COLLECT*/ - pam->inWritePos += blen; - pam->inReadPos += blen; - if (pam->inReadPos >= pam->inWritePos) { - pam->inReadPos = 0; - pam->inWritePos = 0; - }PICODBG_DEBUG(("pam_step -- item is not valid, type: %d",pam->inBuf[pam->inWritePos])); - return PICODATA_PU_BUSY; - } - - /*update input write pointer + move to "schedule" state*/ - pam->inWritePos += blen; - pam->procState = PICOPAM_SCHEDULE; - return PICODATA_PU_BUSY; - - case PICOPAM_SCHEDULE: - /* check out if more items are available */ - if (pam->inReadPos >= pam->inWritePos) { - /*no more items : back to collect state*/ - pam->procState = PICOPAM_COLLECT; - return PICODATA_PU_BUSY; - } - /* we have one full valid item, with len>0 starting at - pam->inBuf[pam->inReadPos]; here we decide how to elaborate it */ - - /* PLAY management */ - if (is_pam_play_command(&(pam->inBuf[pam->inReadPos])) == TRUE) { - /*consume the input item : it has been managed*/ - pam->inReadPos += pam->inBuf[pam->inReadPos + 3] - + sizeof(picodata_itemhead_t); - if (pam->inReadPos >= pam->inWritePos) { - pam->inReadPos = 0; - pam->inWritePos = 0; - } - /*stay in schedule*/ - return PICODATA_PU_BUSY; - } - - if (pam_check_immediate(this, &(pam->inBuf[pam->inReadPos]))) { - /* item has to be sent to next PU NOW : switch to "immediate" state */ - pam->procState = PICOPAM_IMMEDIATE; - return PICODATA_PU_BUSY; - } - if (pamCheckResourceLimits(this, &(pam->inBuf[pam->inReadPos]))) { - /* item would not fit into local buffers -->> free some space -->> - switch to "force term" state */ - pam->procState = PICOPAM_FORWARD_FORCE_TERM; - return PICODATA_PU_BUSY; - } - - if (pam_deal_with(&(pam->inBuf[pam->inReadPos]))) { - /* item has to be managed by the "forward" state : switch to forward state*/ - pam->procState = PICOPAM_FORWARD; - return PICODATA_PU_BUSY; - } - - if (pam_hastobe_queued(this, &(pam->inBuf[pam->inReadPos]))) { - /* item is not for PAM so it has to be queued internally */ - pam_queue(this, &(pam->inBuf[pam->inReadPos])); - /*consume the input item : it has been queued*/ - pam->inReadPos += pam->inBuf[pam->inReadPos + 3] - + sizeof(picodata_itemhead_t); - if (pam->inReadPos >= pam->inWritePos) { - pam->inReadPos = 0; - pam->inWritePos = 0; - } - return PICODATA_PU_BUSY; - } - /*if we get here something wrong happened. Being the the item valid, - switch to "immediate" state -> send it to next PU -> */ - PICODBG_DEBUG(("pam_step (PICOPAM_SCHEDULE) -- unexpected item is sent to next PU !!")); - pam->procState = PICOPAM_IMMEDIATE; - return PICODATA_PU_BUSY; - break; /*PICOPAM_SCHEDULE*/ - - case PICOPAM_FORWARD: - /*we have one full valid item, with len>0 starting at pam->inBuf[pam->inReadPos]. - furthermore this item should be in the set {BOUND,SYLL}. - No other items should arrive here*/ - sResult = pam_adapter_forward_step(this, - &(pam->inBuf[pam->inReadPos])); - /*decide if this item has to be queued for later re-synchronization - normally this is only done for SEND/TERM items*/ - if (pam_hastobe_queued(this, &(pam->inBuf[pam->inReadPos]))) { - /*item has to be queued iternally in local storage*/ - pam_queue(this, &(pam->inBuf[pam->inReadPos])); - } - /*now assign next state according to Forward results*/ - switch (sResult) { - case PICOPAM_READY: - pam->needMoreInput = FALSE; - /*consume the input item : it has already been stored*/ - pam->inReadPos += pam->inBuf[pam->inReadPos + 3] - + sizeof(picodata_itemhead_t); - if (pam->inReadPos >= pam->inWritePos) { - pam->inReadPos = 0; - pam->inWritePos = 0; - } - /*activate backward processing*/ - sResult = pam_adapter_backward_step(this); - if (sResult == PICO_OK) { - pam->procState = PICOPAM_PROCESS; - return PICODATA_PU_BUSY; - } else { - PICODBG_DEBUG(("pam_step (PICOPAM_FORWARD) -- wrong return from BackwardStep: %d -- Buffered sentence will be discarded",sResult)); - pam_reset_processors(this); - pam->nLastAttachedItemId = pam->nCurrAttachedItem - = 0; - pam->nAttachedItemsSize = 0; - - pam->procState = PICOPAM_SCHEDULE; - return PICODATA_PU_BUSY; - } - break; - - case PICOPAM_MORE: - pam->needMoreInput = TRUE; - /*consume the input item : it has already been stored*/ - pam->inReadPos += pam->inBuf[pam->inReadPos + 3] - + sizeof(picodata_itemhead_t); - if (pam->inReadPos >= pam->inWritePos) { - /*input is finished and PAM need more data : - clenaup input buffer + switch state back to "schedule state" - */ - pam->inReadPos = 0; - pam->inWritePos = 0; - pam->procState = PICOPAM_SCHEDULE; - return PICODATA_PU_ATOMIC; - } else { - /*input is not finished and need more data : - remain in state "PICOPAM_FORWARD" */ - return PICODATA_PU_ATOMIC; - } - break; - - case PICOPAM_NA: - default: - /*this item has not been stored in internal buffers: - assign this item to the management of - "immediate" state*/ - pam->procState = PICOPAM_IMMEDIATE; - return PICODATA_PU_BUSY; - break; - } /*end switch sResult*/ - break; /*PICOPAM_FORWARD*/ - - case PICOPAM_FORWARD_FORCE_TERM: - /*we have one full valid item, with len>0 - starting at pam->inBuf[pam->inReadPos] but we decided - to force a TERM item before, without losing the item in - inBuf[inReadPos] : --> generate a TERM item and do the - forward processing */ - pam_put_term(bForcedItem, 0, &bWr); - sResult = pam_adapter_forward_step(this, &(bForcedItem[0])); - switch (sResult) { - case PICOPAM_READY: - pam_queue(this, &(bForcedItem[0])); - /*activate backward processing*/ - sResult = pam_adapter_backward_step(this); - if (sResult == PICO_OK) { - pam->procState = PICOPAM_PROCESS; - return PICODATA_PU_BUSY; - } else { - PICODBG_DEBUG(("pam_step (PICOPAM_FORWARD_FORCE_TERM) -- wrong return from BackwardStep: %d -- Buffered sentence will be discarded",sResult)); - pam_reset_processors(this); - pam->nLastAttachedItemId = pam->nCurrAttachedItem - = 0; - pam->nAttachedItemsSize = 0; - - pam->procState = PICOPAM_SCHEDULE; - return PICODATA_PU_BUSY; - } - break; - - default: - PICODBG_DEBUG(("pam_step (PICOPAM_FORWARD_FORCE_TERM) -- Forced a TERM but processing do not appear to end -- Buffered sentence will be discarded",sResult)); - pam_reset_processors(this); - pam->nLastAttachedItemId = pam->nCurrAttachedItem = 0; - pam->nAttachedItemsSize = 0; - - pam->procState = PICOPAM_SCHEDULE; - return PICODATA_PU_BUSY; - break; - - } /*end switch sResult*/ - break; /*PICOPAM_FORWARD_FORCE_TERM*/ - - case PICOPAM_PROCESS: - - if ((PICOPAM_FRAME_ITEM_SIZE + 4) > (pam->outBufSize - - pam->outWritePos)) { - /*WARNING (buffer overflow): leave status unchanged until output buffer free */ - return PICODATA_PU_BUSY; - } - - if (pam->nCurrSyllable == 0) { - sResult = pamDoPreSyll(this); - if (sResult == PICOPAM_GOTO_FEED) { - /* - items pushed to output buffer : - switch to "feed" but then back - to "process" - */ - pam->retState = PICOPAM_PROCESS; - pam->procState = PICOPAM_FEED; - return PICODATA_PU_BUSY; - } - if (sResult == PICOPAM_CONTINUE) { - /* - items processed (maybe commands) : - return (maybe we need to process other - items in pre_syll) and then back to "process" - */ - pam->retState = PICOPAM_PROCESS; - pam->procState = PICOPAM_PROCESS; - return PICODATA_PU_BUSY; - } - - if ((sResult == PICOPAM_FLUSH_RECEIVED) || (sResult - == PICODATA_PU_ERROR)) { - /* - items processed were a flush or - problems found: switch to "schedule" - and abort all processing - */ - pam->retState = PICOPAM_SCHEDULE; - pam->procState = PICOPAM_SCHEDULE; - return PICODATA_PU_BUSY; - } - if (sResult == PICOPAM_PRE_SYLL_ENDED) { - /* - we get here when pam->nCurrSyllable==0 and - no more items to be processed before the syllable - */ - sResult = sResult; - } - } - - if (pamHasToProcess(this)) { - if (pamPhoneProcess(this) == PICO_OK) { - sResult = pamUpdateProcess(this); - pam->procState = PICOPAM_FEED; /*switch to feed*/ - return PICODATA_PU_BUSY; - } else { - PICODBG_DEBUG(("pam_step(PICOPAM_PROCESS) --- NULL return from pamPhoneProcess")); - return PICODATA_PU_ERROR; - } - } - - if (pamHasToPop(this) != FALSE) { - if ((qItem = pamPopItem(this)) == NULL) { - PICODBG_DEBUG(("pam_step(PICOPAM_PROCESS) --- NULL return from pamPopItem")); - return PICODATA_PU_ERROR; - } - - if (isItemToPut(qItem)) { - /*popped item has to be sent to next PU*/ - sResult = pam_put_qItem(qItem, pam->outBuf, - pam->outWritePos, &bWr); - if (sResult != PICO_OK) { - PICODBG_DEBUG(("pam_step(PICOPAM_PROCESS) --- Error on writing item to output buffer")); - return PICODATA_PU_ERROR; - } - pam->outWritePos += bWr; /*item write ok*/ - pam->procState = PICOPAM_FEED; /*switch to feed*/ - } - - /*moved command processing here (after pam_put_qItem) because of FLUSH command could erase - * the syllable structure and make it impossible to transmit the flush to other PUs*/ - if (is_pam_command(qItem) == TRUE) { - sResult = pamDoCommand(this, qItem); /*popped item is a PAM command : do it NOW!!*/ - if ((sResult == PICOPAM_FLUSH_RECEIVED) || (sResult - == PICODATA_PU_ERROR)) { - pam->retState = PICOPAM_SCHEDULE; - pam->procState = PICOPAM_SCHEDULE; /*switch to schedule */ - return PICODATA_PU_BUSY; - } - } - /*update PAM status: if more items attached to the current syllable - stay in current syllable, otherwise move to next syllable and switch - to processing phones */ - sResult = pamUpdateProcess(this); /*both "doCommand" or "put" : update PAM status*/ - return PICODATA_PU_BUSY; - } else { - pam->procState = PICOPAM_SCHEDULE; /*switch to schedule */ - return PICODATA_PU_BUSY; - } - - break; /*PICOPAM_PROCESS*/ - - case PICOPAM_IMMEDIATE: - /* *** item is output NOW!!! */ - /*context: full valid item, with len> starting at pam->inBuf[pam->inReadPos]*/ - numinb = PICODATA_ITEM_HEADSIZE - + pam->inBuf[pam->inReadPos + 3]; - sResult = picodata_copy_item(&(pam->inBuf[pam->inReadPos]), - numinb, &(pam->outBuf[pam->outWritePos]), - pam->outBufSize - pam->outWritePos, &numoutb); - - if (sResult == PICO_OK) { - pam->inReadPos += numinb; - if (pam->inReadPos >= pam->inWritePos) { - pam->inReadPos = 0; - pam->inWritePos = 0; - pam->needMoreInput = FALSE; - } - pam->outWritePos += numoutb; - pam->procState = PICOPAM_FEED; /*switch to FEED state*/ - pam->retState = PICOPAM_SCHEDULE; /*back to SCHEDULE after FEED*/ - } else { - /* - PICO_EXC_BUF_IGNORE - PICO_EXC_BUF_UNDERFLOW - PICO_EXC_BUF_OVERFLOW - */ - PICODBG_DEBUG(("pam_step(PICOPAM_IMMEDIATE) --- wrong return from picodata_copy_item:%d",sResult)); - return PICODATA_PU_ERROR; - } - return PICODATA_PU_BUSY; - break; /*PICOPAM_IMMEDIATE*/ - - case PICOPAM_FEED: - /* *************** item output/feeding ***********************************/ - /*feeding items to PU output buffer*/ - sResult = picodata_cbPutItem(this->cbOut, - &(pam->outBuf[pam->outReadPos]), pam->outWritePos - - pam->outReadPos, &numoutb); - PICODBG_DEBUG(("pam_step -- put item, status: %d",sResult)); - if (PICO_OK == sResult) { - - PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], - (picoos_uint8 *)"pam: ", - pam->outBuf + pam->outReadPos, pam->outBufSize); - - pam->outReadPos += numoutb; - *numBytesOutput = numoutb; - if (pam->outReadPos >= pam->outWritePos) { - /*reset the output pointers*/ - pam->outReadPos = 0; - pam->outWritePos = 0; - /*switch to appropriate state*/ - switch (pam->retState) { - case PICOPAM_IMMEDIATE: - pam->procState = PICOPAM_IMMEDIATE; - pam->retState = PICOPAM_SCHEDULE; - return PICODATA_PU_BUSY; - break; - case PICOPAM_PLAY: - pam->procState = PICOPAM_PLAY; - pam->retState = PICOPAM_SCHEDULE; - return PICODATA_PU_BUSY; - break; - default: - break; - } - /*Define next state - a)process (if current sentence has more data to process) - b)schedule (no more data to process in current sentence) - NOTE : case b)also happens when dealing with non BOUND/SYLL items*/ - if ((pamHasToProcess(this)) || (pamHasToPop(this))) { - pam->procState = PICOPAM_PROCESS; - } else { - pam->nCurrSyllable = -1; - pam_reset_processors(this); - pam->nLastAttachedItemId = pam->nCurrAttachedItem - = 0; - pam->nAttachedItemsSize = 0; - - pam->nSyllPhoneme = 0; - pam->procState = PICOPAM_SCHEDULE; - } - } - return PICODATA_PU_BUSY; - - } else if (PICO_EXC_BUF_OVERFLOW == sResult) { - - PICODBG_DEBUG(("pam_step ** feeding, overflow, PICODATA_PU_OUT_FULL")); - return PICODATA_PU_OUT_FULL; - - } else if ((PICO_EXC_BUF_UNDERFLOW == sResult) - || (PICO_ERR_OTHER == sResult)) { - - PICODBG_DEBUG(("pam_step ** feeding problem, discarding item")); - pam->outReadPos = 0; - pam->outWritePos = 0; - pam->procState = PICOPAM_COLLECT; - return PICODATA_PU_ERROR; - - } - break; /*PICOPAM_FEED*/ - - default: - /*NOT feeding items*/ - sResult = PICO_EXC_BUF_IGNORE; - break; - }/*end switch*/ - return PICODATA_PU_BUSY; /*check if there is more data to process after feeding*/ - - }/*end while*/ - return PICODATA_PU_IDLE; -}/*pam_step*/ - -/** - * performs one step of a PamTree - * @param this : Pam item subobject pointer - * @param dtpam : the Pam decision tree - * @param *invec : the input vector pointer - * @param inveclen : length of the input vector - * @param *dtres : the classification result - * @return dtres->set : the result of tree traversal - * @callgraph - * @callergraph - */ -static picoos_uint8 pam_do_tree(register picodata_ProcessingUnit this, - const picokdt_DtPAM dtpam, const picoos_uint8 *invec, - const picoos_uint8 inveclen, picokdt_classify_result_t *dtres) -{ - picoos_uint8 okay; - - okay = TRUE; - /* construct input vector, which is set in dtpam */ - if (!picokdt_dtPAMconstructInVec(dtpam, invec, inveclen)) { - /* error constructing invec */ - PICODBG_WARN(("problem with invec")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, NULL, NULL); - okay = FALSE; - } - /* classify */ - if (okay && (!picokdt_dtPAMclassify(dtpam))) { - /* error doing classification */ - PICODBG_WARN(("problem classifying")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, NULL, - NULL); - okay = FALSE; - } - /* decompose */ - if (okay && (!picokdt_dtPAMdecomposeOutClass(dtpam, dtres))) { - /* error decomposing */ - PICODBG_WARN(("problem decomposing")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_OUTVECTOR, NULL, NULL); - okay = FALSE; - } - - PICODBG_TRACE(("dtpam output class: %d", dtres->class)); - - return dtres->set; -}/*pam_do_tree*/ - -/** - * returns the carrier vowel id inside a syllable - * @param this : Pam item subobject pointer - * @param item : the full syllable item - * @param *pos : pointer to the variable to receive the position of the carrier vowel - * @return the phonetic id for the carrier vowel inside the syllable - * @callgraph - * @callergraph - */ -static picoos_uint8 pam_get_vowel_name(register picodata_ProcessingUnit this, - picoos_uint8 *item, picoos_uint8 *pos) -{ - pam_subobj_t *pam; - picoos_uint8 *phon, nI, nCond1; - if (NULL == this || NULL == this->subObj) { - return 0; - } - pam = (pam_subobj_t *) this->subObj; - - if (item == NULL) - return 0; - if (item[3] == 0) - return 0; - phon = &item[4]; - for (nI = 0; nI < item[3]; nI++) { - nCond1 = picoktab_isSyllCarrier(pam->tabphones, phon[nI]); - if (nCond1) { - *pos = nI; - return phon[nI]; - } - } - return 0; -}/*pam_get_vowel_name */ - -/** - * returns the pause phone id in the current ph.alphabet - * @param this : Pam sub object pointer - * @return the (numeric) phonetic id of the pause phone in current phonetic alphabet - * @return 0 : errors on getting the pam subobject pointer - * @callgraph - * @callergraph - */ -static picoos_uint8 pam_get_pause_id(register picodata_ProcessingUnit this) -{ - picoos_uint8 nVal1; - /*picoos_uint8 nVal2; */ - pam_subobj_t *pam; - if (NULL == this || NULL == this->subObj) { - return 0; - } - pam = (pam_subobj_t *) this->subObj; - nVal1 = picoktab_getPauseID(pam->tabphones); - return nVal1; -}/*pam_get_pause_id */ - -/** - * returns the pam sentence type (declarative, interrogative...) - * @param iteminfo1 : the boundary item info 1 - * @param iteminfo2 : the boundary item info 2 - * @return the sentence type suitably encoded for trees - * @callgraph - * @callergraph - */ -static picoos_uint8 pam_map_sentence_type(picoos_uint8 iteminfo1, - picoos_uint8 iteminfo2) -{ - switch (iteminfo2) { - case PICODATA_ITEMINFO2_BOUNDTYPE_P: - return PICOPAM_DECLARATIVE; - case PICODATA_ITEMINFO2_BOUNDTYPE_T: - return PICOPAM_DECLARATIVE; - case PICODATA_ITEMINFO2_BOUNDTYPE_Q: - return PICOPAM_INTERROGATIVE; - case PICODATA_ITEMINFO2_BOUNDTYPE_E: - return PICOPAM_DECLARATIVE; - default: - return PICOPAM_DECLARATIVE; - } - iteminfo1 = iteminfo1; /* avoid warning "var not used in this function"*/ - return PICOPAM_DECLARATIVE; -}/*pam_map_sentence_type */ - -/** - * returns the pam phrase type - * @param iteminfo1 : the boundary item info 1 - * @param iteminfo2 : the boundary item info 2 - * @return the phrase type suitably encoded for trees - * @callgraph - * @callergraph - */ -static picoos_uint8 pam_map_phrase_type(picoos_uint8 iteminfo1, - picoos_uint8 iteminfo2) -{ - - switch (iteminfo2) { - case PICODATA_ITEMINFO2_BOUNDTYPE_P: - switch (iteminfo1) { - case PICODATA_ITEMINFO1_BOUND_PHR1: -# ifdef PAM_PHR2_WITH_PR1 - case PICODATA_ITEMINFO1_BOUND_PHR2: -# endif - return PICOPAM_P; /*current_prhase type = "P" (encoded to 1) */ - break; - case PICODATA_ITEMINFO1_BOUND_PHR3: -# ifdef PAM_PHR2_WITH_PR3 - case PICODATA_ITEMINFO1_BOUND_PHR2 : -# endif - return PICOPAM_p; /*current_prhase type = "p" (encoded to 2) */ - break; - case PICODATA_ITEMINFO1_BOUND_SBEG: - return PICOPAM_P; /*current_prhase type = "P" (encoded to 1) */ - break; - default: - PICODBG_DEBUG(("Map pam_map_phrase_type : unexpected iteminfo1")); - return PICOPAM_P; /*current_prhase type = "P" (encoded to 1) */ - break; - } - case PICODATA_ITEMINFO2_BOUNDTYPE_T: - return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */ - break; - case PICODATA_ITEMINFO2_BOUNDTYPE_E: - return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */ - break; - case PICODATA_ITEMINFO2_BOUNDTYPE_Q: - return PICOPAM_Y; /*current_prhase type = "T" (encoded to 0) */ - break; - default: - PICODBG_DEBUG(("Map pam_map_phrase_type : unexpected iteminfo2")); - return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */ - break; - }PICODBG_DEBUG(("Map pam_map_phrase_type : unexpected iteminfo2")); - return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */ - -}/*pam_map_phrase_type */ - -/** - * does the cleanup of the sub object processors flags at sentence start - * @param this : pointer to PAM PU sub object pointer - * @return PICO_OK : reset OK - * @return PICO_ERR_OTHER : errors on getting pam sub obj pointer - * @callgraph - * @callergraph - */ -static pico_status_t pam_reset_processors(register picodata_ProcessingUnit this) -{ - pam_subobj_t *pam; - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - pam = (pam_subobj_t *) this->subObj; - - pam->nCurrSyllable = -1; - pam->nTotalPhonemes = pam->nSyllPhoneme = pam->nCurrPhoneme - = pam->nTotalSyllables = pam->sType = pam->pType = 0; - pam->dRest = 0.0f; - /*set all to 0*/ - pam->a3_overall_syllable = pam->a3_primary_phrase_syllable = pam->b4_b5_syllable = - pam->b6_b7_syllable = pam->b6_b7_state = pam->b8_b9_stressed_syllable = - pam->b10_b11_accented_syllable = pam->b12_b13_syllable = pam->b12_b13_state = - pam->b14_b15_syllable = pam->b14_b15_state = pam->b17_b19_syllable = - pam->b17_b19_state = pam->b18_b20_b21_syllable = pam->b18_b20_b21_state = - pam->c3_overall_syllable= pam->c3_primary_phrase_syllable = pam->d2_syllable_in_word = - pam->d2_prev_syllable_in_word = pam->d2_current_primary_phrase_word = pam->e1_syllable_word_start = - pam->e1_syllable_word_end= pam->e1_content = pam->e2_syllable_word_start = - pam->e2_syllable_word_end= pam->e3_e4_word = pam->e3_e4_state = - pam->e5_e6_content_word = pam->e5_e6_content = pam->e7_e8_word = - pam->e7_e8_content = pam->e7_e8_state = pam->e9_e11_word = - pam->e9_e11_saw_word = pam->e9_e11_state = pam->e10_e12_e13_word = - pam->e10_e12_e13_state = pam->e10_e12_e13_saw_word = pam->f2_overall_word = - pam->f2_word_syllable = pam->f2_next_word_syllable = pam->f2_current_primary_phrase_word = - pam->g1_current_secondary_phrase_syllable = pam->g1_current_syllable = - pam->g2_current_secondary_phrase_word = pam->g2_current_word = - pam->h1_current_secondary_phrase_syll = pam->h2_current_secondary_phrase_word = - pam->h3_h4_current_secondary_phrase_word = pam->h5_current_phrase_type = - pam->h5_syllable = pam->h5_state = pam->i1_secondary_phrase_syllable = - pam->i1_next_secondary_phrase_syllable = pam->i2_secondary_phrase_word = - pam->i2_next_secondary_phrase_word = pam->j1_utterance_syllable = - pam->j2_utterance_word = pam->j3_utterance_sec_phrases = 0; - /*Override 0 with 1*/ - pam->b4_b5_syllable = pam->b17_b19_syllable = pam->b18_b20_b21_syllable = - pam->e9_e11_word = pam->e10_e12_e13_word = pam->e7_e8_word = - pam->h2_current_secondary_phrase_word = 1; - /*Override 0 with -1*/ - pam->e1_syllable_word_start = pam->e1_syllable_word_end = pam->e2_syllable_word_start = - pam->e2_syllable_word_end = -1; - - return PICO_OK; -}/*pam_reset_processors*/ - -/** - * does the cleanup of the sub object processors flags before the backward step - * @param this : pointer to PAM PU sub object pointer - * @return PICO_OK : reset OK - * @return PICO_ERR_OTHER : errors on getting pam sub obj pointer - * @callgraph - * @callergraph - */ -static pico_status_t pam_reset_processors_back( - register picodata_ProcessingUnit this) -{ - pam_subobj_t *pam; - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - pam = (pam_subobj_t *) this->subObj; - - /*set all to 0*/ - pam->a3_overall_syllable - = pam->a3_primary_phrase_syllable - = pam->b4_b5_syllable - = pam->b6_b7_syllable - = pam->b6_b7_state - = pam->b8_b9_stressed_syllable - = pam->b10_b11_accented_syllable - = pam->b12_b13_syllable - = pam->b12_b13_state - = pam->b14_b15_syllable - = pam->b14_b15_state - = pam->b17_b19_syllable - = pam->b17_b19_state - = pam->b18_b20_b21_syllable - = pam->b18_b20_b21_state - = pam->c3_overall_syllable - = pam->c3_primary_phrase_syllable - = pam->d2_syllable_in_word - = pam->d2_prev_syllable_in_word - = pam->d2_current_primary_phrase_word - = pam->e1_syllable_word_start - = pam->e1_syllable_word_end - = pam->e1_content - = pam->e2_syllable_word_start - = pam->e2_syllable_word_end - = pam->e3_e4_word - = pam->e3_e4_state - = pam->e5_e6_content_word - = pam->e5_e6_content - = pam->e7_e8_word - = pam->e7_e8_content - = pam->e7_e8_state - = pam->e9_e11_word - = pam->e9_e11_saw_word - = pam->e9_e11_state - = pam->e10_e12_e13_word - = pam->e10_e12_e13_state - = pam->e10_e12_e13_saw_word - = pam->f2_overall_word - = pam->f2_word_syllable - = pam->f2_next_word_syllable - = pam->f2_current_primary_phrase_word - = pam->g1_current_secondary_phrase_syllable - = pam->g1_current_syllable - = pam->g2_current_secondary_phrase_word - = pam->g2_current_word - = pam->h1_current_secondary_phrase_syll - = pam->h2_current_secondary_phrase_word - = pam->h3_h4_current_secondary_phrase_word - = pam->h5_current_phrase_type - = pam->h5_state - = pam->i1_secondary_phrase_syllable - = pam->i1_next_secondary_phrase_syllable - = pam->i2_secondary_phrase_word - = pam->i2_next_secondary_phrase_word - = 0; - /*Override 0 with 1*/ - pam->b4_b5_syllable = pam->b17_b19_syllable = pam->b18_b20_b21_syllable - = pam->e9_e11_word = pam->e10_e12_e13_word = pam->e7_e8_word - = pam->h2_current_secondary_phrase_word = 1; - /*Override 0 with -1*/ - pam->e1_syllable_word_start = pam->e1_syllable_word_end - = pam->e2_syllable_word_start = pam->e2_syllable_word_end = -1; - - return PICO_OK; -}/*pam_reset_processors_back*/ - -/** - * processes an input event for a specific feature - * @param this : pointer to PAM PU sub object pointer - * @param nFeat : feature column to process - * @param event_type : event id among syll/boundprim/boundsec/boundword - * @param direction : forward(0)/backward(1) - * @return PICO_OK : process OK - * @return PICO_ERR_OTHER : errors on getting pam sub obj pointer - * @callgraph - * @callergraph - */ -static pico_status_t pam_process_event_feature( - register picodata_ProcessingUnit this, picoos_uint8 nFeat, - picoos_uint8 event_type, picoos_uint8 direction) -{ - picoos_uint8 sDest, nI; - picoos_uint16 syllCurr; - pam_subobj_t *pam; - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - pam = (pam_subobj_t *) this->subObj; - syllCurr = pam->nCurrSyllable; - switch (nFeat) { - case A3: - /*processor for A3*/ - switch (direction) { - case PICOPAM_DIR_FORW: - if (event_type == PICOPAM_EVENT_SYLL) { - if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] - == 1) || (pam->a3_primary_phrase_syllable >= 1)) { - if (pam->a3_overall_syllable < 1) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] - = 0; - else - pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] - = pam->sSyllFeats[pam->nCurrSyllable - - 1].phoneV[B3]; - } else { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] = 0; - } - pam->a3_primary_phrase_syllable++; - pam->a3_overall_syllable++; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->a3_primary_phrase_syllable = 0; - } - break; - case PICOPAM_DIR_BACK: - /*do nothing*/ - break; - } - break; - case B1: - case B2: - case B3: - /*done in createSyllable*/ - break; - case B4:/*processor for B4,B5*/ - switch (direction) { - case PICOPAM_DIR_FORW: - sDest = B4; - break; - case PICOPAM_DIR_BACK: - sDest = B5; - break; - default: - sDest = B4; - break; - } - if (event_type == PICOPAM_EVENT_SYLL) { - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] == 0) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = pam->b4_b5_syllable; - pam->b4_b5_syllable++; - } else { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] = 0; - } - } - if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type - == PICOPAM_EVENT_S_BOUND) || (event_type - == PICOPAM_EVENT_P_BOUND)) { - pam->b4_b5_syllable = 1; - } - break; - case B5:/*processor for B5 : done in B4*/ - break; - case B6:/*processor for B6,B7*/ - switch (direction) { - case PICOPAM_DIR_FORW: - sDest = B6; - break; - case PICOPAM_DIR_BACK: - sDest = B7; - break; - default: - sDest = B6; - break; - } - switch (pam->b6_b7_state) { - case 0: - if (event_type == PICOPAM_EVENT_SYLL) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = PICOPAM_DONT_CARE_VALUE; - if (event_type == PICOPAM_EVENT_S_BOUND) { - pam->b6_b7_syllable = 1; - pam->b6_b7_state = 1; - } - break; - case 1: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = pam->b6_b7_syllable; - pam->b6_b7_syllable++; - } - if (event_type == PICOPAM_EVENT_S_BOUND) { - pam->b6_b7_syllable = 1; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->b6_b7_state = 0; - } - break; - default: - break; - } - break; - case B7:/*Done in B6*/ - break; - case B8:/*processor for B8,B9*/ - switch (direction) { - case PICOPAM_DIR_FORW: - sDest = B8; - break; - case PICOPAM_DIR_BACK: - sDest = B9; - break; - default: - sDest = B8; - break; - } - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = pam->b8_b9_stressed_syllable; - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 1) - pam->b8_b9_stressed_syllable++; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->b8_b9_stressed_syllable = 0; - } - - break; - case B9:/*done in B8*/ - break; - case B10:/*processor for B10, B11*/ - switch (direction) { - case PICOPAM_DIR_FORW: - sDest = B10; - break; - case PICOPAM_DIR_BACK: - sDest = B11; - break; - default: - sDest = B10; - break; - } - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = pam->b10_b11_accented_syllable; - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 1) - pam->b10_b11_accented_syllable++; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->b10_b11_accented_syllable = 0; - } - break; - case B11:/*done in B10*/ - break; - case B12:/*processor for B12,B13*/ - switch (direction) { - case PICOPAM_DIR_FORW: - sDest = B12; - break; - case PICOPAM_DIR_BACK: - sDest = B13; - break; - default: - sDest = B12; - break; - } - switch (pam->b12_b13_state) { - case 0: - if (event_type == PICOPAM_EVENT_SYLL) { - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 0) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = PICOPAM_DONT_CARE_VALUE; - else { - pam->b12_b13_syllable = 0; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = PICOPAM_DONT_CARE_VALUE; - pam->b12_b13_state = 1; - } - } - break; - case 1: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = pam->b12_b13_syllable; - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 1) - pam->b12_b13_syllable = 0; - else - pam->b12_b13_syllable++; - pam->b12_b13_state = 2; - } - if (event_type == PICOPAM_EVENT_P_BOUND) - pam->b12_b13_state = 0; - break; - case 2: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = pam->b12_b13_syllable; - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 1) - pam->b12_b13_syllable = 0; - else - pam->b12_b13_syllable++; - } - if (event_type == PICOPAM_EVENT_P_BOUND) - pam->b12_b13_state = 0; - - break; - default: - break; - } - break; - case B13:/*done in B12*/ - break; - - case B14:/*processor for B14, B15*/ - switch (direction) { - case PICOPAM_DIR_FORW: - sDest = B14; - break; - case PICOPAM_DIR_BACK: - sDest = B15; - break; - default: - sDest = B14; - break; - } - switch (pam->b14_b15_state) { - case 0: - if (event_type == PICOPAM_EVENT_SYLL) { - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 0) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = PICOPAM_DONT_CARE_VALUE; - else { - pam->b14_b15_syllable = 0; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = PICOPAM_DONT_CARE_VALUE; - pam->b14_b15_state = 1; - } - } - break; - case 1: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = pam->b14_b15_syllable; - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 1) - pam->b14_b15_syllable = 0; - else - pam->b14_b15_syllable++; - pam->b14_b15_state = 2; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->b14_b15_state = 0; - } - break; - case 2: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = pam->b14_b15_syllable; - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 1) - pam->b14_b15_syllable = 0; - else - pam->b14_b15_syllable++; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->b14_b15_state = 0; - } - break; - default: - break; - } - break; - case B15:/*Processor for B15 : done in B14*/ - break; - case B16:/*done in createSyllable*/ - break; - case B17:/*processor for B17, B19 unified */ - switch (direction) { - case PICOPAM_DIR_FORW: - switch (pam->b17_b19_state) { - case 0: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17] - = PICOPAM_DONT_CARE_VALUE; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19] - = pam->b17_b19_syllable; - pam->b17_b19_syllable++; - } - if (((event_type == PICOPAM_EVENT_P_BOUND) - || (event_type == PICOPAM_EVENT_S_BOUND)) - && (pam->b17_b19_syllable > 1)) { - if (event_type == PICOPAM_EVENT_P_BOUND) - pam->b17_b19_syllable = 1; - pam->b17_b19_state = 1; - } - break; - case 1: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17] - = pam->b17_b19_syllable; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19] - = PICOPAM_DONT_CARE_VALUE; - pam->b17_b19_syllable++; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->b17_b19_syllable = 1; - } - break; - default: - break; - } - break; - case PICOPAM_DIR_BACK: - /*do nothing*/ - break; - } - break; - case B18:/*processor for B18, B20, B21 unfied*/ - switch (direction) { - case PICOPAM_DIR_FORW:/*do nothing*/ - break; - case PICOPAM_DIR_BACK: - switch (pam->b18_b20_b21_state) { - case 0: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B18] - = PICOPAM_DONT_CARE_VALUE; - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] - == PICOPAM_DECLARATIVE) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] - = pam->b18_b20_b21_syllable; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] - = PICOPAM_DONT_CARE_VALUE; - } else { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] - = PICOPAM_DONT_CARE_VALUE; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] - = pam->b18_b20_b21_syllable; - } - pam->b18_b20_b21_syllable++; - } - if (((event_type == PICOPAM_EVENT_P_BOUND) - || (event_type == PICOPAM_EVENT_S_BOUND)) - && (pam->b18_b20_b21_syllable > 1)) { - if (event_type == PICOPAM_EVENT_P_BOUND) - pam->b18_b20_b21_syllable = 1; - pam->b18_b20_b21_state = 1; - } - break; - case 1: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B18] - = pam->b18_b20_b21_syllable; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] - = PICOPAM_DONT_CARE_VALUE; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] - = PICOPAM_DONT_CARE_VALUE; - pam->b18_b20_b21_syllable++; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->b18_b20_b21_syllable = 1; - } - break; - default: - break; - } - break; - } - break; - case B19:/*processor for B19 : done in B17*/ - break; - case B20:/*processor for B20 : done in B18*/ - break; - case B21:/*processor for B21 : done in B18*/ - break; - case C3:/*processor for C3*/ - switch (direction) { - case PICOPAM_DIR_FORW: - /*do nothing*/ - break; - case PICOPAM_DIR_BACK: - if (event_type == PICOPAM_EVENT_SYLL) { - if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] - == 1) || (pam->c3_primary_phrase_syllable >= 1)) { - if (pam->c3_overall_syllable < 1) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] - = 0; - else - pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] - = pam->sSyllFeats[pam->nCurrSyllable - + 1].phoneV[B3]; - } else { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] = 0; - } - pam->c3_primary_phrase_syllable++; - pam->c3_overall_syllable++; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->c3_primary_phrase_syllable = 0; - } - break; - } - break; - case D2:/*processor for D2*/ - switch (direction) { - case PICOPAM_DIR_FORW: - if (event_type == PICOPAM_EVENT_SYLL) { - if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] - == 1) || (pam->d2_current_primary_phrase_word - >= 1)) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[D2] - = pam->d2_prev_syllable_in_word; - else - pam->sSyllFeats[pam->nCurrSyllable].phoneV[D2] = 0; - - pam->d2_syllable_in_word++; - } - if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type - == PICOPAM_EVENT_S_BOUND) || (event_type - == PICOPAM_EVENT_P_BOUND)) { - pam->d2_current_primary_phrase_word = 1; - pam->d2_prev_syllable_in_word - = pam->d2_syllable_in_word; - pam->d2_syllable_in_word = 0; - /*pam->d2_current_primary_phrase_word++;*/ - } - if ((event_type == PICOPAM_EVENT_P_BOUND)) { - pam->d2_current_primary_phrase_word = 0; - } - break; - case PICOPAM_DIR_BACK: - /*do nothing*/ - break; - } - break; - case E1:/*processor for E1*/ - switch (direction) { - case PICOPAM_DIR_FORW: /*remember : content syllable indicator already on P5*/ - if (event_type == PICOPAM_EVENT_SYLL) { - if (pam->e1_syllable_word_start == -1) - pam->e1_syllable_word_start - = (picoos_int8) pam->nCurrSyllable; - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1) - pam->e1_content = 1; - pam->e1_syllable_word_end - = (picoos_int8) pam->nCurrSyllable; - } - if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type - == PICOPAM_EVENT_S_BOUND) || (event_type - == PICOPAM_EVENT_P_BOUND)) { - if ((pam->e1_syllable_word_start != -1) - && (pam->e1_syllable_word_end != -1)) { - for (nI = pam->e1_syllable_word_start; nI - <= pam->e1_syllable_word_end; nI++) - pam->sSyllFeats[nI].phoneV[E1] - = pam->e1_content; - } - pam->e1_content = 0; - pam->e1_syllable_word_start = -1; - pam->e1_syllable_word_end = -1; - } - break; - case PICOPAM_DIR_BACK: - /*do nothing*/ - break; - } - break; - case E2:/*processor for E2*/ - switch (direction) { - case PICOPAM_DIR_FORW: - if (event_type == PICOPAM_EVENT_SYLL) { - if (pam->e2_syllable_word_start == -1) - pam->e2_syllable_word_start - = (picoos_int8) pam->nCurrSyllable; - pam->e2_syllable_word_end - = (picoos_int8) pam->nCurrSyllable; - } - if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type - == PICOPAM_EVENT_S_BOUND) || (event_type - == PICOPAM_EVENT_P_BOUND)) { - if ((pam->e2_syllable_word_start != -1) - && (pam->e2_syllable_word_end != -1)) { - for (nI = pam->e2_syllable_word_start; nI - <= pam->e2_syllable_word_end; nI++) - pam->sSyllFeats[nI].phoneV[E2] - = pam->e2_syllable_word_end - - pam->e2_syllable_word_start - + 1; - } - pam->e1_content = 0; - pam->e2_syllable_word_start = -1; - pam->e2_syllable_word_end = -1; - } - break; - case PICOPAM_DIR_BACK: - break; - } - break; - case E3:/*processor for E3,E4*/ - switch (direction) { - case PICOPAM_DIR_FORW: - sDest = E3; - break; - case PICOPAM_DIR_BACK: - sDest = E4; - break; - default: - sDest = E3; - break; - } - switch (pam->e3_e4_state) { - case 0: - if (event_type == PICOPAM_EVENT_SYLL) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = PICOPAM_DONT_CARE_VALUE; - if (event_type == PICOPAM_EVENT_S_BOUND) { - pam->e3_e4_word = 1; - pam->e3_e4_state = 1; - } - break; - case 1: - if (event_type == PICOPAM_EVENT_SYLL) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = pam->e3_e4_word; - if (event_type == PICOPAM_EVENT_S_BOUND) - pam->e3_e4_word = 1; - if (event_type == PICOPAM_EVENT_W_BOUND) - pam->e3_e4_word++; - if (event_type == PICOPAM_EVENT_P_BOUND) - pam->e3_e4_state = 0; - break; - default: - break; - } - break; - case E4:/*processor for E4 : done in E3*/ - break; - case E5:/*processor for E5,E6*/ - switch (direction) { - case PICOPAM_DIR_FORW: - sDest = E5; - break; - case PICOPAM_DIR_BACK: - sDest = E6; - break; - default: - sDest = E5; - break; - } - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = pam->e5_e6_content_word; - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1) - pam->e5_e6_content = 1; - } - if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type - == PICOPAM_EVENT_S_BOUND) || (event_type - == PICOPAM_EVENT_P_BOUND)) { - if (pam->e5_e6_content == 1) - pam->e5_e6_content_word++; - pam->e5_e6_content = 0; - if (event_type == PICOPAM_EVENT_P_BOUND) - pam->e5_e6_content_word = 0; - } - break; - case E6:/*processor for E6 : done in E5*/ - break; - case E7:/*processor for E7,E8*/ - switch (direction) { - case PICOPAM_DIR_FORW: - sDest = E7; - break; - case PICOPAM_DIR_BACK: - sDest = E8; - break; - default: - sDest = E7; - break; - } - switch (pam->e7_e8_state) { - case 0: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = PICOPAM_DONT_CARE_VALUE; - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1) - pam->e7_e8_content = 1; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->e7_e8_content = 0; - } - - if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type - == PICOPAM_EVENT_S_BOUND)) { - if (pam->e7_e8_content == 1) { - pam->e7_e8_word = 0; - pam->e7_e8_content = 0; - pam->e7_e8_state = 1; - } - } - break; - case 1: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = pam->e7_e8_word; - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1) - pam->e7_e8_content = 1; - } - if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type - == PICOPAM_EVENT_S_BOUND)) { - if (pam->e7_e8_content == 1) { - pam->e7_e8_word = 0; - pam->e7_e8_content = 0; - } else { - pam->e7_e8_word++; - } - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->e7_e8_state = 0; - pam->e7_e8_content = 0; /*<<<<<< added */ - } - - default: - break; - } - break; - case E8:/*processor for E8 : done in E7*/ - break; - case E9: - /*processor for E9, E11*/ - switch (direction) { - case PICOPAM_DIR_FORW: - switch (pam->e9_e11_state) { - case 0: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9] - = PICOPAM_DONT_CARE_VALUE; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11] - = pam->e9_e11_word; - pam->e9_e11_saw_word = 1; /*new variable, needs to be initialized to 0*/ - } - if (event_type == PICOPAM_EVENT_W_BOUND) - pam->e9_e11_word++; - if (((event_type == PICOPAM_EVENT_P_BOUND) - || (event_type == PICOPAM_EVENT_S_BOUND)) - && (pam->e9_e11_saw_word == 1)) { /* modified*/ - if (event_type == PICOPAM_EVENT_P_BOUND) - pam->e9_e11_word = 1; - else - pam->e9_e11_word++; /*modified*/ - pam->e9_e11_state = 1; - } - break; - case 1: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9] - = pam->e9_e11_word; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11] - = PICOPAM_DONT_CARE_VALUE; - } - if ((event_type == PICOPAM_EVENT_W_BOUND) - || (event_type == PICOPAM_EVENT_S_BOUND)) - pam->e9_e11_word++; - if (event_type == PICOPAM_EVENT_P_BOUND) - pam->e9_e11_word = 1; - break; - default: - break; - } - break; - case PICOPAM_DIR_BACK: - /*do nothing*/ - break; - } - break; - case E10:/*processor for E10, E12, E13 unified*/ - switch (direction) { - case PICOPAM_DIR_FORW:/*do nothing*/ - break; - case PICOPAM_DIR_BACK: - switch (pam->e10_e12_e13_state) { - case 0: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E10] - = PICOPAM_DONT_CARE_VALUE; - pam->e10_e12_e13_saw_word = 1; - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] - == PICOPAM_DECLARATIVE) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] - = pam->e10_e12_e13_word; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] - = PICOPAM_DONT_CARE_VALUE; - } else { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] - = PICOPAM_DONT_CARE_VALUE; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] - = pam->e10_e12_e13_word; - } - } - if (event_type == PICOPAM_EVENT_W_BOUND) - pam->e10_e12_e13_word++; - - /*if (((event_type==PICOPAM_EVENT_P_BOUND)||(event_type==PICOPAM_EVENT_S_BOUND))&&(pam->e10_e12_e13_word>1)) {*/ - if (((event_type == PICOPAM_EVENT_P_BOUND) - || (event_type == PICOPAM_EVENT_S_BOUND)) - && (pam->e10_e12_e13_saw_word > 0)) { - if (event_type == PICOPAM_EVENT_P_BOUND) - pam->e10_e12_e13_word = 1; - else - pam->e10_e12_e13_word++; - pam->e10_e12_e13_state = 1; - } - break; - case 1: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E10] - = pam->e10_e12_e13_word; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] - = PICOPAM_DONT_CARE_VALUE; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] - = PICOPAM_DONT_CARE_VALUE; - } - if ((event_type == PICOPAM_EVENT_W_BOUND) - || (event_type == PICOPAM_EVENT_S_BOUND)) - pam->e10_e12_e13_word++; - if (event_type == PICOPAM_EVENT_P_BOUND) - pam->e10_e12_e13_word = 1; - break; - default: - break; - } - break; - } - break; - - case E11:/*processor for E11 : done in E9*/ - break; - case E12:/*processor for E12 : done in E10*/ - break; - case E13:/*processor for E13 : done in E10*/ - break; - - case F2: - switch (direction) { - case PICOPAM_DIR_FORW:/*do nothing*/ - break; - case PICOPAM_DIR_BACK: - if (event_type == PICOPAM_EVENT_SYLL) { - if (pam->f2_current_primary_phrase_word >= 1)/*at least second word in current primary phrase*/ - pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2] - = pam->f2_next_word_syllable; - else - /*first word in current primary phrase*/ - pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2] = 0; - pam->f2_word_syllable++; - } - if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type - == PICOPAM_EVENT_S_BOUND) || (event_type - == PICOPAM_EVENT_P_BOUND)) {/*word - end : switch*/ - pam->f2_next_word_syllable = pam->f2_word_syllable; - pam->f2_word_syllable = 0; - } - if (event_type == PICOPAM_EVENT_P_BOUND)/*mark first word in current primary phrase*/ - pam->f2_current_primary_phrase_word = 0; - else /*mark next word in current primary phrase(enables output in PICOPAM_EVENT_SYLL)*/ - if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type - == PICOPAM_EVENT_S_BOUND)) - pam->f2_current_primary_phrase_word++; - break; - } - break; - case G1: - switch (direction) { - case PICOPAM_DIR_FORW: - if (event_type == PICOPAM_EVENT_SYLL) { - if (pam->g1_current_secondary_phrase_syllable > 0) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[G1] - = pam->g1_current_secondary_phrase_syllable; - else - pam->sSyllFeats[pam->nCurrSyllable].phoneV[G1] = 0; - pam->g1_current_syllable++; - } - if (event_type == PICOPAM_EVENT_S_BOUND) { - pam->g1_current_secondary_phrase_syllable - = pam->g1_current_syllable; - pam->g1_current_syllable = 0; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->g1_current_secondary_phrase_syllable = 0; - pam->g1_current_syllable = 0; - } - case PICOPAM_DIR_BACK: /*do nothing*/ - break; - } - break; - case G2: - switch (direction) { - case PICOPAM_DIR_FORW: - if (event_type == PICOPAM_EVENT_SYLL) { - if (pam->g2_current_secondary_phrase_word > 0) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[G2] - = pam->g2_current_secondary_phrase_word; - else - pam->sSyllFeats[pam->nCurrSyllable].phoneV[G2] = 0; - } - if (event_type == PICOPAM_EVENT_W_BOUND) - pam->g2_current_word++; - - if (event_type == PICOPAM_EVENT_S_BOUND) { - pam->g2_current_secondary_phrase_word - = pam->g2_current_word + 1; - pam->g2_current_word = 0; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->g2_current_secondary_phrase_word = 0; - pam->g2_current_word = 0; - } - break; - case PICOPAM_DIR_BACK: /*do nothing*/ - break; - } - break; - case H1: - switch (direction) { - case PICOPAM_DIR_FORW: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->h1_current_secondary_phrase_syll++; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1] - = pam->h1_current_secondary_phrase_syll; - } - if ((event_type == PICOPAM_EVENT_S_BOUND) || (event_type - == PICOPAM_EVENT_P_BOUND)) - pam->h1_current_secondary_phrase_syll = 0; - break; - case PICOPAM_DIR_BACK: - if (event_type == PICOPAM_EVENT_SYLL) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1] - = pam->h1_current_secondary_phrase_syll; - if (event_type == PICOPAM_EVENT_S_BOUND) - pam->h1_current_secondary_phrase_syll - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1]; - if (event_type == PICOPAM_EVENT_P_BOUND) - pam->h1_current_secondary_phrase_syll - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H1]; - break; - } - break; - case H2: - switch (direction) { - case PICOPAM_DIR_FORW: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] - = pam->h2_current_secondary_phrase_word; - } - if (event_type == PICOPAM_EVENT_W_BOUND) { - pam->h2_current_secondary_phrase_word++; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] - = pam->h2_current_secondary_phrase_word; - } - if (event_type == PICOPAM_EVENT_S_BOUND) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] - = pam->h2_current_secondary_phrase_word + 1; - pam->h2_current_secondary_phrase_word = 0; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - if (pam->nCurrSyllable > 1) - pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2] - = pam->h2_current_secondary_phrase_word + 1; - pam->h2_current_secondary_phrase_word = 0; - } - break; - case PICOPAM_DIR_BACK: - if (event_type == PICOPAM_EVENT_SYLL) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] - = pam->h2_current_secondary_phrase_word; - if (event_type == PICOPAM_EVENT_S_BOUND) - pam->h2_current_secondary_phrase_word - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2]; - if (event_type == PICOPAM_EVENT_P_BOUND) - pam->h2_current_secondary_phrase_word - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2]; - break; - } - break; - case H3:/*processor for H3,H4 unified */ - switch (direction) { - case PICOPAM_DIR_FORW: - sDest = H3; - break; - case PICOPAM_DIR_BACK: - sDest = H4; - break; - default: - sDest = H3; - break; - } - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] - = pam->h3_h4_current_secondary_phrase_word; - } - if ((event_type == PICOPAM_EVENT_S_BOUND) || (event_type - == PICOPAM_EVENT_P_BOUND)) - pam->h3_h4_current_secondary_phrase_word++; - break; - case H4: /*processor for H4 : already in H3*/ - break; - - case H5:/*processor for H5*/ - switch (direction) { - case PICOPAM_DIR_FORW: - break; - case PICOPAM_DIR_BACK: - switch (pam->h5_state) { - case 0: - if (event_type == PICOPAM_EVENT_SYLL) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5]; - if (event_type == PICOPAM_EVENT_S_BOUND) { - pam->h5_state = 1; - } - break; - case 1: - if (event_type == PICOPAM_EVENT_SYLL) { - if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] - == PICOPAM_P) - && (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] - == 0)) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] - = PICOPAM_p; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->h5_state = 0; - } - break; - default: - break; - } - break; - - default: - break; - } - break; - - case I1:/*processor for I1*/ - switch (direction) { - case PICOPAM_DIR_FORW: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->i1_secondary_phrase_syllable++; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1] - = pam->i1_secondary_phrase_syllable; - } - if ((event_type == PICOPAM_EVENT_S_BOUND) || (event_type - == PICOPAM_EVENT_P_BOUND)) - pam->i1_secondary_phrase_syllable = 0; - break; - case PICOPAM_DIR_BACK: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1] - = pam->i1_next_secondary_phrase_syllable; - } - if (event_type == PICOPAM_EVENT_S_BOUND) { - pam->i1_next_secondary_phrase_syllable - = pam->i1_secondary_phrase_syllable; - pam->i1_secondary_phrase_syllable - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1]; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->i1_next_secondary_phrase_syllable = 0; - pam->i1_secondary_phrase_syllable - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[I1]; - } - break; - } - break; - case I2: /*processor for I2*/ - switch (direction) { - case PICOPAM_DIR_FORW: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2] - = pam->i2_secondary_phrase_word; - } - if (event_type == PICOPAM_EVENT_W_BOUND) - pam->i2_secondary_phrase_word++; - - if ((event_type == PICOPAM_EVENT_P_BOUND) || (event_type - == PICOPAM_EVENT_S_BOUND)) - pam->i2_secondary_phrase_word = 1; - - break; - case PICOPAM_DIR_BACK: - if (event_type == PICOPAM_EVENT_SYLL) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2] - = pam->i2_next_secondary_phrase_word; - } - if (event_type == PICOPAM_EVENT_S_BOUND) { - pam->i2_next_secondary_phrase_word - = pam->i2_secondary_phrase_word; - pam->i2_secondary_phrase_word - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2]; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->i2_next_secondary_phrase_word = 0; - pam->i2_secondary_phrase_word - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[I2]; - } - break; - } - break; - case J1: /*processor for J1 */ - switch (direction) { - case PICOPAM_DIR_FORW: - if (event_type == PICOPAM_EVENT_SYLL) { - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] != 1) - pam->j1_utterance_syllable++; - } - break; - case PICOPAM_DIR_BACK: - pam->sSyllFeats[pam->nCurrSyllable].phoneV[J1] - = pam->j1_utterance_syllable; - break; - } - break; - case J2: /*processor for J2*/ - switch (direction) { - case PICOPAM_DIR_FORW: - if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type - == PICOPAM_EVENT_S_BOUND) || (event_type - == PICOPAM_EVENT_P_BOUND)) - pam->j2_utterance_word++; - break; - case PICOPAM_DIR_BACK: - pam->sSyllFeats[pam->nCurrSyllable].phoneV[J2] - = pam->j2_utterance_word - 1; - break; - } - break; - case J3: /*processor for J3*/ - switch (direction) { - case PICOPAM_DIR_FORW: - if (event_type == PICOPAM_EVENT_S_BOUND) { - pam->j3_utterance_sec_phrases++; - break; - } - if (event_type == PICOPAM_EVENT_P_BOUND) { - pam->j3_utterance_sec_phrases++; - break; - } - break; - case PICOPAM_DIR_BACK: - pam->sSyllFeats[pam->nCurrSyllable].phoneV[J3] - = pam->j3_utterance_sec_phrases - 1; - break; - } - break; - } - return PICO_OK; -}/*pam_process_event_feature*/ - -/** - * processes an input event spanning it to all column features - * @param this : pointer to PAM PU sub object pointer - * @param event_type : event id among syll/boundprim/boundsec/boundword - * @param direction : forward(0)/backward(1) - * @return PICO_OK : process OK - * @return PICO_ERR_OTHER : errors on getting pam sub obj pointer - * @callgraph - * @callergraph - */ -static pico_status_t pam_process_event(register picodata_ProcessingUnit this, - picoos_uint8 event_type, picoos_uint8 direction) -{ - picoos_uint8 nFeat; - pico_status_t nResult; - - pam_subobj_t *pam; - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - pam = (pam_subobj_t *) this->subObj; - - if (direction == PICOPAM_DIR_FORW) { - if (event_type == PICOPAM_EVENT_P_BOUND) - /*primary boundary*/ - pam->sSyllFeats[pam->nCurrSyllable].phoneV[P2] = 1; - if (event_type == PICOPAM_EVENT_S_BOUND) - /*secondary boundary*/ - pam->sSyllFeats[pam->nCurrSyllable].phoneV[P3] = 1; - if (event_type == PICOPAM_EVENT_W_BOUND) - /*word boundary*/ - pam->sSyllFeats[pam->nCurrSyllable].phoneV[P4] = 1; - } - for (nFeat = A3; nFeat <= J3; nFeat++) { - nResult = pam_process_event_feature(this, nFeat, event_type, direction); - if (nResult != PICO_OK) - return nResult; - } - return PICO_OK; -}/*pam_process_event*/ - -/** - * inserts a syllable inside the subobj sentence data struct. - * @param this : pointer to PAM PU sub object pointer - * @param syllType : the syllable type (pause/syllable) - * @param sContent : the item content - * @param sentType : the sentence type - * @param phType : the phrase type - * @param uBoundType : the boundary type (only for silence syllables) - * @param uMinDur, uMaxDur : the mimimum and maximum duration (only for silence syllables) - * @return PICO_OK : syllable creation successful - * @return PICO_ERR_OTHER : errors in one internal function (check_phones_size..) - * @callgraph - * @callergraph - */ -static pico_status_t pam_create_syllable(register picodata_ProcessingUnit this, - picoos_uint8 syllType, picoos_uint8 *sContent, picoos_uint8 sentType, - picoos_uint8 phType, picoos_uint8 uBoundType, picoos_uint16 uMinDur, - picoos_uint16 uMaxDur) -{ - pam_subobj_t *pam; - picoos_uint8 nI; - picoos_uint8 pos; - /* picoos_uint8 *npUi16; */ - picoos_uint32 pos32; - - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - pam = (pam_subobj_t *) this->subObj; - pos = 0; - /*check buffer full condition on number of syllables*/ - if (check_syllables_size(pam, 1) != PICO_OK) { - return PICO_ERR_OTHER; - } - - if (syllType == PICOPAM_SYLL_PAUSE) { - /*check buffer full condition on number of phonemes*/ - if (check_phones_size(pam, 1) != PICO_OK) { - return PICO_ERR_OTHER; - } - } - if (syllType == PICOPAM_SYLL_SYLL) { - /*check item availability*/ - if (sContent == NULL) { - return PICO_ERR_OTHER; - } - /*check buffer full condition on number of phonemes*/ - if (check_phones_size(pam, sContent[3]) != PICO_OK) { - return PICO_ERR_OTHER; - } - } - - /*open new syllable*/ - pam->nCurrSyllable = pam->nCurrSyllable + 1; - /*cleanup*/ - for (nI = 0; nI < PICOPAM_VECT_SIZE; nI++) { - if (pam->nCurrSyllable > 0) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] = 0; - } else { - if ((nI >= ITM) && (nI <= itm)) { - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] > 0) { - /*do not cleanup "attached item offset" fields (ITM, itm): - an already existing attached item could be lost*/ - } else { - /*cleanup "attached item offset"*/ - pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] = 0; - } - } else { - /*cleanup all fields except "attached item offset" (ITM, itm)*/ - pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] = 0; - } - } - } - /*set minimum and maximum duration values*/ - if ((uMinDur == 0) && (uMaxDur == 0) && (syllType == PICOPAM_SYLL_PAUSE)) { - /*both 0 : use default duration limits for boundaries*/ - get_default_boundary_limit(uBoundType, &uMinDur, &uMaxDur); - } - if (uMinDur > 0) { - pos32 = Min; - picoos_write_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV, - &pos32, uMinDur); - } - if (uMaxDur > 0) { - pos32 = Max; - picoos_write_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV, - &pos32, uMaxDur); - } - /*END OF BREAK COMMAND SUPPORT*/ - - if (syllType == PICOPAM_SYLL_PAUSE) { - /*initialize a pause syllable*/ - if (sentType == PICOPAM_DECLARATIVE) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] - = PICOPAM_DECLARATIVE; - if (sentType == PICOPAM_INTERROGATIVE) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] - = PICOPAM_INTERROGATIVE; - - pam->sSyllFeats[pam->nCurrSyllable].phoneV[bnd] = uBoundType; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] = 1; /*this means the syllable contains a pause-silence*/ - pam->sSyllFeats[pam->nCurrSyllable].phoneV[P8] = 1; - - /*b1,b2,b9,b11,b13,b15,e1,e6,e8,e10 already set to 0*/ - - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B4] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B5] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B6] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B7] - = 1; - - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B16] - = PICOPAM_PH_DONT_CARE_VAL; /*name of the vowel in the syllable = NONE */ - - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E2] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E3] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E4] = 1; - - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] = phType; - - /*Store current phonetic codes in input phonetic string*/ - pam->sPhIds[pam->nCurrPhoneme] = pam_get_pause_id(this); - picoos_mem_copy((void*) &pam->nCurrPhoneme, - &(pam->sSyllFeats[pam->nCurrSyllable].phoneV[FID]), - sizeof(pam->nCurrPhoneme)); - pam->nCurrPhoneme++; - pam->nTotalPhonemes++; - /*add 1 to total number of syllables*/ - pam->nTotalSyllables++; - - return PICO_OK; - } - if (syllType == PICOPAM_SYLL_SYLL) { - /*initialize a real syllable*/ - if (sContent[2] > PICODATA_ACC0) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] = 1; /*set content syllable indicator*/ - if (sentType == PICOPAM_DECLARATIVE) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] - = PICOPAM_DECLARATIVE; - if (sentType == PICOPAM_INTERROGATIVE) - pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] - = PICOPAM_INTERROGATIVE; - - if ((sContent[2] >= PICODATA_ACC1) && (sContent[2] <= PICODATA_ACC4)) - /*stressed*/ - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] = 1; - - if ((sContent[2] >= PICODATA_ACC1) && (sContent[2] <= PICODATA_ACC2)) - /*accented*/ - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] = 1; - - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] = sContent[3];/*len*/ - - if (pam->nCurrSyllable > 30) - pam->nCurrSyllable = pam->nCurrSyllable; - - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B16] = pam_get_vowel_name(this, - sContent, &pos); /*name of the vowel in the syllable*/ - - pam->sSyllFeats[pam->nCurrSyllable].phoneV[P8] = pos; /*temp for storing the position of the vowel*/ - - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] = phType; - - /*Store current phonetic codes in input phonetic string*/ - picoos_mem_copy((void*) &pam->nCurrPhoneme, - &(pam->sSyllFeats[pam->nCurrSyllable].phoneV[FID]), - sizeof(pam->nCurrPhoneme)); - for (nI = 0; nI < sContent[3]; nI++) - pam->sPhIds[pam->nCurrPhoneme + nI] = sContent[4 + nI]; - pam->nCurrPhoneme += nI; - pam->nTotalPhonemes += nI; - /*add 1 to total number of syllables*/ - pam->nTotalSyllables++; - return PICO_OK; - } - /*if no SyllType has been identified -->> error*/ - return PICO_ERR_OTHER; -}/*pam_create_syllable*/ - -/** - * performs the forward step of the PAM adapter - * @param this : pointer to PAM PU sub object pointer - * @param itemBase : pointer to current item - * @return PICOPAM_READY : forward step ok, the sentence is complete - * @return PICOPAM_MORE : forward step ok, but more data needed to complete the sentence - * @return PICO_ERR_OTHER : errors in one internal function (CreateSyllable..) - * @callgraph - * @callergraph - */ -static pico_status_t pam_adapter_forward_step( - register picodata_ProcessingUnit this, picoos_uint8 *itemBase) -{ - register pam_subobj_t * pam; - pico_status_t sResult; - picoos_uint16 uMinDur, uMaxDur; - picoos_uint32 nPos; - - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - pam = (pam_subobj_t *) this->subObj; - uMinDur = uMaxDur = 0; /*default 0 : not initialized*/ - switch (itemBase[0]) { - case PICODATA_ITEM_BOUND: - /*received a boundary item*/ - switch (itemBase[1]) { - case PICODATA_ITEMINFO1_BOUND_SBEG: - case PICODATA_ITEMINFO1_BOUND_PHR1: -#ifdef PAM_PHR2_WITH_PR1 - case PICODATA_ITEMINFO1_BOUND_PHR2: -#endif - case PICODATA_ITEMINFO1_BOUND_SEND: - case PICODATA_ITEMINFO1_BOUND_TERM: - if (itemBase[3] == 2 * sizeof(picoos_uint16)) { - /*only when the item len duration is equal to 2 int16 --> get the values*/ - nPos = 4; - picoos_read_mem_pi_uint16(itemBase, &nPos, &uMinDur); - picoos_read_mem_pi_uint16(itemBase, &nPos, &uMaxDur); - } - break; - default: - break; - } - switch (itemBase[1]) { - case PICODATA_ITEMINFO1_BOUND_SBEG: - /* received a sentence init boundary */ - pam_reset_processors(this); /*reset all processor variables*/ - pam->sType - = pam_map_sentence_type(itemBase[1], itemBase[2]); - pam->pType = pam_map_phrase_type(itemBase[1], itemBase[2]); - /*create silence syll and process P_BOUND event*/ - sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, - pam->sType, pam->pType, itemBase[1], uMinDur, - uMaxDur); - if (sResult != PICO_OK) - return sResult; - sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, - PICOPAM_DIR_FORW); - if (sResult != PICO_OK) - return sResult; - return PICOPAM_MORE; - break; - - case PICODATA_ITEMINFO1_BOUND_PHR1: -#ifdef PAM_PHR2_WITH_PR1 - case PICODATA_ITEMINFO1_BOUND_PHR2: -#endif - /*received a primary boundary*/ - pam->sType - = pam_map_sentence_type(itemBase[1], itemBase[2]); - pam->pType = pam_map_phrase_type(itemBase[1], itemBase[2]); - /*create silence syll and process P_BOUND event*/ - sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, - pam->sType, pam->pType, itemBase[1], uMinDur, - uMaxDur); - if (sResult != PICO_OK) - return sResult; - sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, - PICOPAM_DIR_FORW); - if (sResult != PICO_OK) - return sResult; - return PICOPAM_MORE; - break; - -#ifdef PAM_PHR2_WITH_PR3 - case PICODATA_ITEMINFO1_BOUND_PHR2 : -#endif - case PICODATA_ITEMINFO1_BOUND_PHR3: - /*received a secondary boundary*/ - /*process S_BOUND event*/ - sResult = pam_process_event(this, PICOPAM_EVENT_S_BOUND, - PICOPAM_DIR_FORW); - /*determine new sentence and Phrase types for following syllables*/ - pam->sType - = pam_map_sentence_type(itemBase[1], itemBase[2]); - pam->pType = pam_map_phrase_type(itemBase[1], itemBase[2]); - if (sResult != PICO_OK) - return sResult; - return PICOPAM_MORE; - break; - - case PICODATA_ITEMINFO1_BOUND_PHR0: - /*received a word end boundary*/ - /*process W_BOUND event*/ - sResult = pam_process_event(this, PICOPAM_EVENT_W_BOUND, - PICOPAM_DIR_FORW); - if (sResult != PICO_OK) - return sResult; - return PICOPAM_MORE; - break; - - case PICODATA_ITEMINFO1_BOUND_SEND: - /*received a SEND boundary*/ - /*insert a new silence syllable and process P_BOUND event*/ - /*create silence syll and process P_BOUND event*/ - sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, - pam->sType, pam->pType, itemBase[1], uMinDur, - uMaxDur); - if (sResult != PICO_OK) - return sResult; - sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, - PICOPAM_DIR_FORW); - if (sResult != PICO_OK) - return sResult; - return PICOPAM_READY; - break; - - case PICODATA_ITEMINFO1_BOUND_TERM: - /* received a flush boundary*/ - if (pam->nCurrSyllable == -1) { - return PICOPAM_NA; - } - /*insert a new silence syllable and process P_BOUND event*/ - /*create silence syll and process P_BOUND event*/ - sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, - pam->sType, pam->pType, itemBase[1], uMinDur, - uMaxDur); - if (sResult != PICO_OK) - return sResult; - sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, - PICOPAM_DIR_FORW); - if (sResult != PICO_OK) - return sResult; - return PICOPAM_READY; - break; - - default: - /*boundary type not known*/ - return PICOPAM_NA; - break; - }/*end switch (itemBase[1])*/ - break; /*end case PICODATA_ITEM_BOUND*/ - - case PICODATA_ITEM_SYLLPHON: - /*received a syllable item*/ - /* ------------------------------------------------------------------ - following code has to be used if we do expect - SYLL items arrive even without SBEG items starting the sentence. - this may happen after a term has been issued to make room in local storage. - */ - if (pam->nCurrSyllable == -1) { - pam_reset_processors(this); - /*insert an SBEG with sType and pType taken from previous sentence*/ - sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, - pam->sType, pam->pType, PICODATA_ITEMINFO1_BOUND_SBEG, - 0, 0); - if (sResult != PICO_OK) - return sResult; - sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, - PICOPAM_DIR_FORW); - if (sResult != PICO_OK) - return sResult; - } - /* ------------------------------------------------------------------*/ - sResult = pam_create_syllable(this, PICOPAM_SYLL_SYLL, itemBase, - pam->sType, pam->pType, 0, 0, 0); - if (sResult != PICO_OK) - return sResult; - sResult = pam_process_event(this, PICOPAM_EVENT_SYLL, - PICOPAM_DIR_FORW); - if (sResult != PICO_OK) - return sResult; - return PICOPAM_MORE; - break; - - default: - return PICOPAM_NA; - break; - } - return PICO_ERR_OTHER; -}/*pam_adapter_forward_step*/ - -/** - * performs the backward step of the PAM adapter - * @param this : pointer to PAM PU sub object pointer - * @return PICO_OK : backward step complete - * @return PICO_ERR_OTHER : errors on retrieving the PU pointer - * @remarks derived in some parts from the pam forward code - * @callgraph - * @callergraph - */ -static pico_status_t pam_adapter_backward_step( - register picodata_ProcessingUnit this) -{ - register pam_subobj_t * pam; - picoos_uint8 nProcessed; - picoos_uint16 nSyll; - - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - pam = (pam_subobj_t *) this->subObj; - - /*Resets the processors for the backward step*/ - pam_reset_processors_back(this); - /*Do the backward step*/ - nSyll = pam->nCurrSyllable; - while (pam->nCurrSyllable >= 0) { - nProcessed = 0; - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P2] == 1) { - /*primary boundary*/ - pam_process_event(this, PICOPAM_EVENT_P_BOUND, PICOPAM_DIR_BACK); - pam->nCurrSyllable--; - nProcessed = 1; - } - if ((nProcessed == 0) - && (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P3] == 1)) { - /*secondary boundary*/ - pam_process_event(this, PICOPAM_EVENT_S_BOUND, PICOPAM_DIR_BACK); - pam_process_event(this, PICOPAM_EVENT_SYLL, PICOPAM_DIR_BACK); - pam->nCurrSyllable--; - nProcessed = 1; - } - if ((nProcessed == 0) - && (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P4] == 1)) { - /*word boundary*/ - pam_process_event(this, PICOPAM_EVENT_W_BOUND, PICOPAM_DIR_BACK); - pam_process_event(this, PICOPAM_EVENT_SYLL, PICOPAM_DIR_BACK); - pam->nCurrSyllable--; - nProcessed = 1; - } - if (nProcessed == 0) { - /*non boundaried syllable*/ - pam_process_event(this, PICOPAM_EVENT_SYLL, PICOPAM_DIR_BACK); - pam->nCurrSyllable--; - nProcessed = 0; - } - }/*end while (pam->nCurrSyllable>=0)*/ - /*reset syllpointer to original value*/ - pam->nCurrSyllable = nSyll; - /*Perform pause processing*/ - pam_adapter_do_pauses(this); - pam->nCurrSyllable = 0; - pam->nSyllPhoneme = 0; - - return PICO_OK; -}/*pam_adapter_backward_step*/ - -/** - * processes a pause (silence) syllable after backward processing - * @param this : pointer to PAM PU sub object pointer : processes a pause (silence) syllable after backward processing - * @return PICO_OK : backward step complete - * @return PICO_ERR_OTHER : errors on retrieving the PU pointer - * @remarks pam->nCurrSyllable should point to a pause item - * @remarks this function should be called after backward processing - * @remarks this function corresponds to initializing silence phonemes with - * @remarks values derived from previous or following syllables - * @callgraph - * @callergraph - */ -static pico_status_t pam_do_pause(register picodata_ProcessingUnit this) -{ - picoos_uint16 syllCurr; - pam_subobj_t *pam; - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - pam = (pam_subobj_t *) this->subObj; - syllCurr = pam->nCurrSyllable; - - /*processor for all features that can be inherited from previous syll (or word/phrase)*/ - if (pam->nCurrSyllable > 0) { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B3]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B8] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B8]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B10] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B10]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B12] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B12]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B14] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B14]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B17]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B19]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B20]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B21]; - - pam->sSyllFeats[pam->nCurrSyllable].phoneV[D2] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E2]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[G1] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H1]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[G2] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2]; - - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E5] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E5]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E7] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E7]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E9]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E11]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E12]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E13]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E13]; - - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H1]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H3] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H3]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H4] - = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H4]; - - } else { - pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] - =pam->sSyllFeats[pam->nCurrSyllable].phoneV[B8] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B10] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B12] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B14] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E5] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H3] - = 0; - - /*init values different from 0*/ - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H4] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[J3]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] = PICOPAM_p; - - } - - /*processor for all features that can be inherited from next syll (or word/phrase)*/ - if (pam->nCurrSyllable < pam->nTotalSyllables - 1) { - /*non last syllable*/ - pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] - = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[B3]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2] - = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[E2]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1] - = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[H1]; - pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2] - = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[H2]; - } else { - /*last syllable*/ - pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1] - = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2] - = 0; - } - - /*Other fixed values derived from de-facto standard*/ - pam->sSyllFeats[pam->nCurrSyllable].phoneV[B18] = 0; - - return PICO_OK; -}/*pam_do_pause*/ - -/** - * performs the initialization of pause "syllables" - * @param this : pointer to PAM PU sub object pointer : processes a pause (silence) syllable after backward processing - * @return PICO_OK : pause processing successful - * @return PICO_ERR_OTHER : errors on retrieving the PU pointer - * @callgraph - * @callergraph - */ -static pico_status_t pam_adapter_do_pauses(register picodata_ProcessingUnit this) -{ - register pam_subobj_t * pam; - picoos_uint16 nSyll; - - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - pam = (pam_subobj_t *) this->subObj; - - /*Do the pause processing*/ - nSyll = pam->nCurrSyllable; - while (pam->nCurrSyllable >= 0) { - if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P2] == 1) { - /*pause processing*/ - pam_do_pause(this); - } - pam->nCurrSyllable--; - }/*end while (pam->nCurrSyllable>=0)*/ - /*reset syllpointer to original value*/ - pam->nCurrSyllable = nSyll; - return PICOPAM_READY; -}/*pam_adapter_do_pauses*/ - -#ifdef __cplusplus -} -#endif - -/* picopam.c end */ diff --git a/lib/picopam.h b/lib/picopam.h deleted file mode 100644 index 18f7730..0000000 --- a/lib/picopam.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 picopam.h - * - * Phonetic to Acoustic Mapping PU - Header file - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -/** - * @addtogroup picopam - - * Phonetic to acoustic mapping module \n - * - * This module is responsible for mapping the phonetic domain features generated from text analysis - * into parametric representations suitable for signal generation. As such it is the interface - * between text analysis and signal generation - * - * Most the processing of PAM is logically splittable as follows - * - building a suitable symbolic feature vector set for the sentence - * - Feeding Decision Trees with the symbolic seqence vector set - * - Colecting the parametric output of the Decision trees into suitable items to be sent to following PU's - * - * To perform the decision tree feeding and output collection the PU uses an internal buffer. This - * buffer is used several times with different meanings. - * - While building the symbolic feature vector set for the sentence this data structure stores syllable relevant data. - * The corresponding phonetic data is stored outside as a single string of phonetic id's for all the sentence. - * - While feeding the decision trees the data structure is used to represent data for phonemes of the syllable - * - Addiotional data strucures are mantained to temporarily store items not pertaining to the PAM processing, for later resynchronization - * - * A quite detailed description of PAM processing is in the Know How section of the repository. - */ - -#ifndef PICOPAM_H_ -#define PICOPAM_H_ - -#include "picodata.h" -#include "picokdt.h" -#include "picokpdf.h" -#include "picoktab.h" -#include "picokdbg.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -/*------------------------------------------------------------------ -Service routines -------------------------------------------------------------------*/ -picodata_ProcessingUnit picopam_newPamUnit( - picoos_MemoryManager mm, picoos_Common common, - picodata_CharBuffer cbIn, picodata_CharBuffer cbOut, - picorsrc_Voice voice); - -#ifdef __cplusplus -} -#endif -#endif /*PICOPAM_H_*/ diff --git a/lib/picopltf.h b/lib/picopltf.h deleted file mode 100644 index 0cf2659..0000000 --- a/lib/picopltf.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 picopltf.h - * - * Header file (only) to define platform symbols. - * - * Refer to http://predef.sourceforge.net/ for a comprehensive list - * of pre-defined C/C++ compiler macros. - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - */ - -#if !defined(__PICOPLTF_H__) -#define __PICOPLTF_H__ - -#define ENDIANNESS_BIG 1 -#define ENDIANNESS_LITTLE 2 - -/* * platform identifiers ***/ -#define PICO_Windows 1 /* Windows */ -#define PICO_MacOSX 5 /* Macintosh OS X */ -#define PICO_Linux 7 /* Linux */ - -/* * definition of current platform ***/ -#if !defined(PICO_PLATFORM) -#if defined(_WIN32) -#define PICO_PLATFORM PICO_Windows -#elif defined(__APPLE__) && defined(__MACH__) -#define PICO_PLATFORM PICO_MacOSX -#elif defined(linux) || defined(__linux__) || defined(__linux) -#define PICO_PLATFORM PICO_Linux -#else -#error PICO_PLATFORM not defined -#endif -#endif /* !defined(PICO_PLATFORM) */ - - -/* * symbol PICO_PLATFORM_STRING to define platform as string ***/ -#if (PICO_PLATFORM == PICO_Windows) -#define PICO_PLATFORM_STRING "Windows" -#elif (PICO_PLATFORM == PICO_MacOSX) -#define PICO_PLATFORM_STRING "MacOSX" -#elif (PICO_PLATFORM == PICO_Linux) -#define PICO_PLATFORM_STRING "Linux" -#elif (PICO_PLATFORM == PICO_GENERIC) -#define PICO_PLATFORM_STRING "UnknownPlatform" -#endif - -#if (PICO_PLATFORM == PICO_MacOSX) -#define PICO_ENDIANNESS ENDIANNESS_BIG -#else -#define PICO_ENDIANNESS ENDIANNESS_LITTLE -#endif - -#endif /* !defined(__PICOPLTF_H__) */ diff --git a/lib/picopr.c b/lib/picopr.c deleted file mode 100644 index f54734a..0000000 --- a/lib/picopr.c +++ /dev/null @@ -1,3550 +0,0 @@ -/* - * 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 picopr.c - * - * text preprocessor - * - * 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 "picobase.h" -#include "picodbg.h" -#include "picodata.h" -#include "picokpr.h" -#include "picopr.h" -#include "picoktab.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* *****************************************************************************/ -/* constants */ -/* *****************************************************************************/ - -#define PR_TRACE_MEM FALSE -#define PR_TRACE_MAX_MEM FALSE -#define PR_TRACE_PATHCOST TRUE - -#define PR_WORK_MEM_SIZE 10000 -#define PR_DYN_MEM_SIZE 7000 - -#define PR_ENABLED TRUE - -#define PR_MAX_NR_ITERATIONS 1000; - -#define SPEC_CHAR "\\/" - -#define PICO_ERR_CONTEXT_NOT_FOUND PICO_ERR_OTHER -#define PICO_ERR_MAX_PREPROC_PATH_LEN_REACHED PICO_ERR_OTHER - -#define IN_BUF_SIZE 255 -#define OUT_BUF_SIZE IN_BUF_SIZE + 3 * PICODATA_ITEM_HEADSIZE + 3 - -#define PR_MAX_NR_PREPROC (1 + PICOKNOW_MAX_NUM_UTPP) - -#define PR_MAX_PATH_LEN 130 -#define PR_MAX_DATA_LEN IN_BUF_SIZE -#define PR_MAX_DATA_LEN_Z PR_MAX_DATA_LEN + 1 /* all strings in picopr should use this constant - to ensure zero termination */ -#define PR_COST_INIT 100000 -#define PR_COST 10 -#define PR_EOL '\n' - -/* Bit mask constants for token sets with parameters */ -#define PR_TSE_MASK_OUT (1<pr_DynMem. Dynamic memory has - to be deallocated again with pr_DEALLOCATE. - Working memory is allocated in pr_subobj_t->pr_WorkMem. Working memory is stack - based and may not to be deallocated with pr_DEALLOCATE, but with pr_resetMemState - to a state previously saved with pr_getMemState. -*/ - -static void pr_ALLOCATE (picodata_ProcessingUnit this, pr_MemTypes mType, void * * adr, unsigned int byteSize) - /* allocates 'byteSize' bytes in the memery partition given by 'mType' */ -{ - pr_subobj_t * pr = (pr_subobj_t *) this->subObj; - picoos_int32 incrUsedBytes, prevmaxDynMemSize; - - if (mType == pr_WorkMem) { - if ((pr->workMemTop + byteSize) < PR_WORK_MEM_SIZE) { - (*adr) = (void *)(&(pr->pr_WorkMem[pr->workMemTop])); - byteSize = ((byteSize + PICOOS_ALIGN_SIZE - 1) / PICOOS_ALIGN_SIZE) * PICOOS_ALIGN_SIZE; - pr->workMemTop += byteSize; -#if PR_TRACE_MEM - PICODBG_INFO(("pr_WorkMem: +%u, tot:%i of %i", byteSize, pr->workMemTop, PR_WORK_MEM_SIZE)); -#endif - - if (pr->workMemTop > pr->maxWorkMemTop) { - pr->maxWorkMemTop = pr->workMemTop; -#if PR_TRACE_MAX_MEM - PICODBG_INFO(("new max pr_WorkMem: %i of %i", pr->workMemTop, PR_WORK_MEM_SIZE)); -#endif - } - } - else { - (*adr) = NULL; - PICODBG_ERROR(("pr out of working memory")); - picoos_emRaiseException(this->common->em, PICO_EXC_OUT_OF_MEM, (picoos_char *)"pr out of dynamic memory", (picoos_char *)""); - pr->outOfMemory = TRUE; - } - } - else if (mType == pr_DynMem) { - (*adr) = picoos_allocate(pr->dynMemMM, byteSize); - if ((*adr) != NULL) { - prevmaxDynMemSize = pr->maxDynMemSize; - picoos_getMemUsage(pr->dynMemMM, 1, &pr->dynMemSize, &incrUsedBytes, &pr->maxDynMemSize); -#if PR_TRACE_MEM - PICODBG_INFO(("pr_DynMem : +%i, tot:%i of %i", incrUsedBytes, pr->dynMemSize, PR_DYN_MEM_SIZE)); -#endif - -#if PR_TRACE_MAX_MEM - if (pr->maxDynMemSize > prevmaxDynMemSize) { - PICODBG_INFO(("new max pr_DynMem : %i of %i", pr->maxDynMemSize, PR_DYN_MEM_SIZE)); - } -#endif - } - else { - PICODBG_ERROR(("pr out of dynamic memory")); - picoos_emRaiseException(this->common->em, PICO_EXC_OUT_OF_MEM, (picoos_char *)"pr out of dynamic memory", (picoos_char *)""); - pr->outOfMemory = TRUE; - } - } - else { - (*adr) = NULL; - } -} - - -static void pr_DEALLOCATE (picodata_ProcessingUnit this, pr_MemTypes mType, void * * adr) -{ - pr_subobj_t * pr = (pr_subobj_t *) this->subObj; - picoos_int32 incrUsedBytes; - if (mType == pr_WorkMem) { - PICODBG_INFO(("not possible; use pr_resetMemState instead")); - } - else if (mType == pr_DynMem) { - picoos_deallocate(pr->dynMemMM, &(*adr)); - picoos_getMemUsage(pr->dynMemMM, 1, &pr->dynMemSize, &incrUsedBytes, &pr->maxDynMemSize); -#if PR_TRACE_MEM - PICODBG_INFO(("pr_DynMem : %i, tot:%i of %i: adr: %u", incrUsedBytes, pr->dynMemSize, PR_DYN_MEM_SIZE, *adr)); -#endif - } - else { - (*adr) = NULL; - } -} - - -static void pr_getMemState(picodata_ProcessingUnit this, pr_MemTypes mType, picoos_uint32 *lmemState) -{ - pr_subobj_t * pr = (pr_subobj_t *) this->subObj; - mType = mType; /* avoid warning "var not used in this function"*/ - *lmemState = pr->workMemTop; -} - - -static void pr_resetMemState(picodata_ProcessingUnit this, pr_MemTypes mType, picoos_uint32 lmemState) -{ - pr_subobj_t * pr = (pr_subobj_t *) this->subObj; - -#if PR_TRACE_MEM - PICODBG_INFO(("pr_WorkMem: -%i, tot:%i of %i", pr->workMemTop-lmemState, lmemState, PR_WORK_MEM_SIZE)); -#endif - mType = mType; /* avoid warning "var not used in this function"*/ - pr->workMemTop = lmemState; -} - - -/* *****************************************************************************/ -/* string operations */ - -static picoos_int32 pr_strlen(const picoos_uchar * str) -{ - picoos_int32 i; - - i=0; - while ((i= length) { - return length; - } else { - i = pos + len; - while (i < length) { - str[pos] = str[i]; - i++; - pos++; - } - str[pos] = 0; - return pos; - } -} - - -static picoos_bool pr_strEqual(picoos_uchar * str1, picoos_uchar * str2) -{ - return (picoos_strcmp((picoos_char *)str1, (picoos_char *)str2) == 0); -} - - -static void pr_int_to_string(picoos_int32 n, picoos_uchar * str, picoos_int32 maxstrlen) -{ - picoos_int32 i, len; - picoos_bool negative=FALSE; - - len = 0; - str[0] = 0; - if (n<0) { - negative = TRUE; - n = -n; - len++; - } - i = n; - - while (i>0) { - i = i / 10; - len++; - } - - if (len0) && (len>0)) { - len--; - str[len] = i % 10 + '0'; - i = i / 10; - } - if (negative) { - len--; - str[len] = '-'; - } - } -} -/* *****************************************************************************/ - -static void pr_firstLetterToLowerCase (const picoos_uchar src[], picoos_uchar dest[]) -{ - - picoos_int32 i; - picoos_int32 j; - picoos_int32 l; - picoos_bool done; - - i = 0; - j = 0; - l = picobase_det_utf8_length(src[0]); - while ((i < l) && (j < PR_MAX_DATA_LEN)) { - dest[j] = src[i]; - i++; - j++; - } - if (j < PR_MAX_DATA_LEN) { - dest[j] = 0; - } - picobase_lowercase_utf8_str(dest, (picoos_char*)dest, PR_MAX_DATA_LEN, &done); - j = picobase_det_utf8_length(dest[0]); - l = pr_strlen(src); - while ((i < l) && (j < PR_MAX_DATA_LEN)) { - dest[j] = src[i]; - i++; - j++; - } - dest[j] = 0; -} - - -static picoos_int32 tok_tokenDigitStrToInt (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_uchar stokenStr[]) -{ - picoos_uint32 i; - picoos_uint32 l; - picoos_int32 id; - picoos_int32 val; - picoos_uint32 n; - picobase_utf8char utf8char; - - val = 0; - i = 0; - l = pr_strlen(stokenStr); - while (i < l) { - picobase_get_next_utf8char(stokenStr, PR_MAX_DATA_LEN, & i, utf8char); - id = picoktab_graphOffset(pr->graphs, utf8char); - if (id > 0) { - if (picoktab_getIntPropValue(pr->graphs, id, &n)) { - val = (10 * val) + n; - } else { - val = ((10 * val) + (int)((int)utf8char[0] - (int)'0')); - } - } else if ((utf8char[0] >= '0') && (utf8char[0] <= '9')) { - val = 10 * val + ((int)utf8char[0] - (int)'0'); - } - } - return val; -} - - -static picoos_bool pr_isLatinNumber (picoos_uchar str[], picoos_int32 * val) -{ - - picoos_uint32 li; - picoos_uint32 llen; - picoos_uchar lact; - picoos_uchar lnext; - picoos_uchar lprev; - picoos_uchar llatinI; - picoos_uchar llatinV; - picoos_uchar llatinX; - picoos_uchar llatinL; - picoos_uchar llatinC; - picoos_uchar llatinD; - picoos_uchar llatinM; - picoos_int32 lseq; - picobase_utf8char utf8; - - *val = 0; - llen = picobase_utf8_length(str, PR_MAX_DATA_LEN); - if (llen > 0) { - li = 0; - picobase_get_next_utf8char(str, PR_MAX_DATA_LEN, & li,utf8); - if (picobase_is_utf8_uppercase(utf8, PICOBASE_UTF8_MAXLEN)) { - llatinI = 'I'; - llatinV = 'V'; - llatinX = 'X'; - llatinL = 'L'; - llatinC = 'C'; - llatinD = 'D'; - llatinM = 'M'; - } else { - llatinI = 'i'; - llatinV = 'v'; - llatinX = 'x'; - llatinL = 'l'; - llatinC = 'c'; - llatinD = 'd'; - llatinM = 'm'; - } - lseq = 1000; - li = 0; - while (li < llen) { - if (li > 0) { - lprev = str[li - 1]; - } else { - lprev = 0; - } - lact = str[li]; - if (li < (llen - 1)) { - lnext = str[li + 1]; - } else { - lnext = 0; - } - if ((lseq > 1) && (lact == llatinI)) { - if ((lprev != lact) && (lseq >= 4)) { - if (lnext == llatinV) { - *val = *val + 4; - li++; - lseq = 1; - } else if (lnext == llatinX) { - *val = *val + 9; - li++; - lseq = 1; - } else { - *val = *val + 1; - lseq = 3; - } - } else { - *val = *val + 1; - lseq = lseq - 1; - } - } else if ((lseq > 5) && (lact == llatinV)) { - *val = *val + 5; - lseq = 5; - } else if ((lseq > 10) && (lact == llatinX)) { - if ((lprev != lact) && (lseq >= 40)) { - if (lnext == llatinL) { - *val = *val + 40; - li++; - lseq = 10; - } else if (lnext == llatinC) { - *val = *val + 90; - li++; - lseq = 10; - } else { - *val = *val + 10; - lseq = 30; - } - } else { - *val = *val + 10; - lseq = lseq - 10; - } - } else if ((lseq > 50) && (lact == llatinL)) { - *val = *val + 50; - lseq = 50; - } else if ((lseq > 100) && (lact == llatinC)) { - if ((lprev != lact) && (lseq >= 400)) { - if (lnext == llatinD) { - *val = *val + 400; - li++; - lseq = 100; - } else if (lnext == llatinM) { - *val = *val + 900; - li++; - lseq = 100; - } else { - *val = *val + 100; - lseq = 300; - } - } else { - *val = *val + 100; - lseq = lseq - 100; - } - } else if ((lseq > 500) && (lact == llatinD)) { - *val = *val + 500; - lseq = 500; - } else if ((lseq >= 1000) && (lact == llatinM)) { - *val = *val + 1000; - } else { - return FALSE; - } - li++; - } - } - return TRUE; -} - - -static picoos_bool pr_isSUC (picoos_uchar str[]) -{ - - picoos_int32 li; - picoos_bool lis; - picobase_utf8char lutf; - picoos_int32 lj; - picoos_int32 ll; - picoos_bool luc; - - li = 0; - lis = TRUE; - luc = TRUE; - while (lis && (li < PR_MAX_DATA_LEN) && (str[li] != 0)) { - lj = 0; - ll = picobase_det_utf8_length(str[li]); - while (lj < ll) { - lutf[lj] = str[li]; - lj++; - li++; - } - lutf[lj] = 0; - if (luc) { - lis = lis && picobase_is_utf8_uppercase(lutf,PICOBASE_UTF8_MAXLEN+1); - } else { - lis = lis && picobase_is_utf8_lowercase(lutf,PICOBASE_UTF8_MAXLEN+1); - } - luc = FALSE; - } - return lis; -} - -/* *****************************************************************************/ - -static picoos_bool pr_isCmdType (pr_ioItemPtr it, picoos_uint8 type) -{ - if ((it != NULL) && (it->head.type == PICODATA_ITEM_CMD) && (it->head.info1 == type)) { - return TRUE; - } else { - return FALSE; - } -} - - -static picoos_bool pr_isCmdInfo2 (pr_ioItemPtr it, picoos_uint8 info2) -{ - if ((it != NULL) && (it->head.type == PICODATA_ITEM_CMD) && (it->head.info2 == info2)) { - return TRUE; - } else { - return FALSE; - } -} - - -static void pr_initPathEle (struct pr_PathEle * ele) -{ - ele->rnetwork = NULL; - ele->rtok = 0; - ele->ritemid = -1; - ele->rdepth = 1; - ele->rlState = PR_LSInit; - ele->rcompare = -1; - ele->rprodname = 0; - ele->rprodprefcost = 0; -} - -/* *****************************************************************************/ - -static void pr_disposeProdList (register picodata_ProcessingUnit this, pr_ProdList * prodList) -{ - pr_ProdList p; - - while ((*prodList) != NULL) { - p = (*prodList); - (*prodList) = (*prodList)->rNext; - picoos_deallocate(this->common->mm, (void *) &p); - } -} - - -static pico_Status pr_addContext (register picodata_ProcessingUnit this, pr_subobj_t * pr, pr_ContextList * ctxList, picokpr_VarStrPtr contextNamePtr, picokpr_VarStrPtr netNamePtr, picokpr_VarStrPtr prodNamePtr) -{ - picokpr_Preproc net; - pr_ContextList ctx; - pr_ProdList prod; - int i; - picokpr_VarStrPtr strp; - picoos_int32 lprodarrlen; - - ctx = (*ctxList); - while ((ctx != NULL) && !(pr_strEqual(contextNamePtr, ctx->rContextName))) { - ctx = ctx->rNext; - } - if (ctx == NULL) { - ctx = picoos_allocate(this->common->mm, sizeof(pr_Context)); - if (ctx == NULL) { - return PICO_EXC_OUT_OF_MEM; - } - ctx->rNext = (*ctxList); - ctx->rProdList = NULL; - ctx->rContextName = contextNamePtr; - (*ctxList) = ctx; - } - i = 0; - net = pr->preproc[i]; - while ((ipreproc[i]; - } - if (net != NULL) { - i = 0; - strp = picokpr_getVarStrPtr(net, picokpr_getProdNameOfs(net, i)); - lprodarrlen = picokpr_getProdArrLen(net); - while ((i < lprodarrlen) && !(pr_strEqual(prodNamePtr, strp))) { - i++; - if (i < lprodarrlen) { - strp = picokpr_getVarStrPtr(net, picokpr_getProdNameOfs(net, i)); - } - } - if (i < lprodarrlen) { - prod = picoos_allocate(this->common->mm, sizeof(pr_Prod)); - if (prod == NULL) { - return PICO_EXC_OUT_OF_MEM; - } - prod->rNetwork = net; - prod->rProdOfs = i; - prod->rNext = ctx->rProdList; - ctx->rProdList = prod; - } - } - return PICO_OK; -} - - -static pico_Status pr_createContextList (register picodata_ProcessingUnit this) -{ - pr_subobj_t * pr = (pr_subobj_t *) this->subObj; - picokpr_VarStrPtr ctxNamePtr; - picokpr_VarStrPtr netNamePtr; - picokpr_VarStrPtr prodNamePtr; - picoos_int32 p, i, n; - pico_Status status; - - pr->ctxList = NULL; - for (p=0; ppreproc[p] != NULL) { - n = picokpr_getCtxArrLen(pr->preproc[p]); - for (i = 1; ipreproc[p], picokpr_getCtxCtxNameOfs(pr->preproc[p], i)); - netNamePtr = picokpr_getVarStrPtr(pr->preproc[p], picokpr_getCtxNetNameOfs(pr->preproc[p], i)); - prodNamePtr = picokpr_getVarStrPtr(pr->preproc[p], picokpr_getCtxProdNameOfs(pr->preproc[p], i)); - status = pr_addContext(this, pr, &pr->ctxList, ctxNamePtr,netNamePtr, prodNamePtr); - if (status != PICO_OK) { - return status; - } - } - } - } - return PICO_OK; -} - - -static void pr_disposeContextList (register picodata_ProcessingUnit this) -{ - pr_subobj_t * pr = (pr_subobj_t *) this->subObj; - pr_ContextList c; - - while (pr->ctxList != NULL) { - c = pr->ctxList; - pr->ctxList = pr->ctxList->rNext; - pr_disposeProdList(this, & c->rProdList); - picoos_deallocate(this->common->mm, (void *) &c); - } -} - - -static pr_ContextList pr_findContext (pr_ContextList contextList, picoos_uchar contextName[]) -{ - pr_ContextList context; - - context = contextList; - while ((context != NULL) && !(pr_strEqual(context->rContextName,contextName))) { - context = context->rNext; - } - return context; -} - - -static void pr_setContext (register picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_uchar context[]) -{ - - pr_ContextList ctx; - - ctx = pr_findContext(pr->ctxList,context); - if (ctx != NULL) { - pr->actCtx = ctx; - pr->actCtxChanged = TRUE; - } else { - PICODBG_WARN(("context '%s' not found; no change",context)); - picoos_emRaiseWarning(this->common->em, PICO_ERR_CONTEXT_NOT_FOUND, (picoos_char*)"context '%s' not found; no change",(picoos_char*)context); - } -} - -/* *****************************************************************************/ -/* item handling routines */ - - -static picoos_uint32 pr_copyData(picoos_uint8 * dest, const picoos_uint8 * src, picoos_int32 nrBytes, picoos_bool zeroTerm) -{ - picoos_int32 i=0; - - if ((src != NULL) && (dest != NULL)) { - i = 0; - while ((inext = NULL; - item->val = 0; - item->head.len = 0; - item->strci = NULL; - item->strcis = NULL; - item->suc = FALSE; - item->alc = FALSE; - item->auc = FALSE; -} - - -static void pr_newItem (picodata_ProcessingUnit this, pr_MemTypes mType, pr_ioItemPtr * item, picoos_uint8 itemType, picoos_int32 size, picoos_bool inItem) -{ - pr_subobj_t * pr = (pr_subobj_t *) this->subObj; - - if (mType == pr_WorkMem) { - pr_ALLOCATE(this, mType, (void * *) & (*item),PR_IOITEM_MIN_SIZE+size+1); - if (pr->outOfMemory) return; - pr_initItem(this, *item); - } - else if ((mType == pr_DynMem) && inItem) { - pr_ALLOCATE(this, mType, (void * *) & (*item), PR_IOITEM_MIN_SIZE+3*size+3); - if (pr->outOfMemory) return; - pr_initItem(this, *item); - if (itemType == PICODATA_ITEM_TOKEN) { - (*item)->strci = &((*item)->data[size+1]); - (*item)->strcis = &((*item)->data[2*size+2]); - (*item)->strci[0] = 0; - (*item)->strcis[0] = 0; - } - } - else if ((mType == pr_DynMem) && !inItem) { - pr_ALLOCATE(this, mType, (void * *) & (*item), PR_IOITEM_MIN_SIZE+size+1); - if (pr->outOfMemory) return; - pr_initItem(this, *item); - } - - (*item)->data[0] = 0; -} - - -static void pr_copyItemContent (picodata_ProcessingUnit this, pr_ioItem * inItem, pr_ioItem * outItem) -{ - if (outItem != NULL) { - outItem->next = inItem->next; - outItem->val = inItem->val; - outItem->head = inItem->head; - outItem->suc = inItem->suc; - outItem->alc = inItem->alc; - outItem->auc = inItem->auc; - if (inItem->head.len > 0 ) { - pr_copyData(outItem->data, inItem->data, inItem->head.len, /*zeroTerm*/TRUE); - pr_copyData(outItem->strci, inItem->strci, inItem->head.len, /*zeroTerm*/TRUE); - pr_copyData(outItem->strcis, inItem->strcis, inItem->head.len, /*zeroTerm*/TRUE); - } - } -} - - -static void pr_copyItem (picodata_ProcessingUnit this, pr_MemTypes mType, pr_ioItemPtr inItem, pr_ioItemPtr * outItem) -{ - pr_subobj_t * pr = (pr_subobj_t *) this->subObj; - - if (inItem != NULL) { - pr_newItem(this, mType,& (*outItem), inItem->head.type, inItem->head.len, FALSE); - if (pr->outOfMemory) return; - pr_copyItemContent(this, inItem, *outItem); - } - else { - outItem = NULL; - } -} - - -static void pr_startItemList (pr_ioItemPtr * firstItem, pr_ioItemPtr * lastItem) -{ - *firstItem = NULL; - *lastItem = NULL; -} - - -static void pr_appendItem (picodata_ProcessingUnit this, pr_ioItemPtr * firstItem, pr_ioItemPtr * lastItem, pr_ioItemPtr item) -{ - if (item != NULL) { - item->next = NULL; - if ((*lastItem) == NULL) { - *firstItem = item; - } else { - (*lastItem)->next = item; - } - (*lastItem) = item; - } -} - - -static void pr_disposeItem (picodata_ProcessingUnit this, pr_ioItemPtr * item) -{ - if ((*item) != NULL) { - pr_DEALLOCATE(this, pr_DynMem, (void * *) & (*item)); - } -} - - -static void pr_putItem (picodata_ProcessingUnit this, pr_subobj_t * pr, - pr_ioItemPtr * first, pr_ioItemPtr * last, - picoos_uint8 itemType, picoos_uint8 info1, picoos_uint8 info2, - picoos_uint16 val, - picoos_uchar str[]) -{ - picoos_int32 i; - pr_ioItemPtr item; - - pr->tmpItem.next = NULL; - pr->tmpItem.val = 0; - pr->tmpItem.head.type = itemType; - pr->tmpItem.head.info1 = info1; - pr->tmpItem.head.info2 = info2; - - pr_initItem(this, &pr->tmpItem); - switch (itemType) { - case PICODATA_ITEM_CMD: - switch (info1) { - case PICODATA_ITEMINFO1_CMD_CONTEXT: - case PICODATA_ITEMINFO1_CMD_VOICE: - case PICODATA_ITEMINFO1_CMD_MARKER: - case PICODATA_ITEMINFO1_CMD_PLAY: - case PICODATA_ITEMINFO1_CMD_SAVE: - case PICODATA_ITEMINFO1_CMD_UNSAVE: - case PICODATA_ITEMINFO1_CMD_PROSDOMAIN: - pr->tmpItem.head.len = picoos_strlen((picoos_char*)str); - for (i=0; itmpItem.head.len; i++) { - pr->tmpItem.data[i] = str[i]; - } - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, & item); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),item); - break; - case PICODATA_ITEMINFO1_CMD_IGNSIG: - case PICODATA_ITEMINFO1_CMD_IGNORE: - case PICODATA_ITEMINFO1_CMD_FLUSH: - pr->tmpItem.head.len = 0; - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, & item); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),item); - break; - case PICODATA_ITEMINFO1_CMD_SPEED: - case PICODATA_ITEMINFO1_CMD_PITCH: - case PICODATA_ITEMINFO1_CMD_VOLUME: - case PICODATA_ITEMINFO1_CMD_SPELL: - case PICODATA_ITEMINFO1_CMD_SIL: - pr->tmpItem.head.len = 2; - pr->tmpItem.data[0] = val % 256; - pr->tmpItem.data[1] = val / 256; - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, & item); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),item); - break; - case PICODATA_ITEMINFO1_CMD_PHONEME: - PICODBG_WARN(("phoneme command not yet implemented")); - break; - default: - PICODBG_WARN(("pr_putItem: unknown command type")); - } - break; - case PICODATA_ITEM_TOKEN: - pr->tmpItem.head.len = picoos_strlen((picoos_char*)str); - for (i=0; itmpItem.head.len; i++) { - pr->tmpItem.data[i] = str[i]; - } - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, & item); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),item); - break; - default: - PICODBG_WARN(("pr_putItem: unknown item type")); - } -} - - -static void pr_appendItemToOutItemList (picodata_ProcessingUnit this, pr_subobj_t * pr, - pr_ioItemPtr * firstItem, pr_ioItemPtr * lastItem, pr_ioItemPtr item) -{ - pr_ioItemPtr litem; - picoos_int32 li; - picoos_int32 li2; - picoos_int32 lid; - picoos_int32 ln; - picoos_int32 ln2; - picoos_uint8 ltype; - picoos_int8 lsubtype; - picoos_uchar lstr[10]; - picoos_bool ldone; - - item->next = NULL; - if (((pr->spellMode != 0) && (item->head.type == PICODATA_ITEM_TOKEN) && (item->head.info1 != PICODATA_ITEMINFO1_TOKTYPE_SPACE))) { - li = 0; - ln = pr_strlen(item->data); - while (li < ln) { - ln2 = picobase_det_utf8_length(item->data[li]); - for (li2 = 0; li2data[li]; - li++; - } - lstr[ln2] = 0; - lid = picoktab_graphOffset(pr->graphs, lstr); - if ((lid > 0) && picoktab_getIntPropTokenType(pr->graphs, lid, <ype) && - ((ltype == PICODATA_ITEMINFO1_TOKTYPE_LETTERV) /*|| (ltype == PICODATA_ITEMINFO1_TOKTYPE_DIGIT)*/)) { - ln2 = pr_strcat(lstr,(picoos_uchar*)SPEC_CHAR); - picoktab_getIntPropTokenSubType(pr->graphs,lid, &lsubtype); - } - else { - ltype = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; - lsubtype = -(1); - } - pr_newItem(this, pr_DynMem,& litem, PICODATA_ITEM_TOKEN, ln2, /*inItem*/FALSE); - if (pr->outOfMemory) return; - litem->head.type = PICODATA_ITEM_TOKEN; - litem->head.info1 = item->head.info1; - litem->head.info2 = item->head.info2; - pr_strcpy(litem->data, lstr); - litem->data[ln2] = 0; - litem->head.len = ln2; - if (litem->head.info1 == PICODATA_ITEMINFO1_TOKTYPE_DIGIT) { - litem->val = tok_tokenDigitStrToInt(this, pr, litem->data); - } else { - litem->val = 0; - } - picobase_lowercase_utf8_str(litem->data,litem->strci,PR_MAX_DATA_LEN, &ldone); - pr_firstLetterToLowerCase(litem->data,litem->strcis); - litem->alc = picobase_is_utf8_lowercase(litem->data,PR_MAX_DATA_LEN); - litem->auc = picobase_is_utf8_uppercase(litem->data,PR_MAX_DATA_LEN); - litem->suc = pr_isSUC(litem->data); - - pr_appendItem(this, firstItem, lastItem, litem); - if (pr->spellMode == PR_SPELL_WITH_SENTENCE_BREAK) { - pr_newItem(this, pr_DynMem,& litem, PICODATA_ITEM_TOKEN, 2, /*inItem*/FALSE); - if (pr->outOfMemory) return; - litem->head.type = PICODATA_ITEM_TOKEN; - litem->head.info1 = PICODATA_ITEMINFO1_TOKTYPE_CHAR; - litem->head.info2 = -1; - litem->head.len = 1; - litem->data[0] = ','; - litem->data[1] = 0; - litem->strci[0] = ','; - litem->strci[1] = 0; - litem->strcis[0] = ','; - litem->strcis[1] = 0; - litem->val = 0; - pr_appendItem(this, firstItem, lastItem, litem); - } else if (pr->spellMode == PR_SPELL_WITH_SENTENCE_BREAK) { - pr_newItem(this, pr_DynMem,& litem, PICODATA_ITEM_CMD, 0, /*inItem*/FALSE); - if (pr->outOfMemory) return; - litem->head.type = PICODATA_ITEM_CMD; - litem->head.info1 = PICODATA_ITEMINFO1_CMD_FLUSH; - litem->head.info2 = PICODATA_ITEMINFO2_NA; - litem->head.len = 0; - pr_appendItem(this, firstItem, lastItem,litem); - } else if (pr->spellMode > 0) { - pr_newItem(this, pr_DynMem,& litem, PICODATA_ITEM_CMD, 2, /*inItem*/FALSE); - if (pr->outOfMemory) return; - litem->head.type = PICODATA_ITEM_CMD; - litem->head.info1 = PICODATA_ITEMINFO1_CMD_SIL; - litem->head.info2 = PICODATA_ITEMINFO2_NA; - litem->head.len = 2; - litem->data[0] = pr->spellMode % 256; - litem->data[1] = pr->spellMode / 256; - pr_appendItem(this, firstItem, lastItem, litem); - } - } - pr_disposeItem(this, & item); - } else if (pr_isCmdType(item, PICODATA_ITEMINFO1_CMD_SPELL) && pr_isCmdInfo2(item, PICODATA_ITEMINFO2_CMD_START)) { - pr->spellMode = item->data[0]+256*item->data[1]; - pr_disposeItem(this, & item); - } else if (pr_isCmdType(item, PICODATA_ITEMINFO1_CMD_SPELL) && pr_isCmdInfo2(item, PICODATA_ITEMINFO2_CMD_END)) { - pr->spellMode = 0; - pr_disposeItem(this, & item); - } else { - pr_appendItem(this, firstItem,lastItem,item); - } -} - - -/* *****************************************************************************/ - -static pr_OutItemVarPtr pr_findVariable (pr_OutItemVarPtr vars, picoos_int32 id) -{ - while ((vars != NULL) && (vars->id != id)) { - vars = vars->next; - } - if ((vars != NULL)) { - return vars; - } else { - return NULL; - } -} - - -static void pr_genCommands (picodata_ProcessingUnit this, pr_subobj_t * pr, - picokpr_Preproc network, picokpr_OutItemArrOffset outitem, pr_OutItemVarPtr vars, pr_ioItemPtr * first, pr_ioItemPtr * last) -{ - - pr_ioItemPtr litem; - pr_OutItemVarPtr lvar; - picoos_uint8 lcmd; - picoos_uint8 linfo2; - picoos_bool ldone; -#if 0 - picoos_int32 lphontype; -#endif - picokpr_VarStrPtr lstrp; - picoos_int32 lnum; - pr_ioItemPtr lf; - pr_ioItemPtr ll; - picoos_int32 lf0beg; - picoos_int32 lf0end; - ShortStrParam lxfadebeg; - ShortStrParam lxfadeend; - picoos_bool lout; - picoos_int32 ltype; - picoos_int32 argOfs; - picoos_int32 nextOfs; - picoos_int32 nextOfs2; - picoos_int32 nextOfs3; - picoos_int32 nextOfs4; - picoos_uchar alphabet[32]; - - lcmd = 0; - lnum = 0; - litem = NULL; - ltype = picokpr_getOutItemType(network, outitem); - switch (ltype) { - case PR_OIgnore: - if (picokpr_getOutItemVal(network, outitem) == 0) { - pr_putItem(this, pr, & (*first),& (*last),PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_IGNORE,PICODATA_ITEMINFO2_CMD_START,0,(picoos_uchar*)""); - } else { - pr_putItem(this, pr, & (*first),& (*last),PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_IGNORE,PICODATA_ITEMINFO2_CMD_END,0,(picoos_uchar*)""); - } - break; - case PR_OPitch: case PR_OSpeed: case PR_OVolume: - switch (ltype) { - case PR_OPitch: - lcmd = PICODATA_ITEMINFO1_CMD_PITCH; - lnum = PICO_PITCH_DEFAULT; - break; - case PR_OSpeed: - lcmd = PICODATA_ITEMINFO1_CMD_SPEED; - lnum = PICO_SPEED_DEFAULT; - break; - case PR_OVolume: - lcmd = PICODATA_ITEMINFO1_CMD_VOLUME; - lnum = PICO_VOLUME_DEFAULT; - break; - default: - break; - } - if ((picokpr_getOutItemArgOfs(network, outitem) != 0)) { - switch (picokpr_getOutItemType(network, picokpr_getOutItemArgOfs(network, outitem))) { - case PR_OVal: - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, lcmd,PICODATA_ITEMINFO2_CMD_ABSOLUTE, picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, outitem)),(picoos_uchar*)""); - break; - case PR_OVar: - lvar = pr_findVariable(vars,picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, outitem))); - if ((lvar != NULL) && (lvar->first != NULL) && (lvar->first->head.type == PICODATA_ITEM_TOKEN)) { - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,PICODATA_ITEMINFO2_CMD_ABSOLUTE,picoos_atoi((picoos_char*)lvar->first->data),(picoos_uchar*)""); - } - break; - default: - pr_startItemList(& lf,& ll); - pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, outitem),vars,& lf,& ll); - if (pr->outOfMemory) return; - if (((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN))) { - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,PICODATA_ITEMINFO2_CMD_ABSOLUTE,picoos_atoi((picoos_char*)lf->data),(picoos_uchar*)""); - } - break; - } - } else { - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,PICODATA_ITEMINFO2_CMD_ABSOLUTE,lnum,(picoos_uchar*)""); - } - break; - - case PR_OPhonSVOXPA: case PR_OPhonSAMPA: - if (picokpr_getOutItemArgOfs(network, outitem) != 0) { - if (ltype == PR_OPhonSVOXPA) { - picoos_strlcpy(alphabet, PICODATA_SVOXPA, sizeof(alphabet)); - } - else { - picoos_strlcpy(alphabet, PICODATA_SAMPA, sizeof(alphabet)); - } - pr_startItemList(& lf,& ll); - pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, outitem),vars,& lf,& ll); - if (pr->outOfMemory) return; - if (lf != NULL) { - ldone = FALSE; - if (lf->head.type == PICODATA_ITEM_TOKEN) { - if (picodata_mapPAStrToPAIds(pr->transducer, this->common, pr->xsampa_parser, pr->svoxpa_parser, pr->xsampa2svoxpa_mapper, lf->data, alphabet, pr->tmpStr1, sizeof(pr->tmpStr1)-1) == PICO_OK) { - pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PHONEME, - PICODATA_ITEMINFO2_CMD_START, 0, pr->tmpStr1); - ldone = TRUE; - } - else { - PICODBG_WARN(("cannot map phonetic string '%s'; synthesizeing text instead", lf->data)); - picoos_emRaiseWarning(this->common->em, PICO_ERR_OTHER,(picoos_char*)"", (picoos_char*)"cannot map phonetic string '%s'; synthesizing text instead", lf->data); - } - } - if (ldone) { - lf = lf->next; - while (lf != NULL) { - if (lf->head.type == PICODATA_ITEM_TOKEN) { - pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_TOKEN, PICODATA_ITEMINFO1_CMD_PHONEME, - PICODATA_ITEMINFO2_CMD_END, 0, (picoos_char *)""); - } - lf = lf->next; - } - pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PHONEME, - PICODATA_ITEMINFO2_CMD_END, 0, (picoos_char *)""); - } - } - } - break; - - case PR_OSent: - pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); - break; - case PR_OPara: - pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); - if (picokpr_getOutItemVal(network, outitem) == 1) { - pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SIL, PICODATA_ITEMINFO2_NA, PICO_PARAGRAPH_PAUSE_DUR, (picoos_uchar*)""); - } - break; - case PR_OBreak: - if ((picokpr_getOutItemArgOfs(network, outitem) != 0)) { - switch (picokpr_getOutItemType(network, picokpr_getOutItemArgOfs(network, outitem))) { - case PR_OVal: - pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SIL, PICODATA_ITEMINFO2_NA, picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, outitem)), (picoos_uchar*)""); - break; - case PR_OVar: - lvar = pr_findVariable(vars,picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, outitem))); - if ((lvar != NULL) && (lvar->first != NULL) && (lvar->first->head.type == PICODATA_ITEM_TOKEN)) { - pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SIL, PICODATA_ITEMINFO2_NA, picoos_atoi((picoos_char*)lvar->first->data), (picoos_uchar*)""); - } - break; - default: - pr_startItemList(& lf,& ll); - pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, outitem),vars,& lf,& ll); - if (pr->outOfMemory) return; - if (((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN))) { - pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SIL, PICODATA_ITEMINFO2_NA, picoos_atoi((picoos_char*)lf->data), (picoos_uchar*)""); - } - break; - } - } - break; - case PR_OVoice: case PR_OContext: case PR_OMark: - if (picokpr_getOutItemType(network, outitem) == PR_OVoice) { - lcmd = PICODATA_ITEMINFO1_CMD_VOICE; - pr->tmpStr1[0] = 0; - lnum = 1; - } else if (picokpr_getOutItemType(network, outitem) == PR_OContext) { - lcmd = PICODATA_ITEMINFO1_CMD_CONTEXT; - pr_strcpy(pr->tmpStr1, (picoos_uchar*)PICO_CONTEXT_DEFAULT); - lnum = 1; - } else if ((picokpr_getOutItemType(network, outitem) == PR_OMark)) { - lcmd = PICODATA_ITEMINFO1_CMD_MARKER; - pr->tmpStr1[0] = 0; - lnum = 0; - } - if (picokpr_getOutItemArgOfs(network, outitem) != 0) { - switch (picokpr_getOutItemType(network, picokpr_getOutItemArgOfs(network, outitem))) { - case PR_OVar: - lvar = pr_findVariable(vars,picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, outitem))); - if (lvar != NULL) { - litem = lvar->first; - } - pr->tmpStr1[0] = 0; - while (litem != NULL) { - if (litem->head.type == PICODATA_ITEM_TOKEN) { - pr_strcat(pr->tmpStr1,litem->data); - } - litem = litem->next; - } - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, lcmd,lnum,0,pr->tmpStr1); - break; - case PR_OStr: - if (picokpr_getOutItemStrOfs(network, picokpr_getOutItemArgOfs(network, outitem)) != 0) { - lstrp = picokpr_getOutItemStr(network, picokpr_getOutItemArgOfs(network, outitem)); - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,lnum,0,lstrp); - } - break; - default: - pr_startItemList(& lf,& ll); - pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, outitem),vars,& lf,& ll); - if (pr->outOfMemory) return; - if (((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN))) { - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,lnum,0,lf->data); - } - break; - } - } else { - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,lnum,0,pr->tmpStr1); - } - break; - case PR_OGenFile: - if (picokpr_getOutItemArgOfs(network, outitem) != 0) { - lcmd = PICODATA_ITEMINFO1_CMD_SAVE; - } else { - lcmd = PICODATA_ITEMINFO1_CMD_UNSAVE; - } - pr->tmpStr1[0] = 0; - lnum = 0; - if (picokpr_getOutItemArgOfs(network, outitem) != 0) { - switch (picokpr_getOutItemType(network, picokpr_getOutItemArgOfs(network, outitem))) { - case PR_OVar: - lvar = pr_findVariable(vars,picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, outitem))); - if (lvar != NULL) { - litem = lvar->first; - } - pr->tmpStr1[0] = 0; - while (litem != NULL) { - if (litem->head.type == PICODATA_ITEM_TOKEN) { - pr_strcat(pr->tmpStr1,litem->data); - } - litem = litem->next; - } - if ((lnum = picodata_getPuTypeFromExtension(pr->tmpStr1, /*input*/FALSE)) != PICODATA_ITEMINFO2_CMD_TO_UNKNOWN) { - if (pr->saveFile[0] != 0) { - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_UNSAVE, - picodata_getPuTypeFromExtension(pr->saveFile, /*input*/FALSE),0,pr->saveFile); - } - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, lcmd,lnum,0,pr->tmpStr1); - pr_strcpy(pr->saveFile, pr->tmpStr1); - } - break; - case PR_OStr: - if (picokpr_getOutItemStrOfs(network, picokpr_getOutItemArgOfs(network, outitem)) != 0) { - lstrp = picokpr_getOutItemStr(network, picokpr_getOutItemArgOfs(network, outitem)); - if ((lnum = picodata_getPuTypeFromExtension(lstrp, /*input*/FALSE)) != PICODATA_ITEMINFO2_CMD_TO_UNKNOWN) { - if (pr->saveFile[0] != 0) { - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_UNSAVE, - picodata_getPuTypeFromExtension(pr->saveFile, /*input*/FALSE),0,pr->saveFile); - } - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, lcmd,lnum,0,lstrp); - pr_strcpy(pr->saveFile, lstrp); - } - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,lnum,0,lstrp); - } - break; - default: - pr_startItemList(& lf,& ll); - pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, outitem),vars,& lf,& ll); - if (pr->outOfMemory) return; - if (((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN))) { - if ((lnum = picodata_getPuTypeFromExtension(lf->data, /*input*/FALSE)) != PICODATA_ITEMINFO2_CMD_TO_UNKNOWN) { - if (pr->saveFile[0] != 0) { - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_UNSAVE, - picodata_getPuTypeFromExtension(pr->saveFile, /*input*/FALSE),0,pr->saveFile); - } - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, lcmd,lnum,0,lf->data); - pr_strcpy(pr->saveFile, lf->data); - } - } - break; - } -/* - } else { - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,lnum,0,pr->tmpStr1); -*/ - } - break; - case PR_OUseSig: case PR_OPlay: - lout = FALSE; - lf0beg = -(1); - lf0end = -(1); - lxfadebeg[0] = 0; - lxfadeend[0] = 0; - pr->tmpStr1[0] = 0; - if ((picokpr_getOutItemType(network, outitem) == PR_OUseSig)) { - lcmd = PICODATA_ITEMINFO1_CMD_IGNSIG; - } else { - lcmd = PICODATA_ITEMINFO1_CMD_IGNORE; - } - if (picokpr_getOutItemArgOfs(network, outitem) != 0) { - linfo2 = PICODATA_ITEMINFO2_CMD_START; - } else { - linfo2 = PICODATA_ITEMINFO2_CMD_END; - } - if (picokpr_getOutItemArgOfs(network, outitem) != 0) { - switch (picokpr_getOutItemType(network, picokpr_getOutItemArgOfs(network, outitem))) { - case PR_OVar: - lvar = pr_findVariable(vars,picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, outitem))); - if (lvar != NULL) { - litem = lvar->first; - } - pr->tmpStr1[0] = 0; - while (litem != NULL) { - if (litem->head.type == PICODATA_ITEM_TOKEN) { - pr_strcat(pr->tmpStr1,litem->data); - } - litem = litem->next; - } - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PLAY, - picodata_getPuTypeFromExtension(pr->tmpStr1, /*input*/TRUE),0, pr->tmpStr1); - lout = TRUE; - break; - case PR_OStr: - if (picokpr_getOutItemStrOfs(network, picokpr_getOutItemArgOfs(network, outitem)) != 0) { - lstrp = picokpr_getOutItemStr(network, picokpr_getOutItemArgOfs(network, outitem)); - pr_strcpy(pr->tmpStr1, lstrp); - lout = TRUE; - } - break; - default: - pr_startItemList(& lf,& ll); - pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, outitem),vars,& lf,& ll); - if (pr->outOfMemory) return; - if ((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN)) { - pr_strcpy(pr->tmpStr1, lf->data); - lout = TRUE; - } - break; - } - } - argOfs = picokpr_getOutItemArgOfs(network, outitem); - if (argOfs != 0) { - nextOfs = picokpr_getOutItemNextOfs(network, outitem); - if (nextOfs != 0) { - if (picokpr_getOutItemType(network, nextOfs) == PR_OVal) { - lf0beg = picokpr_getOutItemVal(network, nextOfs); - } - nextOfs2 = picokpr_getOutItemNextOfs(network, nextOfs); - if (nextOfs2 != 0) { - if (picokpr_getOutItemType(network, nextOfs2) == PR_OVal) { - lf0end = picokpr_getOutItemVal(network, nextOfs2); - } - nextOfs3 = picokpr_getOutItemNextOfs(network, nextOfs2); - if (nextOfs3 != 0) { - if ((picokpr_getOutItemType(network, nextOfs3) == PR_OStr) && (picokpr_getOutItemStrOfs(network, nextOfs3) != 0)) { - lstrp = picokpr_getOutItemStr(network, nextOfs3); - pr_strcpy(lxfadebeg, lstrp); - } - nextOfs4 = picokpr_getOutItemNextOfs(network, nextOfs3); - if (nextOfs4 != 0) { - if ((picokpr_getOutItemType(network, nextOfs4) == PR_OStr) && (picokpr_getOutItemStrOfs(network, nextOfs4) != 0)) { - lstrp = picokpr_getOutItemStr(network, nextOfs4); - pr_strcpy(lxfadeend, lstrp); - } - } - } - } - } - } - if (lout) { - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,PICODATA_ITEMINFO1_CMD_PLAY, - picodata_getPuTypeFromExtension(pr->tmpStr1, /*input*/TRUE),0,pr->tmpStr1); - } - pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,linfo2,0,(picoos_uchar*)""); - break; - default: - PICODBG_INFO(("unknown command")); - break; - } -} - - -static void pr_getOutputItemList (picodata_ProcessingUnit this, - pr_subobj_t * pr, - picokpr_Preproc network, - picokpr_OutItemArrOffset outitem, - pr_OutItemVarPtr vars, - pr_ioItemPtr * first, - pr_ioItemPtr * last) -{ - - picokpr_OutItemArrOffset lo; - picoos_int32 llen; - picoos_int32 llen2; - picokpr_VarStrPtr lstrp; - picoos_int32 lval32; - picoos_int32 li; - picoos_int32 li2; - picoos_int32 ln; - picoos_int32 ln2; - pr_ioItemPtr litem2; - pr_ioItemPtr lf; - pr_ioItemPtr ll; - picoos_int32 lid; - picoos_uint8 ltype; - picoos_int8 lsubtype; - pr_OutItemVarPtr lvar; - picoos_int32 lspellmode; - picoos_int32 largOfs; - picoos_int32 lnextOfs; - - - lo = outitem; - while (lo != 0) { - switch (picokpr_getOutItemType(network, lo)) { - case PR_OStr: - lstrp = picokpr_getOutItemStr(network, lo); - if (pr->outOfMemory) return; - pr_initItem(this, &pr->tmpItem); - pr->tmpItem.head.type = PICODATA_ITEM_TOKEN; - pr->tmpItem.head.info1 = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; - pr->tmpItem.head.info2 = -1; - pr->tmpItem.head.len = pr_strcpy(pr->tmpItem.data, lstrp); - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),litem2); - break; - case PR_OVar: - lvar = pr_findVariable(vars,picokpr_getOutItemVal(network, lo)); - if (lvar != NULL) { - lf = lvar->first; - } else { - lf = NULL; - } - while (lf != NULL) { - pr_copyItem(this, pr_WorkMem,& (*lf),& litem2); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),litem2); - lf = lf->next; - } - break; - case PR_OSpell: - lspellmode = PR_SPELL; - largOfs = picokpr_getOutItemArgOfs(network, lo); - if ((largOfs!= 0) && ((lnextOfs = picokpr_getOutItemNextOfs(network, largOfs)) != 0)) { - lspellmode = picokpr_getOutItemVal(network, lnextOfs); - } - pr_startItemList(& lf,& ll); - pr_getOutputItemList(this, pr, network,largOfs,vars,& lf,& ll); - if (pr->outOfMemory) return; - while (lf != NULL) { - switch (lf->head.type) { - case PICODATA_ITEM_TOKEN: - li = 0; - ln = pr_strlen(lf->data); - while (li < ln) { - pr_initItem(this, &pr->tmpItem); - if (pr->outOfMemory) return; - pr->tmpItem.head.type = PICODATA_ITEM_TOKEN; - pr->tmpItem.head.info1 = lf->head.info1; - pr->tmpItem.head.info2 = lf->head.info2; - pr->tmpItem.head.len = picobase_det_utf8_length(lf->data[li]); - for (li2 = 0; li2 < pr->tmpItem.head.len; li2++) { - pr->tmpItem.data[li2] = lf->data[li]; - li++; - } - pr->tmpItem.data[pr->tmpItem.head.len] = 0; - pr->tmpItem.val = 0; - lid = picoktab_graphOffset(pr->graphs,pr->tmpItem.data); - if (lid > 0) { - if (picoktab_getIntPropTokenType(pr->graphs, lid, <ype)) { - if ((ltype == PICODATA_ITEMINFO1_TOKTYPE_LETTERV)/* || (ltype == PICODATA_ITEMINFO1_TOKTYPE_DIGIT)*/) { - pr->tmpItem.head.len = pr_strcat(pr->tmpItem.data,(picoos_uchar*)SPEC_CHAR); - } - } - picoktab_getIntPropTokenSubType(pr->graphs, lid, &lsubtype); - } else { - ltype = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; - lsubtype = -(1); - } - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last), litem2); - if (lspellmode == PR_SPELL_WITH_PHRASE_BREAK) { - pr_initItem(this, &pr->tmpItem); - pr->tmpItem.head.type = PICODATA_ITEM_TOKEN; - pr->tmpItem.head.info1 = PICODATA_ITEMINFO1_TOKTYPE_CHAR; - pr->tmpItem.head.info2 = lsubtype; - pr->tmpItem.head.len = 1; - pr->tmpItem.data[0] = ','; - pr->tmpItem.data[1] = 0; - pr->tmpItem.val = 0; - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),litem2); - } else if (lspellmode == PR_SPELL_WITH_SENTENCE_BREAK) { - pr_initItem(this, &pr->tmpItem); - pr->tmpItem.head.type = PICODATA_ITEM_CMD; - pr->tmpItem.head.info1 = PICODATA_ITEMINFO1_CMD_FLUSH; - pr->tmpItem.head.info2 = PICODATA_ITEMINFO2_NA; - pr->tmpItem.head.len = 0; - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),litem2); - } else if (lspellmode > 0) { - pr_initItem(this, &pr->tmpItem); - pr->tmpItem.head.type = PICODATA_ITEM_TOKEN; - pr->tmpItem.head.info1 = PICODATA_ITEMINFO1_TOKTYPE_CHAR; - pr->tmpItem.head.info2 = lsubtype; - pr->tmpItem.head.len = 1; - pr->tmpItem.data[0] = ','; - pr->tmpItem.data[1] = 0; - pr->tmpItem.val = 0; - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),litem2); - } - } - break; - default: - pr_copyItem(this, pr_WorkMem,& (*lf),& litem2); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),litem2); - break; - } - ll = lf; - lf = lf->next; - ll->next = NULL; - } - break; - case PR_OConcat: - pr_startItemList(& lf,& ll); - pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, lo),vars,& lf,& ll); - if (pr->outOfMemory) return; - pr_initItem(this, &pr->tmpItem); - pr->tmpItem.head.type = PICODATA_ITEM_TOKEN; - pr->tmpItem.head.info1 = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; - pr->tmpItem.head.info2 = -(1); - pr->tmpItem.head.len = 0; - pr->tmpItem.data[0] = 0; - pr->tmpItem.val = 0; - while (lf != NULL) { - switch (lf->head.type) { - case PICODATA_ITEM_TOKEN: - pr->tmpItem.head.len = pr_strcat(pr->tmpItem.data,lf->data); - break; - case PICODATA_ITEM_CMD: - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),litem2); - - pr_copyItem(this, pr_WorkMem, lf, &litem2); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),litem2); - - pr_initItem(this, &pr->tmpItem); - pr->tmpItem.head.type = PICODATA_ITEM_TOKEN; - pr->tmpItem.head.info1 = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; - pr->tmpItem.head.info2 = -(1); - pr->tmpItem.head.len = 0; - pr->tmpItem.data[0] = 0; - pr->tmpItem.val = 0; - break; - default: - break; - } - lf = lf->next; - } - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),litem2); - break; - case PR_ORomanToCard: - pr_startItemList(& lf,& ll); - pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, lo),vars,& lf,& ll); - if (pr->outOfMemory) return; - if ((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN)) { - pr_initItem(this, &pr->tmpItem); - pr_copyItemContent(this, lf, &pr->tmpItem); - if (pr_isLatinNumber(lf->data, & lval32)) { - pr_int_to_string(lval32, (picoos_char *)pr->tmpItem.data, PR_MAX_DATA_LEN_Z); - pr->tmpItem.head.len = pr_strlen(pr->tmpItem.data); - pr->tmpItem.val = lval32; - } - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); - pr_appendItem(this, & (*first),& (*last),litem2); - } - break; - case PR_OVal: - break; - case PR_OLeft: - pr_startItemList(& lf,& ll); - pr_getOutputItemList(this, pr, network,picokpr_getOutItemNextOfs(network, picokpr_getOutItemArgOfs(network, lo)),vars,& lf,& ll); - if (pr->outOfMemory) return; - if ((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN)) { - pr_initItem(this, &pr->tmpItem); - pr_copyItemContent(this, lf, &pr->tmpItem); - llen = lf->head.len; - llen2 = picobase_utf8_length(pr->tmpItem.data,PR_MAX_DATA_LEN); - ln = 0; - ln2 = 0; - largOfs = picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, lo)); - while ((ln < llen) && (ln2 < llen2) && (ln2 < largOfs)) { - ln = ln + picobase_det_utf8_length(pr->tmpItem.data[ln]); - ln2++; - } - pr->tmpItem.data[ln] = 0; - pr->tmpItem.head.len = ln; - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),litem2); - } - break; - case PR_ORight: - pr_startItemList(& lf,& ll); - pr_getOutputItemList(this, pr, network,picokpr_getOutItemNextOfs(network, picokpr_getOutItemArgOfs(network, lo)),vars,& lf,& ll); - if (pr->outOfMemory) return; - if ((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN)) { - pr_initItem(this, &pr->tmpItem); - pr_copyItemContent(this, lf, & pr->tmpItem); - llen = lf->head.len; - llen2 = picobase_utf8_length(pr->tmpItem.data,PR_MAX_DATA_LEN); - ln = 0; - ln2 = 0; - while ((ln < llen) && (ln2 < llen2) && (ln2 < (llen2 - picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, lo))))) { - ln = ln + picobase_det_utf8_length(pr->tmpItem.data[ln]); - ln2++; - } - pr->tmpItem.head.len = pr_removeSubstring(0,ln,pr->tmpItem.data); - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, & litem2); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),litem2); - } - break; - case PR_OItem: - pr_startItemList(& lf,& ll); - pr_getOutputItemList(this, pr, network,picokpr_getOutItemNextOfs(network, picokpr_getOutItemArgOfs(network, lo)),vars,& lf,& ll); - if (pr->outOfMemory) return; - ln = picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, lo)); - li = 1; - while ((li < ln) && (lf != NULL)) { - lf = lf->next; - li++; - } - if ((lf != NULL) && (li == ln) && (lf->head.type == PICODATA_ITEM_TOKEN)) { - pr_copyItem(this, pr_WorkMem, lf, & litem2); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),litem2); - } - break; - case PR_ORLZ: - pr_startItemList(& lf,& ll); - pr_getOutputItemList(this, pr, network, picokpr_getOutItemArgOfs(network, lo),vars,& lf,& ll); - if (pr->outOfMemory) return; - if ((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN)) { - pr_initItem(this, &pr->tmpItem); - pr_copyItemContent(this, lf, & pr->tmpItem); - li = 0; - while ((li < lf->head.len) && (pr->tmpItem.data[li] == '0')) { - li++; - } - pr->tmpItem.head.len = pr_removeSubstring(0,li,pr->tmpItem.data); - pr_copyItem(this, pr_WorkMem, &pr->tmpItem, & litem2); - if (pr->outOfMemory) return; - pr_appendItem(this, & (*first),& (*last),litem2); - } - break; - case PR_OIgnore: case PR_OPitch: case PR_OSpeed: case PR_OVolume: case PR_OPhonSVOXPA: case PR_OPhonSAMPA: case PR_OBreak: case PR_OMark: case PR_OPara: case PR_OSent: case PR_OPlay: - case PR_OUseSig: case PR_OGenFile: case PR_OAudioEdit: case PR_OContext: case PR_OVoice: - pr_genCommands(this, pr, network,lo,vars,& (*first),& (*last)); - if (pr->outOfMemory) return; - break; - default: - PICODBG_INFO(("unkown command")); - break; - } - lo = picokpr_getOutItemNextOfs(network, lo); - } -} - - -static picoos_int32 pr_attrVal (picokpr_Preproc network, picokpr_TokArrOffset tok, pr_TokSetEleWP type) -{ - - pr_TokSetEleWP tse; - picoos_int32 n; - picokpr_TokSetWP set; - - n = 0; - tse = PR_FIRST_TSE_WP; - set = picokpr_getTokSetWP(network, tok); - while (tse < type) { - if (((1<rbestpath.rlen) { - with__0 = & pr->rbestpath.rele[*i]; - li = 0; - if (*i > 0) { - while ((li < 127) && (li < pr->rbestpath.rele[*i].rdepth)) { - pr->lspaces[li++] = ' '; - } - } - pr->lspaces[li] = 0; - if (with__0->rprodname != 0) { - PICODBG_INFO(("pp path :%s%s(", pr->lspaces, picokpr_getVarStrPtr(with__0->rnetwork,with__0->rprodname))); - } - if ((pr->ritems[with__0->ritemid+1] != NULL) && (pr->ritems[with__0->ritemid+1]->head.type == PICODATA_ITEM_TOKEN)) { - PICODBG_INFO(("pp in (1): %s'%s'", pr->lspaces, pr->ritems[with__0->ritemid+1]->data)); - } - if ((pr->ritems[with__0->ritemid+1] != NULL)) { - while ((pr->rinItemList != NULL) && (pr->rinItemList != pr->ritems[with__0->ritemid+1]) && (pr->rinItemList->head.type != PICODATA_ITEM_TOKEN)) { - lit = pr->rinItemList; - pr->rinItemList = pr->rinItemList->next; - lit->next = NULL; - pr_copyItem(this, pr_WorkMem,& (*lit),& lcopy); - if (pr->outOfMemory) return; - pr_disposeItem(this, & lit); - pr_appendItem(this, & (*o),& (*ol),lcopy); - } - if (pr->rinItemList != NULL) { - lit = pr->rinItemList; - pr->rinItemList = pr->rinItemList->next; - lit->next = NULL; - } else { - lit = NULL; - } - } - wpset = picokpr_getTokSetWP(with__0->rnetwork, with__0->rtok); - npset = picokpr_getTokSetNP(with__0->rnetwork, with__0->rtok); - - if ((PR_TSE_MASK_PROD & wpset) != 0) { - if ((PR_TSE_MASK_VAR & wpset) != 0) { - lvar = pr_findVariable(lvars,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEVar)); - if (lvar == NULL) { - pr_ALLOCATE(this, pr_WorkMem, (void *) & lvar,(sizeof (*lvar))); - lvar->next = lvars; - lvar->id = pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEVar); - lvars = lvar; - } - pr_startItemList(& lvar->first,& lvar->last); - pr_getOutput(this, pr, & (*i),(d + 1),& lvar->first,& lvar->last); - if (pr->outOfMemory) return; - } else { - pr_startItemList(& ldit,& ldlit); - pr_getOutput(this, pr, & (*i),(d + 1),& ldit,& ldlit); - if (pr->outOfMemory) return; - } - (*i)++; - } else if ((PR_TSE_MASK_VAR & wpset) != 0) { - lvar = pr_findVariable(lvars,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEVar)); - if (lvar == NULL) { - pr_ALLOCATE(this, pr_WorkMem, (void *) & lvar,(sizeof (*lvar))); - lvar->next = lvars; - lvar->id = pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEVar); - lvars = lvar; - } - if (((PR_TSE_MASK_LEX & wpset) != 0) && ((PR_TSE_MASK_LETTER & npset) == 0)) { - if (lfirst) { - pr_newItem(this, pr_WorkMem,& lit, PICODATA_ITEM_TOKEN, sizeof(struct pr_ioItem), /*inItem*/FALSE); - if (pr->outOfMemory) return; - lit->head.type = PICODATA_ITEM_TOKEN; - lit->head.info1 = pr->ritems[with__0->ritemid+1]->head.info1; - lit->head.info2 = pr->ritems[with__0->ritemid+1]->head.info2; - if (pr->ritems[with__0->ritemid+1]->head.info1 == PICODATA_ITEMINFO1_TOKTYPE_SPACE) { - lit->head.len = pr_strcpy(lit->data, (picoos_uchar*)"_"); - } else { - lit->head.len = pr_strcpy(lit->data, pr->ritems[with__0->ritemid+1]->data); - } - lvar->first = lit; - lvar->last = lit; - lfirst = FALSE; - } else { - if ((pr->ritems[with__0->ritemid+1]->head.info1 == PICODATA_ITEMINFO1_TOKTYPE_SPACE)) { - lvar->last->head.len = pr_strcat(lvar->last->data,(picoos_uchar*)"_"); - } else { - lvar->last->head.len = pr_strcat(lvar->last->data,pr->ritems[with__0->ritemid+1]->data); - } - lvar->last->head.info1 = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; - lvar->last->head.info2 = -(1); - } - } else { - lvar->first = pr->ritems[with__0->ritemid+1]; - lvar->last = pr->ritems[with__0->ritemid+1]; - } - (*i)++; - } else if ((PR_TSE_MASK_OUT & wpset) != 0) { - pr_getOutputItemList(this, pr, with__0->rnetwork,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEOut),lvars,& (*o),& (*ol)); - if (pr->outOfMemory) return; - (*i)++; - } else if (((*i) < (pr->rbestpath.rlen - 1)) && (d != pr->rbestpath.rele[(*i) + 1].rdepth)) { - if ((*i > 0) && (with__0->rdepth-1) == pr->rbestpath.rele[*i + 1].rdepth) { - li = 0; - while ((li < 127) && (li < with__0->rdepth-1)) { - pr->lspaces[li++] = ' '; - } - pr->lspaces[li] = 0; - PICODBG_INFO(("pp path :%s)", pr->lspaces)); - } - return; - } else { - (*i)++; - } - if ((PR_TSE_MASK_LEX & wpset) == 0) { - lfirst = TRUE; - } - } - li = 0; - while ((li < 127) && (li < pr->rbestpath.rele[*i].rdepth-1)) { - pr->lspaces[li++] = ' '; - } - pr->lspaces[li] = 0; - PICODBG_INFO(("pp path :%s)", pr->lspaces)); -} - - -static void pr_outputPath (picodata_ProcessingUnit this, pr_subobj_t * pr) -{ - register struct pr_PathEle * with__0; - picoos_int32 li; - pr_ioItemPtr lf; - pr_ioItemPtr ll; - pr_ioItemPtr lit; - pr_ioItemPtr lit2; - pr_MemState lmemState; - picoos_bool lastPlayFileFound; - - pr_getMemState(this, pr_WorkMem, & lmemState); - lf = NULL; - ll = NULL; - li = -(1); - pr_getOutput(this, pr, & li,1,& lf,& ll); - if (pr->outOfMemory) return; - lastPlayFileFound = TRUE; - while (lf != NULL) { - lit = lf; - lf = lf->next; - lit->next = NULL; - if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PLAY)) { - lastPlayFileFound = picoos_FileExists(this->common, (picoos_char*)lit->data); - if (!lastPlayFileFound) { - PICODBG_WARN(("file '%s' not found; synthesizing enclosed text instead", lit->data)); - picoos_emRaiseWarning(this->common->em, PICO_EXC_CANT_OPEN_FILE, (picoos_char*)"", (picoos_char*)"file '%s' not found; synthesizing enclosed text instead",lit->data); - } - } - if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PHONEME) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_START)) { - pr->insidePhoneme = TRUE; - } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PHONEME)&& pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_END)) { - pr->insidePhoneme = FALSE; - } - if ((pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PLAY) && !lastPlayFileFound)) { - } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_IGNORE) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_START)) { - if (lastPlayFileFound) { - pr->rignore++; - } - } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_IGNORE) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_END)) { - if (lastPlayFileFound) { - if (pr->rignore > 0) { - pr->rignore--; - } - } - } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_IGNSIG) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_START) && !lastPlayFileFound) { - } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_IGNSIG) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_END) && !lastPlayFileFound) { - } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_CONTEXT)) { - if (pr->rignore <= 0) { - pr_setContext(this, pr, lit->data); - } - } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_VOICE)) { - if (pr->rignore <= 0) { - pr_copyItem(this, pr_DynMem,lit,& lit2); - if (pr->outOfMemory) return; - pr_appendItem(this, & pr->routItemList,& pr->rlastOutItem, lit2); - } - } else { - if ((pr->rignore <= 0) && !(pr->insidePhoneme && (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PLAY) || - pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_IGNSIG)))) { - PICODBG_INFO(("pp out(1): '%s'", lit->data)); - pr_copyItem(this, pr_DynMem,lit,& lit2); - if (pr->outOfMemory) return; - pr_appendItemToOutItemList(this, pr, & pr->routItemList,& pr->rlastOutItem,lit2); - if (pr->outOfMemory) return; - } - } - } - for (li = 0; lirbestpath.rlen; li++) { - with__0 = & pr->rbestpath.rele[li]; - pr_disposeItem(this, & pr->ritems[with__0->ritemid+1]); - } - pr_resetMemState(this, pr_WorkMem, lmemState); -} - -/* *****************************************************************************/ - -static void pr_compare (picoos_uchar str1lc[], picoos_uchar str2[], picoos_int16 * result) -{ - - picoos_int32 i; - picoos_int32 j; - picoos_int32 l; - picoos_uint32 pos; - picoos_bool finished1; - picoos_bool finished2; - picoos_bool done; - picobase_utf8char utf8char; - - pos = 0; - l = picobase_get_next_utf8char(str2, PR_MAX_DATA_LEN, & pos,utf8char); - picobase_lowercase_utf8_str(utf8char,(picoos_char*)utf8char,PICOBASE_UTF8_MAXLEN+1, &done); - l = picobase_det_utf8_length(utf8char[0]); - j = 0; - i = 0; - while ((i < PR_MAX_DATA_LEN) && (str1lc[i] != 0) && (l > 0) && (j <= 3) && (str1lc[i] == utf8char[j])) { - i++; - j++; - if (j >= l) { - l = picobase_get_next_utf8char(str2, PR_MAX_DATA_LEN, & pos,utf8char); - picobase_lowercase_utf8_str(utf8char,(picoos_char*)utf8char,PICOBASE_UTF8_MAXLEN+1, &done); - l = picobase_det_utf8_length(utf8char[0]); - j = 0; - } - } - finished1 = (i >= PR_MAX_DATA_LEN) || (str1lc[i] == 0); - finished2 = (j > 3) || (utf8char[j] == 0); - if (finished1 && finished2) { - *result = PR_EQUAL; - } else if (finished1) { - *result = PR_SMALLER; - } else if (finished2) { - *result = PR_LARGER; - } else { - if (str1lc[i] < utf8char[j]) { - *result = PR_SMALLER; - } else { - *result = PR_LARGER; - } - } -} - - -static picoos_bool pr_hasToken (picokpr_TokSetWP * tswp, picokpr_TokSetNP * tsnp) -{ - return (((( PR_TSE_MASK_SPACE | PR_TSE_MASK_DIGIT | PR_TSE_MASK_LETTER | PR_TSE_MASK_SEQ - | PR_TSE_MASK_CHAR | PR_TSE_MASK_BEGIN | PR_TSE_MASK_END) & (*tsnp)) != 0) || - ((PR_TSE_MASK_LEX & (*tswp)) != 0)); -} - - -static picoos_bool pr_getNextToken (picodata_ProcessingUnit this, pr_subobj_t * pr) -{ - register struct pr_PathEle * with__0; - picoos_int32 len; - picokpr_TokSetNP npset; - - len = pr->ractpath.rlen; - with__0 = & pr->ractpath.rele[len - 1]; - npset = picokpr_getTokSetNP(with__0->rnetwork, with__0->rtok); - if ((len > 0) && (pr->ractpath.rlen < PR_MAX_PATH_LEN) && ((PR_TSE_MASK_NEXT & npset) != 0)) { - pr_initPathEle(& pr->ractpath.rele[len]); - pr->ractpath.rele[len].rnetwork = with__0->rnetwork; - pr->ractpath.rele[len].rtok = picokpr_getTokNextOfs(with__0->rnetwork, with__0->rtok); - pr->ractpath.rele[len].rdepth = with__0->rdepth; - pr->ractpath.rlen++; - return TRUE; - } else { - if (len >= PR_MAX_PATH_LEN) { - PICODBG_INFO(("max path len reached (pr_getNextToken)")); - } - return FALSE; - } -} - - -static picoos_bool pr_getAltToken (picodata_ProcessingUnit this, pr_subobj_t * pr) -{ - register struct pr_PathEle * with__0; - picokpr_TokArrOffset lTok; - picokpr_TokSetNP npset; - - - with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; - if ((pr->ractpath.rlen > 0) && (pr->ractpath.rlen < PR_MAX_PATH_LEN)) { - npset = picokpr_getTokSetNP(with__0->rnetwork, with__0->rtok); - if (with__0->rcompare == PR_SMALLER) { - if ((PR_TSE_MASK_ALTL & npset) != 0) { - lTok = picokpr_getTokAltLOfs(with__0->rnetwork, with__0->rtok); - } else { - return FALSE; - } - } else { - if ((PR_TSE_MASK_ALTR & npset) != 0) { - lTok = picokpr_getTokAltROfs(with__0->rnetwork, with__0->rtok); - } else { - return FALSE; - } - } - with__0->rlState = PR_LSInit; - with__0->rtok = lTok; - with__0->ritemid = -1; - with__0->rcompare = -1; - with__0->rprodname = 0; - with__0->rprodprefcost = 0; - return TRUE; - } else { - if (pr->ractpath.rlen >= PR_MAX_PATH_LEN) { - PICODBG_INFO(("max path len reached (pr_getAltToken)")); - } - return FALSE; - } -} - - -static picoos_bool pr_findProduction (picodata_ProcessingUnit this, pr_subobj_t * pr, - picoos_uchar str[], picokpr_Preproc * network, picokpr_TokArrOffset * tokOfs) -{ - picoos_bool found; - picoos_int32 p; - picoos_int32 ind; - picoos_int32 i; - picoos_bool done; - picokpr_VarStrPtr lstrp; - picoos_int32 lprodarrlen; - - ind = 0; - pr_getTermPartStr(str,& ind,'.',pr->tmpStr1,& done); - pr_getTermPartStr(str,& ind,'.',pr->tmpStr2,& done); - found = FALSE; - - for (p=0; ppreproc[p] != NULL)) { - if (pr_strEqual(pr->tmpStr1, picokpr_getPreprocNetName(pr->preproc[p]))) { - i = 0; - lprodarrlen = picokpr_getProdArrLen(pr->preproc[p]); - while (!found && (i <= (lprodarrlen - 1))) { - lstrp = picokpr_getVarStrPtr(pr->preproc[p],picokpr_getProdNameOfs(pr->preproc[p], i)); - if (pr_strEqual(pr->tmpStr2, lstrp)) { - *network = pr->preproc[p]; - *tokOfs = picokpr_getProdATokOfs(pr->preproc[p], i); - return TRUE; - } - i++; - } - } - } - } - return FALSE; -} - - -static picoos_bool pr_getProdToken (picodata_ProcessingUnit this, pr_subobj_t * pr) -{ - register struct pr_PathEle * with__0; - picokpr_VarStrPtr lstrp; - picokpr_TokSetWP wpset; - - if ((pr->ractpath.rlen > 0) && (pr->ractpath.rlen < PR_MAX_PATH_LEN)) { - with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; - wpset = picokpr_getTokSetWP(with__0->rnetwork, with__0->rtok); - if ((PR_TSE_MASK_PROD & wpset) != 0) { - if ((PR_TSE_MASK_PRODEXT & wpset) != 0) { - pr_initPathEle(& pr->ractpath.rele[pr->ractpath.rlen]); - lstrp = picokpr_getVarStrPtr(with__0->rnetwork, pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEProdExt)); - if (pr_findProduction(this, pr, lstrp,& pr->ractpath.rele[pr->ractpath.rlen].rnetwork,& pr->ractpath.rele[pr->ractpath.rlen].rtok)) { - with__0->rprodname = picokpr_getProdNameOfs(with__0->rnetwork, pr_attrVal(with__0->rnetwork, with__0->rtok,PR_TSEProd)); - with__0->rprodprefcost = picokpr_getProdPrefCost(with__0->rnetwork, pr_attrVal(with__0->rnetwork,with__0->rtok,PR_TSEProd)); - pr->ractpath.rele[pr->ractpath.rlen].rdepth = with__0->rdepth + 1; - pr->ractpath.rlen++; - return TRUE; - } else { - return FALSE; - } - } else { - pr_initPathEle(& pr->ractpath.rele[pr->ractpath.rlen]); - pr->ractpath.rele[pr->ractpath.rlen].rnetwork = with__0->rnetwork; - pr->ractpath.rele[pr->ractpath.rlen].rtok = picokpr_getProdATokOfs(with__0->rnetwork, pr_attrVal(with__0->rnetwork, with__0->rtok,PR_TSEProd)); - with__0->rprodname = picokpr_getProdNameOfs(with__0->rnetwork, pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEProd)); - with__0->rprodprefcost = picokpr_getProdPrefCost(with__0->rnetwork, pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEProd)); - pr->ractpath.rele[pr->ractpath.rlen].rdepth = with__0->rdepth + 1; - pr->ractpath.rlen++; - return TRUE; - } - } - } - if (pr->ractpath.rlen >= PR_MAX_PATH_LEN) { - PICODBG_INFO(("max path len reached (pr_getProdToken)")); - } - return FALSE; -} - - -static picoos_bool pr_getProdContToken (picodata_ProcessingUnit this, pr_subobj_t * pr) -{ - picoos_int32 li; - - li = pr->ractpath.rlen - 1; - while ((li > 0) && !((pr->ractpath.rele[li].rdepth == (pr->ractpath.rele[pr->ractpath.rlen - 1].rdepth - 1)) && ((PR_TSE_MASK_PROD &picokpr_getTokSetWP(pr->ractpath.rele[li].rnetwork, pr->ractpath.rele[li].rtok)) != 0))) { - li--; - } - if (((li >= 0) && (pr->ractpath.rlen < PR_MAX_PATH_LEN) && (PR_TSE_MASK_NEXT &picokpr_getTokSetNP(pr->ractpath.rele[li].rnetwork, pr->ractpath.rele[li].rtok)) != 0)) { - pr_initPathEle(& pr->ractpath.rele[pr->ractpath.rlen]); - pr->ractpath.rele[pr->ractpath.rlen].rnetwork = pr->ractpath.rele[li].rnetwork; - pr->ractpath.rele[pr->ractpath.rlen].rtok = picokpr_getTokNextOfs(pr->ractpath.rele[li].rnetwork, pr->ractpath.rele[li].rtok); - pr->ractpath.rele[pr->ractpath.rlen].rdepth = pr->ractpath.rele[li].rdepth; - pr->ractpath.rlen++; - return TRUE; - } else { - if (pr->ractpath.rlen >= PR_MAX_PATH_LEN) { - PICODBG_INFO(("max path len reached (pr_getProdContToken)")); - } - return FALSE; - } -} - -/* *****************************************************************************/ - -static picoos_bool pr_getTopLevelToken (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_bool firstprod) -{ - if (firstprod) { - if (pr->actCtx != NULL) { - pr->prodList = pr->actCtx->rProdList; - } else { - pr->prodList = NULL; - } - } else if (pr->prodList != NULL) { - pr->prodList = pr->prodList->rNext; - } - if ((pr->prodList != NULL) && (pr->prodList->rProdOfs != 0) && (picokpr_getProdATokOfs(pr->prodList->rNetwork, pr->prodList->rProdOfs) != 0)) { - pr_initPathEle(& pr->ractpath.rele[pr->ractpath.rlen]); - pr->ractpath.rele[pr->ractpath.rlen].rdepth = 1; - pr->ractpath.rele[pr->ractpath.rlen].rnetwork = pr->prodList->rNetwork; - pr->ractpath.rele[pr->ractpath.rlen].rtok = picokpr_getProdATokOfs(pr->prodList->rNetwork, pr->prodList->rProdOfs); - pr->ractpath.rele[pr->ractpath.rlen].rlState = PR_LSInit; - pr->ractpath.rele[pr->ractpath.rlen].rcompare = -1; - pr->ractpath.rele[pr->ractpath.rlen].rprodname = picokpr_getProdNameOfs(pr->prodList->rNetwork, pr->prodList->rProdOfs); - pr->ractpath.rele[pr->ractpath.rlen].rprodprefcost = picokpr_getProdPrefCost(pr->prodList->rNetwork, pr->prodList->rProdOfs); - pr->ractpath.rlen++; - return TRUE; - } else { - return FALSE; - } -} - - -static picoos_bool pr_getToken (picodata_ProcessingUnit this, pr_subobj_t * pr) -{ - picoos_int32 ln; - picoos_int32 lid; - - ln = (pr->ractpath.rlen - 2); - while ((ln >= 0) && (pr->ractpath.rele[ln].ritemid == -1)) { - ln = ln - 1; - } - if (ln >= 0) { - lid = pr->ractpath.rele[ln].ritemid + 1; - } else { - lid = 0; - } - if (lid < pr->rnritems) { - pr->ractpath.rele[pr->ractpath.rlen - 1].ritemid = lid; - } else { - pr->ractpath.rele[pr->ractpath.rlen - 1].ritemid = -1; - } - return (lid < pr->rnritems); -} - - -static picoos_bool pr_getNextMultiToken (picodata_ProcessingUnit this, pr_subobj_t * pr) -{ - picoos_int32 len; - - len = pr->ractpath.rlen; - if ((len > 0) && (len < PR_MAX_PATH_LEN)) { - pr->ractpath.rele[len].rtok = pr->ractpath.rele[len - 1].rtok; - pr->ractpath.rele[len].ritemid = -(1); - pr->ractpath.rele[len].rcompare = pr->ractpath.rele[len - 1].rcompare; - pr->ractpath.rele[len].rdepth = pr->ractpath.rele[len - 1].rdepth; - pr->ractpath.rele[len].rlState = PR_LSInit; - pr->ractpath.rlen++; - return TRUE; - } else { - if (len >= PR_MAX_PATH_LEN) { - PICODBG_INFO(("max path len reached (pr_getNextMultiToken)")); - } - return FALSE; - } - return FALSE; -} - - -static pr_MatchState pr_matchMultiToken (picodata_ProcessingUnit this, pr_subobj_t * pr, - picokpr_TokSetNP npset, picokpr_TokSetWP wpset) -{ - picoos_bool lcontinue=FALSE; - picoos_bool lmatch=FALSE; - - if (lmatch) { - return PR_MSMatchedMulti; - } else if (lcontinue) { - return PR_MSMatchedContinue; - } else { - return PR_MSNotMatched; - } - pr = pr; /* avoid warning "var not used in this function"*/ - npset = npset; /* avoid warning "var not used in this function"*/ - wpset = wpset; /* avoid warning "var not used in this function"*/ - -} - - -static pr_MatchState pr_matchTokensSpace (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_int32 cmpres, - picokpr_TokSetNP npset, picokpr_TokSetWP wpset) -{ - register struct pr_PathEle * with__0; - picoos_int32 llen; - picoos_int32 lulen; - picoos_int32 li; - picokpr_VarStrPtr lstrp; - picoos_int32 leol; - - with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; - if ((PR_TSE_MASK_SPACE & npset) == 0) { - return PR_MSNotMatched; - } - lstrp = (picokpr_VarStrPtr)&pr->ritems[with__0->ritemid+1]->data; - lulen = picobase_utf8_length(lstrp,PR_MAX_DATA_LEN); - if (((PR_TSE_MASK_LEN & wpset) != 0) && (lulen != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSELen))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_MIN & wpset) != 0) && (lulen < pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMin))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_MAX & wpset) != 0) && (lulen > pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMax))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_STR & wpset) != 0) && (cmpres != PR_EQUAL)) { - return PR_MSNotMatched; - } - if ((PR_TSE_MASK_VAL & wpset) != 0) { - leol = 0; - llen = pr_strlen(lstrp); - for (li = 0; li < llen; li++) { - if (lstrp[li] == PR_EOL) { - leol++; - } - } - if (leol != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEVal)) { - return PR_MSNotMatched; - } - } - if (((PR_TSE_MASK_ID & wpset) != 0) && (pr->ritems[with__0->ritemid+1]->head.info2 != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEID))) { - return PR_MSNotMatched; - } - return PR_MSMatched; -} - - -static pr_MatchState pr_matchTokensDigit (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_int32 cmpres, - picokpr_TokSetNP npset, picokpr_TokSetWP wpset) -{ - register struct pr_PathEle * with__0; - picoos_int32 lulen; - picoos_int32 lval; - picokpr_VarStrPtr lstrp; - - with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; - if ((PR_TSE_MASK_DIGIT & npset) == 0) { - return PR_MSNotMatched; - } - lstrp = (picokpr_VarStrPtr)&pr->ritems[with__0->ritemid+1]->data; - lulen = picobase_utf8_length(lstrp,PR_MAX_DATA_LEN); - if ((((PR_TSE_MASK_LEN & wpset) != 0) && (lulen != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSELen)))) { - return PR_MSNotMatched; - } - lval = pr->ritems[with__0->ritemid+1]->val; - if (((PR_TSE_MASK_MIN & wpset) != 0) && (lval < pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMin))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_MAX & wpset) != 0) && (lval > pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMax))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_STR & wpset) != 0) && (cmpres != PR_EQUAL)) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_VAL & wpset) != 0) && (lval != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEVal))) { - return PR_MSNotMatched; - } - if ((((PR_TSE_MASK_NLZ & npset) != 0) && lstrp[0] == '0')) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_HEAD & wpset) != 0) && !(picokpr_isEqualHead(with__0->rnetwork,lstrp,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEHead)))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_MID & wpset) != 0) && !(picokpr_isEqualMid(with__0->rnetwork,lstrp,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMid)))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_TAIL & wpset) != 0) && !(picokpr_isEqualTail(with__0->rnetwork,lstrp,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSETail)))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_ID & wpset) != 0) && (pr->ritems[with__0->ritemid+1]->head.info2 != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEID))) { - return PR_MSNotMatched; - } - return PR_MSMatched; -} - - -static pr_MatchState pr_matchTokensSeq (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_int32 cmpres, - picokpr_TokSetNP npset, picokpr_TokSetWP wpset) -{ - - register struct pr_PathEle * with__0; - picoos_int32 lulen; - picokpr_VarStrPtr lstrp; - - with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; - - if (!((PR_TSE_MASK_SEQ & npset) != 0)) { - return PR_MSNotMatched; - } - lstrp = (picokpr_VarStrPtr)(void *) &pr->ritems[with__0->ritemid+1]->data; - lulen = picobase_utf8_length(lstrp,PR_MAX_DATA_LEN); - if (((PR_TSE_MASK_LEN & wpset) != 0) && (lulen != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSELen))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_MIN & wpset) != 0) && (lulen < pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMin))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_MAX & wpset) != 0) && (lulen > pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMax))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_STR & wpset) != 0) && (cmpres != PR_EQUAL)) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_HEAD & wpset) != 0) && !(picokpr_isEqualHead(with__0->rnetwork,lstrp,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEHead)))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_MID & wpset) != 0) && !(picokpr_isEqualMid(with__0->rnetwork,lstrp,PR_MAX_DATA_LEN ,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMid)))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_TAIL & wpset) != 0) && !(picokpr_isEqualTail(with__0->rnetwork,lstrp,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSETail)))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_ID & wpset) != 0) && (pr->ritems[with__0->ritemid+1]->head.info2 != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEID))) { - return PR_MSNotMatched; - } - return PR_MSMatched; -} - - -static pr_MatchState pr_matchTokensChar (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_int32 cmpres, - picokpr_TokSetNP npset, picokpr_TokSetWP wpset) -{ - register struct pr_PathEle * with__0; - - with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; - - if (!((PR_TSE_MASK_CHAR & npset) != 0)) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_STR & wpset) != 0) && (cmpres != PR_EQUAL)) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_ID & wpset) != 0) && (pr->ritems[with__0->ritemid+1]->head.info2 != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEID))) { - return PR_MSNotMatched; - } - return PR_MSMatched; -} - - -static pr_MatchState pr_matchTokensLetter (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_int32 cmpres, - picokpr_TokSetNP npset, picokpr_TokSetWP wpset) -{ - - register struct pr_PathEle * with__0; - picoos_int32 lulen; - picoos_int32 lromanval; - - with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; - - if ( !((PR_TSE_MASK_LETTER & npset) != 0)) { - return PR_MSNotMatched; - } - lulen = picobase_utf8_length(pr->ritems[with__0->ritemid+1]->data, PR_MAX_DATA_LEN); - if (((PR_TSE_MASK_LEN & wpset) != 0) && (lulen != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSELen))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_MIN & wpset) != 0) && (lulen < pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMin))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_MAX & wpset) != 0) && (lulen > pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMax))) { - return PR_MSNotMatched; - } - if ((PR_TSE_MASK_CI & npset) != 0) { - if (((PR_TSE_MASK_STR & wpset) != 0) && (cmpres != PR_EQUAL)) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_HEAD & wpset) != 0) && !(picokpr_isEqualHead(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->strci,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEHead)))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_MID & wpset) != 0) && !(picokpr_isEqualMid(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->strci,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMid)))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_TAIL & wpset) != 0) && !(picokpr_isEqualTail(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->strci,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSETail)))) { - return PR_MSNotMatched; - } - } else if ((PR_TSE_MASK_CIS & npset) != 0) { - if (((PR_TSE_MASK_STR & wpset) != 0) && !(picokpr_isEqual(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->strcis,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEStr)))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_HEAD & wpset) != 0) && !(picokpr_isEqualHead(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->strcis,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEHead)))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_MID & wpset) != 0) && !(picokpr_isEqualMid(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->strcis,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMid)))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_TAIL & wpset) != 0) && !(picokpr_isEqualTail(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->strcis,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSETail)))) { - return PR_MSNotMatched; - } - } else { - if (((PR_TSE_MASK_STR & wpset) != 0) && !(picokpr_isEqual(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->data,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEStr)))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_HEAD & wpset) != 0) && !(picokpr_isEqualHead(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->data,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEHead)))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_MID & wpset) != 0) && !(picokpr_isEqualMid(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->data,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMid)))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_TAIL & wpset) != 0) && !(picokpr_isEqualTail(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->data,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSETail)))) { - return PR_MSNotMatched; - } - } - if (((PR_TSE_MASK_AUC & npset) != 0) && !(pr->ritems[with__0->ritemid+1]->auc)) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_ALC & npset) != 0) && !(pr->ritems[with__0->ritemid+1]->alc)) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_SUC & npset) != 0) && !(pr->ritems[with__0->ritemid+1]->suc)) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_ROMAN & npset) != 0) && !(pr_isLatinNumber(pr->ritems[with__0->ritemid+1]->data,& lromanval))) { - return PR_MSNotMatched; - } - if (((PR_TSE_MASK_ID & wpset) != 0) && (pr->ritems[with__0->ritemid+1]->head.info2 != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEID))) { - return PR_MSNotMatched; - } - return PR_MSMatched; -} - - -static pr_MatchState pr_matchTokensBegin (picodata_ProcessingUnit this, pr_subobj_t * pr, - picokpr_TokSetNP npset, picokpr_TokSetWP wpset) -{ - npset = npset; /* avoid warning "var not used in this function"*/ - wpset = wpset; /* avoid warning "var not used in this function"*/ - if ((PR_TSE_MASK_BEGIN &picokpr_getTokSetNP(pr->ractpath.rele[pr->ractpath.rlen - 1].rnetwork, pr->ractpath.rele[pr->ractpath.rlen - 1].rtok)) != 0) { - return PR_MSMatched; - } else { - return PR_MSNotMatched; - } -} - - - -static pr_MatchState pr_matchTokensEnd (picodata_ProcessingUnit this, pr_subobj_t * pr, - picokpr_TokSetNP npset, picokpr_TokSetWP wpset) -{ - npset = npset; /* avoid warning "var not used in this function"*/ - wpset = wpset; /* avoid warning "var not used in this function"*/ - if ((PR_TSE_MASK_END &picokpr_getTokSetNP(pr->ractpath.rele[pr->ractpath.rlen - 1].rnetwork, pr->ractpath.rele[pr->ractpath.rlen - 1].rtok)) != 0) { - return PR_MSMatched; - } else { - return PR_MSNotMatched; - } -} - - -static pr_MatchState pr_matchTokens (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_int16 * cmpres) -{ - - register struct pr_PathEle * with__0; - picokpr_VarStrPtr lstrp; - picokpr_TokSetNP npset; - picokpr_TokSetWP wpset; - - with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; - npset = picokpr_getTokSetNP(with__0->rnetwork, with__0->rtok); - wpset = picokpr_getTokSetWP(with__0->rnetwork, with__0->rtok); - - *cmpres = PR_EQUAL; - if ((PR_TSE_MASK_STR & wpset) != 0) { - lstrp = picokpr_getVarStrPtr(with__0->rnetwork, pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEStr)); - pr_compare(pr->ritems[with__0->ritemid+1]->strci,lstrp,cmpres); - } - if (((PR_TSE_MASK_LEX & wpset) == PR_TSE_MASK_LEX) && ((PR_TSE_MASK_LETTER & npset) == 0)) { - return pr_matchMultiToken(this, pr, npset, wpset); - } else { - switch (pr->ritems[with__0->ritemid+1]->head.info1) { - case PICODATA_ITEMINFO1_TOKTYPE_BEGIN: - return pr_matchTokensBegin(this, pr, npset, wpset); - break; - case PICODATA_ITEMINFO1_TOKTYPE_END: - return pr_matchTokensEnd(this, pr, npset, wpset); - break; - case PICODATA_ITEMINFO1_TOKTYPE_SPACE: - return pr_matchTokensSpace(this, pr, *cmpres, npset, wpset); - break; - case PICODATA_ITEMINFO1_TOKTYPE_DIGIT: - return pr_matchTokensDigit(this, pr, *cmpres, npset, wpset); - break; - case PICODATA_ITEMINFO1_TOKTYPE_LETTER: - return pr_matchTokensLetter(this, pr, *cmpres, npset, wpset); - break; - case PICODATA_ITEMINFO1_TOKTYPE_SEQ: - return pr_matchTokensSeq(this, pr, *cmpres, npset, wpset); - break; - case PICODATA_ITEMINFO1_TOKTYPE_CHAR: - return pr_matchTokensChar(this, pr, *cmpres, npset, wpset); - break; - default: - PICODBG_INFO(("pr_matchTokens: unknown token type")); - return PR_MSNotMatched; - break; - } - } -} - - -static void pr_calcPathCost (struct pr_Path * path) -{ - picoos_int32 li; - picoos_bool lfirst; - picokpr_TokSetWP wpset; - picokpr_TokSetNP npset; -#if PR_TRACE_PATHCOST - picoos_uchar str[1000]; - picoos_uchar * strp; -#endif - -#if PR_TRACE_PATHCOST - str[0] = 0; -#endif - - lfirst = TRUE; - path->rcost = PR_COST_INIT; - for (li = 0; li < path->rlen; li++) { - if (li == 0) { - path->rcost = path->rcost + path->rele[li].rprodprefcost; - } - wpset = picokpr_getTokSetWP(path->rele[li].rnetwork, path->rele[li].rtok); - npset = picokpr_getTokSetNP(path->rele[li].rnetwork, path->rele[li].rtok); - if ((PR_TSE_MASK_COST & wpset) != 0) { - if (((PR_TSE_MASK_LEX & wpset) == PR_TSE_MASK_LEX) && ((PR_TSE_MASK_LETTER & npset) == 0)) { - if (lfirst) { - path->rcost = path->rcost - PR_COST + pr_attrVal(path->rele[li].rnetwork, path->rele[li].rtok, PR_TSECost); - } else { - path->rcost = path->rcost - PR_COST; - } - lfirst = FALSE; - } else { - path->rcost = path->rcost - PR_COST + pr_attrVal(path->rele[li].rnetwork, path->rele[li].rtok, PR_TSECost); - lfirst = TRUE; - } - } else if (pr_hasToken(& wpset,& npset)) { - path->rcost = path->rcost - PR_COST; - } -#if PR_TRACE_PATHCOST - if ((path->rele[li].rprodname != 0)) { - strp = picokpr_getVarStrPtr(path->rele[li].rnetwork, path->rele[li].rprodname); - picoos_strcat(str, (picoos_char *)" "); - picoos_strcat(str, strp); - } -#endif - } -#if PR_TRACE_PATHCOST - PICODBG_INFO(("pp cost: %i %s", path->rcost, str)); -#endif -} - - -void pr_processToken (picodata_ProcessingUnit this, pr_subobj_t * pr) -{ - register struct pr_PathEle * with__0; - picoos_bool ldummy; - picoos_int32 li; - picokpr_TokSetNP npset; - picokpr_TokSetWP wpset; - - do { - pr->rgState = PR_GSContinue; - if ((pr->ractpath.rlen == 0)) { - if (pr_getTopLevelToken(this, pr, FALSE)) { - pr->rgState = PR_GSContinue; - } else if (pr->rbestpath.rlen == 0) { - pr->rgState = PR_GSNotFound; - } else { - pr->rgState = PR_GSFound; - } - } else { - if (pr->maxPathLen < pr->ractpath.rlen) { - pr->maxPathLen = pr->ractpath.rlen; - } - with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; - switch (with__0->rlState) { - case PR_LSInit: - npset = picokpr_getTokSetNP(with__0->rnetwork, with__0->rtok); - wpset = picokpr_getTokSetWP(with__0->rnetwork, with__0->rtok); - if ((PR_TSE_MASK_ACCEPT & npset) != 0){ - if (with__0->rdepth == 1) { - pr_calcPathCost(&pr->ractpath); - if ((pr->rbestpath.rlen == 0) || (pr->ractpath.rcost < pr->rbestpath.rcost)) { - pr->rbestpath.rlen = pr->ractpath.rlen; - pr->rbestpath.rcost = pr->ractpath.rcost; - for (li = 0; li < pr->ractpath.rlen; li++) { - pr->rbestpath.rele[li] = pr->ractpath.rele[li]; - } - } - with__0->rlState = PR_LSGetNextToken; - } else { - with__0->rlState = PR_LSGetProdContToken; - } - } else if ((PR_TSE_MASK_PROD & wpset) != 0) { - with__0->rlState = PR_LSGetProdToken; - } else if ((PR_TSE_MASK_OUT & wpset) != 0) { - with__0->rlState = PR_LSGetNextToken; - } else if (pr_hasToken(& wpset,& npset)) { - with__0->rlState = PR_LSGetToken; - } else { - with__0->rlState = PR_LSGetNextToken; - } - break; - case PR_LSGetProdToken: - with__0->rlState = PR_LSGetAltToken; - ldummy = pr_getProdToken(this, pr); - break; - case PR_LSGetProdContToken: - with__0->rlState = PR_LSGetAltToken; - ldummy = pr_getProdContToken(this, pr); - break; - case PR_LSGoBack: - pr->ractpath.rlen--; - break; - case PR_LSGetToken: - if (pr_getToken(this, pr)) { - with__0->rlState = PR_LSMatch; - } else if (pr->forceOutput) { - with__0->rlState = PR_LSGetAltToken; - } else { - with__0->rlState = PR_LSGetToken2; - pr->rgState = PR_GSNeedToken; - } - break; - case PR_LSGetToken2: - if (pr_getToken(this, pr)) { - with__0->rlState = PR_LSMatch; - } else { - with__0->rlState = PR_LSGoBack; - } - break; - case PR_LSMatch: - switch (pr_matchTokens(this, pr, & with__0->rcompare)) { - case PR_MSMatched: - with__0->rlState = PR_LSGetNextToken; - break; - case PR_MSMatchedContinue: - with__0->rlState = PR_LSGetAltToken; - ldummy = pr_getNextMultiToken(this, pr); - break; - case PR_MSMatchedMulti: - with__0->rlState = PR_LSGetNextToken; - ldummy = pr_getNextMultiToken(this, pr); - break; - default: - with__0->rlState = PR_LSGetAltToken; - break; - } - break; - case PR_LSGetNextToken: - with__0->rlState = PR_LSGetAltToken; - ldummy = pr_getNextToken(this, pr); - break; - case PR_LSGetAltToken: - with__0->rlState = PR_LSGoBack; - ldummy = pr_getAltToken(this, pr); - break; - default: - PICODBG_INFO(("unhandled local state")); - break; - } - } - pr->nrIterations--; - } while ((pr->rgState == PR_GSContinue) && (pr->nrIterations > 0)); -} - - -void pr_process (picodata_ProcessingUnit this, pr_subobj_t * pr) -{ - switch (pr->rgState) { - case PR_GS_START: - case PR_GSFound: - case PR_GSNotFound: - pr->ractpath.rlen = 0; - pr->ractpath.rcost = PR_COST_INIT; - pr->rbestpath.rlen = 0; - pr->rbestpath.rcost = PR_COST_INIT; - if (pr_getTopLevelToken(this, pr, TRUE)) { - pr->rgState = PR_GSContinue; - } else { - pr->rgState = PR_GSNotFound; - } - break; - case PR_GSContinue: - pr_processToken(this, pr); - break; - case PR_GSNeedToken: - pr->rgState = PR_GSContinue; - break; - default: - pr->rgState = PR_GS_START; - break; - } -} - - -static void pr_prepareItem (picodata_ProcessingUnit this, pr_subobj_t * pr, pr_ioItemPtr item) -{ - pr->ritems[pr->rnritems + 1] = item; - pr->rnritems++; -} - - -static void pr_processItems (picodata_ProcessingUnit this, pr_subobj_t * pr) -{ - pr_ioItemPtr lit; - pr_MemState lmemState; - - pr_getMemState(this, pr_WorkMem,& lmemState); - - while ((pr->rinItemList != NULL) && (pr->rinItemList->head.type != PICODATA_ITEM_TOKEN)) { - lit = pr->rinItemList; - PICODBG_INFO(("pp in (0)")); - PICODBG_INFO(("pp out(0)")); - pr->rinItemList = pr->rinItemList->next; - lit->next = NULL; - if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PHONEME) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_START)) { - pr->insidePhoneme = TRUE; - } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PHONEME) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_END)) { - pr->insidePhoneme = FALSE; - } - if (pr->insidePhoneme && (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PLAY) || pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_IGNSIG))) { - pr_disposeItem(this, & lit); - } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_CONTEXT)) { - pr_setContext(this, pr, lit->data); - pr_disposeItem(this, & lit); - } else if (pr->rignore <= 0) { - pr_appendItemToOutItemList(this, pr, & pr->routItemList,& pr->rlastOutItem,lit); - if (pr->outOfMemory) return; - } else { - pr_disposeItem(this, & lit); - } - pr->rgState = PR_GS_START; - } - if (pr->rinItemList != NULL) { - pr_process(this, pr); - if (pr->rgState == PR_GSNotFound) { - lit = pr->rinItemList; - pr->rinItemList = pr->rinItemList->next; - lit->next = NULL; - PICODBG_INFO(("pp in (2): '%s'", lit->data)); - if (pr->rignore <= 0) { - PICODBG_INFO(("pp out(2): '%s'", lit->data)); - } - - if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PHONEME) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_START)) { - pr->insidePhoneme = TRUE; - } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PHONEME) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_END)) { - pr->insidePhoneme = FALSE; - } - if (((pr->rignore <= 0) && !((pr->insidePhoneme && (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PLAY) || pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_IGNSIG)))))) { - pr_appendItemToOutItemList(this, pr, & pr->routItemList,& pr->rlastOutItem,lit); - if (pr->outOfMemory) return; - } else { - pr_disposeItem(this, & lit); - } - pr->rgState = PR_GS_START; - pr->rnritems = 0; - } else if (pr->rgState == PR_GSFound) { - pr_outputPath(this, pr); - if (pr->outOfMemory) return; - pr->rgState = PR_GS_START; - pr->rnritems = 0; - } - } - if (pr->rinItemList == NULL) { - pr->rlastInItem = NULL; - } else if (pr->rnritems == 0) { - lit = pr->rinItemList; - while (lit != NULL) { - if (lit->head.type == PICODATA_ITEM_TOKEN) { - pr_prepareItem(this, pr, lit); - } - lit = lit->next; - } - } - pr_resetMemState(this, pr_WorkMem,lmemState); -} - - - -extern void pr_treatItem (picodata_ProcessingUnit this, pr_subobj_t * pr, pr_ioItemPtr item) -{ - pr_ioItemPtr lit; - - pr_startItemList(& pr->routItemList,& pr->rlastOutItem); - - if (!PR_ENABLED || (pr->rgState == PR_GSNoPreproc)) { - /* preprocessing disabled or no preproc networks available: - append items directly to output item list */ - PICODBG_INFO(("pp in (3): '%s'", item->data)); - PICODBG_INFO(("pp out(3): '%s'", item->data)); - pr_appendItemToOutItemList(this, pr, & pr->routItemList,& pr->rlastOutItem,item); - } else { - - if (pr->actCtxChanged) { - pr->rgState = PR_GS_START; - pr->ractpath.rcost = PR_COST_INIT; - pr->ractpath.rlen = 0; - pr->rbestpath.rcost = PR_COST_INIT; - pr->rbestpath.rlen = 0; - pr->prodList = NULL; - pr->rnritems = 0; - pr->actCtxChanged = FALSE; - } - if (pr_isCmdType(item , PICODATA_ITEMINFO1_CMD_CONTEXT) || pr_isCmdType(item, PICODATA_ITEMINFO1_CMD_FLUSH)) { - /* context switch or flush: force processing and empty input item list */ - pr->forceOutput = TRUE; - } - pr_appendItem(this, & pr->rinItemList,& pr->rlastInItem, item); - if (pr->rnritems == 0) { - lit = pr->rinItemList; - while (lit != NULL) { - if (lit->head.type == PICODATA_ITEM_TOKEN) { - pr_prepareItem(this, pr, lit); - } - lit = lit->next; - } - } else if (item->head.type == PICODATA_ITEM_TOKEN) { - pr_prepareItem(this, pr, item); - } - } -} - -/* *****************************************************************************/ -/* *****************************************************************************/ -/* *****************************************************************************/ - - -pico_status_t prReset(register picodata_ProcessingUnit this) -{ - picoos_int32 i; - pr_subobj_t * pr; - - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - pr = (pr_subobj_t *) this->subObj; - - pr->rinItemList = NULL; - pr->rlastInItem = NULL; - pr->routItemList = NULL; - pr->rlastOutItem = NULL; - pr->ractpath.rcost = PR_COST_INIT; - pr->ractpath.rlen = 0; - pr->rbestpath.rcost = PR_COST_INIT; - pr->rbestpath.rlen = 0; - pr->rnritems = 0; - pr->ritems[0] = NULL; - pr->rignore = 0; - pr->spellMode = 0; - pr->maxPathLen = 0; - pr->insidePhoneme = FALSE; - pr->saveFile[0] = 0; - - pr->outReadPos = 0; - pr->outWritePos = 0; - pr->inBufLen = 0; - - pr->rgState = PR_GSNoPreproc; - for (i=0; ipreproc[i] != NULL) { - pr->rgState = PR_GS_START; - } - } - pr->actCtx = pr_findContext(pr->ctxList, (picoos_uchar*)PICO_CONTEXT_DEFAULT); - pr->actCtxChanged = FALSE; - pr->prodList = NULL; - - if (((picoos_uint32)pr->pr_WorkMem % PICOOS_ALIGN_SIZE) == 0) { - pr->workMemTop = 0; - } - else { - pr->workMemTop = PICOOS_ALIGN_SIZE - ((picoos_uint32)pr->pr_WorkMem % PICOOS_ALIGN_SIZE); - } - pr->maxWorkMemTop=0; - pr->dynMemSize=0; - pr->maxDynMemSize=0; - /* this is ok to be in 'initialize' because it is a private memory within pr. Creating a new mm - * here amounts to resetting this internal memory - */ - pr->dynMemMM = picoos_newMemoryManager((void *)pr->pr_DynMem, PR_DYN_MEM_SIZE, - /*enableMemProt*/ FALSE); - pr->outOfMemory = FALSE; - - pr->forceOutput = FALSE; - - - pr->xsampa_parser = picokfst_getFST(this->voice->kbArray[PICOKNOW_KBID_FST_XSAMPA_PARSE]); - - pr->svoxpa_parser = picokfst_getFST(this->voice->kbArray[PICOKNOW_KBID_FST_SVOXPA_PARSE]); - - pr->xsampa2svoxpa_mapper = picokfst_getFST(this->voice->kbArray[PICOKNOW_KBID_FST_XSAMPA2SVOXPA]); - - - - return PICO_OK; -} - - -pico_status_t prInitialize(register picodata_ProcessingUnit this) -{ -/* - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } -*/ - return prReset(this); -} - - -pico_status_t prTerminate(register picodata_ProcessingUnit this) -{ - return PICO_OK; -} - -picodata_step_result_t prStep(register picodata_ProcessingUnit this, picoos_int16 mode, picoos_uint16 * numBytesOutput); - -pico_status_t prSubObjDeallocate(register picodata_ProcessingUnit this, - picoos_MemoryManager mm) -{ - pr_subobj_t * pr; - - if (NULL != this) { - pr = (pr_subobj_t *) this->subObj; - mm = mm; /* avoid warning "var not used in this function"*/ - PICODBG_INFO(("max pr_WorkMem: %i of %i", pr->maxWorkMemTop, PR_WORK_MEM_SIZE)); - PICODBG_INFO(("max pr_DynMem: %i of %i", pr->maxDynMemSize, PR_DYN_MEM_SIZE)); - - pr_disposeContextList(this); - picoos_deallocate(this->common->mm, (void *) &this->subObj); - } - return PICO_OK; -} - -picodata_ProcessingUnit picopr_newPreprocUnit(picoos_MemoryManager mm, picoos_Common common, - picodata_CharBuffer cbIn, picodata_CharBuffer cbOut, - picorsrc_Voice voice) -{ - picoos_int32 i; - pr_subobj_t * pr; - - - picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, cbOut, voice); - if (this == NULL) { - return NULL; - } - - this->initialize = prInitialize; - PICODBG_DEBUG(("set this->step to prStep")); - this->step = prStep; - this->terminate = prTerminate; - this->subDeallocate = prSubObjDeallocate; - this->subObj = picoos_allocate(mm, sizeof(pr_subobj_t)); -#if PR_TRACE_MEM || PR_TRACE_MAX_MEM - PICODBG_INFO(("preproc alloc: %i", sizeof(pr_subobj_t))); - PICODBG_INFO(("max dyn size: %i", PR_MAX_PATH_LEN*((((PR_IOITEM_MIN_SIZE+2) + PICOOS_ALIGN_SIZE - 1) / PICOOS_ALIGN_SIZE) * PICOOS_ALIGN_SIZE + 16))); -#endif - if (this->subObj == NULL) { - picoos_deallocate(mm, (void *)&this); - return NULL; - } - pr = (pr_subobj_t *) this->subObj; - - pr->graphs = picoktab_getGraphs(this->voice->kbArray[PICOKNOW_KBID_TAB_GRAPHS]); - pr->preproc[0] = picokpr_getPreproc(this->voice->kbArray[PICOKNOW_KBID_TPP_MAIN]); - for (i=0; ipreproc[1+i] = picokpr_getPreproc(this->voice->kbArray[PICOKNOW_KBID_TPP_USER_1+i]); - } - - if (pr_createContextList(this) != PICO_OK) { - pr_disposeContextList(this); - picoos_deallocate(mm, (void *)&this); - return NULL; - } - prInitialize(this); - return this; -} - -/** - * fill up internal buffer - */ -picodata_step_result_t prStep(register picodata_ProcessingUnit this, - picoos_int16 mode, picoos_uint16 * numBytesOutput) -{ - register pr_subobj_t * pr; - pr_ioItemPtr it; - picoos_int32 len, i; - pico_status_t rv; - picoos_int32 id; - picoos_uint8 info1; - picoos_uint8 info2; - picoos_int32 nrUtfChars; - picoos_uint32 pos; - picobase_utf8char inUtf8char, outUtf8char; - picoos_int32 inUtf8charlen, outUtf8charlen; - picoos_int32 lenpos; - picoos_bool ldone; - picoos_bool split; - - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - pr = (pr_subobj_t *) this->subObj; - - if (pr->outOfMemory) return PICODATA_PU_ERROR; - - mode = mode; /* avoid warning "var not used in this function"*/ - pr->nrIterations = PR_MAX_NR_ITERATIONS; - - *numBytesOutput = 0; - while (1) { /* exit via return */ - if ((pr->outWritePos - pr->outReadPos) > 0) { - /* deliver the data in the output buffer */ - if (picodata_cbPutItem(this->cbOut, &pr->outBuf[pr->outReadPos], pr->outWritePos - pr->outReadPos, numBytesOutput) == PICO_OK) { - pr->outReadPos += *numBytesOutput; - if (pr->outWritePos == pr->outReadPos) { - pr->outWritePos = 0; - pr->outReadPos = 0; - } - } - else { - return PICODATA_PU_OUT_FULL; - } - } - else if (pr->routItemList != NULL) { - /* there are item(s) in the output item list, move them to the output buffer */ - it = pr->routItemList; - pr->routItemList = pr->routItemList->next; - if (pr->routItemList == NULL) { - pr->rlastOutItem = NULL; - } - if (it->head.type == PICODATA_ITEM_TOKEN) { - if ((it->head.info1 != PICODATA_ITEMINFO1_TOKTYPE_SPACE) && (it->head.len > 0)) { - nrUtfChars = picobase_utf8_length(it->data, PR_MAX_DATA_LEN); - if ((nrUtfChars == 1) - && (((id = picoktab_graphOffset(pr->graphs, it->data)) > 0)) - && picoktab_getIntPropPunct(pr->graphs, id, &info1, &info2)) { - /* single punctuation chars have to be delivered as PICODATA_ITEM_PUNC items - instead as PICODATA_ITEM_WORDGRAPH items */ - pr->outBuf[pr->outWritePos++] = PICODATA_ITEM_PUNC; - pr->outBuf[pr->outWritePos++] = info1; - pr->outBuf[pr->outWritePos++] = info2; - pr->outBuf[pr->outWritePos++] = 0; - PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], - (picoos_uint8 *)"pr: ", pr->outBuf, pr->outWritePos); - } - else { - /* do subgraphs substitutions and deliver token items as PICODATA_ITEM_WORDGRAPH - items to the output buffer */ - split = FALSE; - pr->outBuf[pr->outWritePos++] = PICODATA_ITEM_WORDGRAPH; - pr->outBuf[pr->outWritePos++] = PICODATA_ITEMINFO1_NA; - pr->outBuf[pr->outWritePos++] = PICODATA_ITEMINFO2_NA; - lenpos=pr->outWritePos; - pr->outBuf[pr->outWritePos++] = 0; - pos = 0; - len = pr_strlen(it->data); - while (pos < (picoos_uint32)len) { - if (picobase_get_next_utf8char(it->data, it->head.len, &pos, inUtf8char)) { - if (inUtf8char[0] <= 32) { - /* do not add whitespace characters to the output buffer, - but initiate token splitting instead - - */ - split = TRUE; - } - else if (((id = picoktab_graphOffset(pr->graphs, inUtf8char)) > 0) && picoktab_getStrPropGraphsubs1(pr->graphs, id, outUtf8char)) { - if (split) { - /* split the token, eg. start a new item */ - pr->outBuf[pr->outWritePos++] = PICODATA_ITEM_WORDGRAPH; - pr->outBuf[pr->outWritePos++] = PICODATA_ITEMINFO1_NA; - pr->outBuf[pr->outWritePos++] = PICODATA_ITEMINFO2_NA; - lenpos=pr->outWritePos; - pr->outBuf[pr->outWritePos++] = 0; - } - outUtf8charlen = picobase_det_utf8_length(outUtf8char[0]); - for (i=0; ioutBuf[pr->outWritePos++] = outUtf8char[i]; - pr->outBuf[lenpos]++; - } - if (picoktab_getStrPropGraphsubs2(pr->graphs, id, outUtf8char)) { - outUtf8charlen = picobase_det_utf8_length(outUtf8char[0]); - for (i=0; ioutBuf[pr->outWritePos++] = outUtf8char[i]; - pr->outBuf[lenpos]++; - } - } - split = FALSE; - } - else { - if (split) { - /* split the token, eg. start a new item */ - pr->outBuf[pr->outWritePos++] = PICODATA_ITEM_WORDGRAPH; - pr->outBuf[pr->outWritePos++] = PICODATA_ITEMINFO1_NA; - pr->outBuf[pr->outWritePos++] = PICODATA_ITEMINFO2_NA; - lenpos=pr->outWritePos; - pr->outBuf[pr->outWritePos++] = 0; - } - inUtf8charlen = picobase_det_utf8_length(inUtf8char[0]); - for (i=0; ioutBuf[pr->outWritePos++] = inUtf8char[i]; - pr->outBuf[lenpos]++; - } - split = FALSE; - } - } - } - PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], - (picoos_uint8 *)"pr: ", pr->outBuf, pr->outWritePos); - } - } - } - else { - /* handle all other item types and put them to the output buffer */ - pr->outBuf[pr->outWritePos++] = it->head.type; - pr->outBuf[pr->outWritePos++] = it->head.info1; - pr->outBuf[pr->outWritePos++] = it->head.info2; - pr->outBuf[pr->outWritePos++] = it->head.len; - for (i=0; ihead.len; i++) { - pr->outBuf[pr->outWritePos++] = it->data[i]; - } - PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], - (picoos_uint8 *)"pr: ", pr->outBuf, pr->outWritePos); - } - pr_disposeItem(this, &it); - } - else if (pr->forceOutput) { - pr_processItems(this, pr); - if (pr->rinItemList == NULL) { - pr->forceOutput = FALSE; - } - } - else if ((pr->rgState != PR_GSNeedToken) && (pr->rinItemList != NULL)) { - pr_processItems(this, pr); - } - else if (pr->inBufLen > 0) { - /* input data is available in the input buffer, copy it to an input item - and treat it */ - if (pr->dynMemSize < (45*PR_DYN_MEM_SIZE / 100)) { - pr_newItem(this, pr_DynMem, &it, pr->inBuf[0], pr->inBuf[3], /*inItem*/TRUE); - if (pr->outOfMemory) return PICODATA_PU_ERROR; - it->head.type = pr->inBuf[0]; - it->head.info1 = pr->inBuf[1]; - it->head.info2 = pr->inBuf[2]; - it->head.len = pr->inBuf[3]; - for (i=0; iinBuf[3]; i++) { - it->data[i] = pr->inBuf[4+i]; - } - it->data[pr->inBuf[3]] = 0; - if ((pr->inBuf[0] == PICODATA_ITEM_TOKEN) && ((pr->inBuf[1] == PICODATA_ITEMINFO1_TOKTYPE_DIGIT))) { - it->val = tok_tokenDigitStrToInt(this, pr, it->data); - } else { - it->val = 0; - } - if (pr->inBuf[0] == PICODATA_ITEM_TOKEN) { - picobase_lowercase_utf8_str(it->data,it->strci,PR_MAX_DATA_LEN, &ldone); - pr_firstLetterToLowerCase(it->data,it->strcis); - it->alc = picobase_is_utf8_lowercase(it->data,PR_MAX_DATA_LEN); - it->auc = picobase_is_utf8_uppercase(it->data,PR_MAX_DATA_LEN); - it->suc = pr_isSUC(it->data); - } - - pr_treatItem(this, pr, it); - if (pr->outOfMemory) return PICODATA_PU_ERROR; - pr_processItems(this, pr); - pr->inBufLen = 0; - } - else { - pr->forceOutput = TRUE; - } - } - else { - /* there is not data in the output buffer and there is no data in the output item list, so - check whether input data is available */ - rv = picodata_cbGetItem(this->cbIn, pr->inBuf, IN_BUF_SIZE+PICODATA_ITEM_HEADSIZE, &pr->inBufLen); - if (PICO_OK == rv) { - } else if (PICO_EOF == rv) { - /* there was no item in the char buffer */ - return PICODATA_PU_IDLE; - } else if ((PICO_EXC_BUF_UNDERFLOW == rv) || (PICO_EXC_BUF_OVERFLOW == rv)) { - pr->inBufLen = 0; - PICODBG_ERROR(("problem getting item")); - picoos_emRaiseException(this->common->em, rv, NULL, NULL); - return PICODATA_PU_ERROR; - } else { - pr->inBufLen = 0; - PICODBG_ERROR(("problem getting item, unhandled")); - picoos_emRaiseException(this->common->em, rv, NULL, NULL); - return PICODATA_PU_ERROR; - } - } -#if PR_TRACE_MEM - PICODBG_INFO(("memory: dyn=%u, work=%u", pr->dynMemSize, pr->workMemTop)); -#endif - if (pr->nrIterations <= 0) { - return PICODATA_PU_BUSY; - } - } /* while */ - return PICODATA_PU_ERROR; -} - -#ifdef __cplusplus -} -#endif - - - -/* end */ diff --git a/lib/picopr.h b/lib/picopr.h deleted file mode 100644 index 3ade5c9..0000000 --- a/lib/picopr.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 picopr.h - * - * text preprocessor PU - include file - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -/** - * @addtogroup picopr - * - * Text Pre Processing module \n - * -*/ -#ifndef PICOPR_H_ -#define PICOPR_H_ - -#include "picoos.h" -#include "picodata.h" -#include "picorsrc.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -picodata_ProcessingUnit picopr_newPreprocUnit( - picoos_MemoryManager mm, - picoos_Common common, - picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, - picorsrc_Voice voice); - -#define PICOPR_OUTBUF_SIZE 256 - -#ifdef __cplusplus -} -#endif - - -#endif /*PICOPR_H_*/ diff --git a/lib/picorsrc.c b/lib/picorsrc.c deleted file mode 100644 index d6e1e51..0000000 --- a/lib/picorsrc.c +++ /dev/null @@ -1,1028 +0,0 @@ -/* - * 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 picorsrc.c - * - * 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" - -/* knowledge layer */ -#include "picoknow.h" - -#include "picokdt.h" -#include "picoklex.h" -#include "picokfst.h" -#include "picokpdf.h" -#include "picoktab.h" -#include "picokpr.h" - -#include "picorsrc.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -#if defined(PICO_DEBUG) -#include "picokdbg.h" -#endif - - -/** object : Resource - * shortcut : rsrc - * - */ -typedef struct picorsrc_resource { - picoos_uint32 magic; /* magic number used to validate handles */ - /* next connects all active resources of a resource manager and the garbaged resources of the manager's free list */ - picorsrc_Resource next; - picorsrc_resource_type_t type; - picorsrc_resource_name_t name; - picoos_int8 lockCount; /* count of current subscribers of this resource */ - picoos_File file; - picoos_uint8 * raw_mem; /* pointer to allocated memory. NULL if preallocated. */ - /* picoos_uint32 size; */ - picoos_uint8 * start; /* start of content (after header) */ - picoknow_KnowledgeBase kbList; -} picorsrc_resource_t; - - -#define MAGIC_MASK 0x7049634F /* pIcO */ - -#define SET_MAGIC_NUMBER(res) \ - (res)->magic = ((picoos_uint32) (res)) ^ MAGIC_MASK - -#define CHECK_MAGIC_NUMBER(res) \ - ((res)->magic == (((picoos_uint32) (res)) ^ MAGIC_MASK)) - - - -/** - * Returns non-zero if 'this' is a valid resource handle, zero otherwise. - */ -picoos_int16 picoctrl_isValidResourceHandle(picorsrc_Resource this) -{ - return (this != NULL) && CHECK_MAGIC_NUMBER(this); -} - - -static picorsrc_Resource picorsrc_newResource(picoos_MemoryManager mm) -{ - picorsrc_Resource this = picoos_allocate(mm, sizeof(*this)); - if (NULL != this) { - SET_MAGIC_NUMBER(this); - /* initialize */ - this->name[0] = NULLC; - /* picoos_strlcpy(this->name, name,PICORSRC_MAX_RSRC_NAME_SIZ); */ - this->next = NULL; - this->type = PICORSRC_TYPE_NULL; - this->lockCount = 0; - this->file = NULL; - this->raw_mem = NULL; - this->start = NULL; - this->kbList = NULL; - /* this->size=0; */ - } - return this; -} - -static void picorsrc_disposeResource(picoos_MemoryManager mm, picorsrc_Resource * this) -{ - if (NULL != (*this)) { - (*this)->magic ^= 0xFFFEFDFC; - /* we have to explicitly free 'raw_mem' here because in testing - scenarios (where memory protection functionality is enabled) - it might be allocated aside from normal memory */ - if ((*this)->raw_mem != NULL) { - picoos_deallocProtMem(mm, (void *) &(*this)->raw_mem); - } - picoos_deallocate(mm,(void * *)this); - } -} - - - - -static void picorsrc_initializeVoice(picorsrc_Voice this) -{ - picoos_uint16 i; - if (NULL != this) { - /* initialize */ - for (i=0; ikbArray[i] = NULL; - } - this->numResources = 0; - this->next = NULL; - } -} - -static picorsrc_Voice picorsrc_newVoice(picoos_MemoryManager mm) -{ - picorsrc_Voice this = (picorsrc_Voice) picoos_allocate(mm,sizeof(*this)); - picorsrc_initializeVoice(this); - return this; -} - -/* -static void picorsrc_disposeVoice(picoos_MemoryManager mm, picorsrc_Voice * this) -{ - if (NULL != (*this)) { - - picoos_deallocate(mm,(void *)this); - } -} -*/ - - -/** object : VoiceDefinition - * shortcut : vdef - * - */ - -typedef struct picorsrc_voice_definition * picorsrc_VoiceDefinition; - -typedef struct picorsrc_voice_definition { - picoos_char voiceName[PICO_MAX_VOICE_NAME_SIZE]; - picoos_uint8 numResources; - picorsrc_resource_name_t resourceName[PICO_MAX_NUM_RSRC_PER_VOICE]; - picorsrc_VoiceDefinition next; -} picorsrc_voice_definition_t; - - -static picorsrc_VoiceDefinition picorsrc_newVoiceDefinition(picoos_MemoryManager mm) -{ - /* picoos_uint8 i; */ - picorsrc_VoiceDefinition this = (picorsrc_VoiceDefinition) picoos_allocate(mm,sizeof(*this)); - if (NULL != this) { - /* initialize */ - this->voiceName[0] = NULLC; - this->numResources = 0; - /* - for (i=0; i < PICO_MAX_NUM_RSRC_PER_VOICE; i++) { - this->resourceName[i][0] = NULLC; - } - */ - this->next = NULL; - } - return this; -} - -/* -static void picorsrc_disposeVoiceDefinition(picoos_MemoryManager mm, picorsrc_VoiceDefinition * this) -{ - if (NULL != (*this)) { - - picoos_deallocate(mm,(void *)this); - } -} -*/ - - - -/** object : ResourceManager - * shortcut : rm - * - */ -typedef struct picorsrc_resource_manager { - picoos_Common common; - picoos_uint16 numResources; - picorsrc_Resource resources, freeResources; - picoos_uint16 numVoices; - picorsrc_Voice voices, freeVoices; - picoos_uint16 numVdefs; - picorsrc_VoiceDefinition vdefs, freeVdefs; - picoos_uint16 numKbs; - picoknow_KnowledgeBase freeKbs; - picoos_header_string_t tmpHeader; -} picorsrc_resource_manager_t; - -pico_status_t picorsrc_createDefaultResource(picorsrc_ResourceManager this /*, - picorsrc_Resource * resource */); - - -picorsrc_ResourceManager picorsrc_newResourceManager(picoos_MemoryManager mm, picoos_Common common /* , picoos_char * configFile */) -{ - picorsrc_ResourceManager this = picoos_allocate(mm,sizeof(*this)); - if (NULL != this) { - /* initialize */ - this->common = common; - this->numResources = 0; - this->resources = NULL; - this->freeResources = NULL; - this->numVoices = 0; - this->voices = NULL; - this->freeVoices = NULL; - this->numVdefs = 0; - this->vdefs = NULL; - this->freeVdefs = NULL; - } - return this; -} - -void picorsrc_disposeResourceManager(picoos_MemoryManager mm, picorsrc_ResourceManager * this) -{ - if (NULL != (*this)) { - /* terminate */ - picoos_deallocate(mm,(void *)this); - } -} - - -/* ******* accessing resources **************************************/ - - -static pico_status_t findResource(picorsrc_ResourceManager this, picoos_char * resourceName, picorsrc_Resource * rsrc) { - picorsrc_Resource r; - if (NULL == this) { - return PICO_ERR_NULLPTR_ACCESS; - } - r = this->resources; - while (NULL != r && (0 != picoos_strcmp(r->name,resourceName))) { - r = r->next; - } - *rsrc = r; - return PICO_OK; -} - -static picoos_uint8 isResourceLoaded(picorsrc_ResourceManager this, picoos_char * resourceName) { - picorsrc_Resource res; - - if (PICO_OK == findResource(this, resourceName,&res)){ - return (NULL != res); - } else { - return FALSE; - } - } - -static pico_status_t parse_resource_name(picoos_char * fileName) -{ - PICODBG_DEBUG(("analysing file name %s",fileName)); - if (picoos_has_extension(fileName, - (picoos_char *)PICO_BIN_EXTENSION)) { - return PICO_OK; - } else { - return PICO_EXC_UNEXPECTED_FILE_TYPE; - } -} - - - -static pico_status_t readHeader(picorsrc_ResourceManager this, - picoos_FileHeader header, picoos_uint32 * headerlen, picoos_File file) -{ - - picoos_uint16 hdrlen1; - picoos_uint32 n; - pico_status_t status; - - - /* read PICO header */ - status = picoos_readPicoHeader(file, headerlen); - if (PICO_OK == status) { - - } else { - return picoos_emRaiseException(this->common->em,status,NULL,(picoos_char *)"problem reading file header"); - } - /* read header length (excluding length itself) */ - status = picoos_read_pi_uint16(file,&hdrlen1); - PICODBG_DEBUG(("got header size %d",hdrlen1)); - - if (PICO_OK == status) { - *headerlen += 2; - status = (hdrlen1 <= PICOOS_MAX_HEADER_STRING_LEN-1) ? PICO_OK : PICO_ERR_OTHER; - if (PICO_OK == status) { - n = hdrlen1; - if (picoos_ReadBytes(file, (picoos_uint8 *) this->tmpHeader, &n) && hdrlen1 == n) { - this->tmpHeader[hdrlen1] = NULLC; - *headerlen += hdrlen1; - PICODBG_DEBUG(("got header <%s>",this->tmpHeader)); - - status = PICO_OK; - } else { - status = PICO_ERR_OTHER; - } - } - if (PICO_OK == status) { - status = picoos_hdrParseHeader(header, this->tmpHeader); - } - } - return status; -} - -static pico_status_t picorsrc_createKnowledgeBase( - picorsrc_ResourceManager this, - picoos_uint8 * data, - picoos_uint32 size, - picoknow_kb_id_t kbid, - picoknow_KnowledgeBase * kb) -{ - (*kb) = picoknow_newKnowledgeBase(this->common->mm); - if (NULL == (*kb)) { - return PICO_EXC_OUT_OF_MEM; - } - (*kb)->base = data; - (*kb)->size = size; - (*kb)->id = kbid; - switch (kbid) { - case PICOKNOW_KBID_TPP_MAIN: - case PICOKNOW_KBID_TPP_USER_1: - case PICOKNOW_KBID_TPP_USER_2: - return picokpr_specializePreprocKnowledgeBase(*kb, this->common); - break; - case PICOKNOW_KBID_TAB_GRAPHS: - return picoktab_specializeGraphsKnowledgeBase(*kb, this->common); - break; - case PICOKNOW_KBID_TAB_PHONES: - return picoktab_specializePhonesKnowledgeBase(*kb, this->common); - break; - case PICOKNOW_KBID_TAB_POS: - return picoktab_specializePosKnowledgeBase(*kb, this->common); - break; - case PICOKNOW_KBID_FIXED_IDS: - return picoktab_specializeIdsKnowledgeBase(*kb, this->common); - break; - case PICOKNOW_KBID_LEX_MAIN: - case PICOKNOW_KBID_LEX_USER_1: - case PICOKNOW_KBID_LEX_USER_2: - return picoklex_specializeLexKnowledgeBase(*kb, this->common); - break; - case PICOKNOW_KBID_DT_POSP: - return picokdt_specializeDtKnowledgeBase(*kb, this->common, - PICOKDT_KDTTYPE_POSP); - break; - case PICOKNOW_KBID_DT_POSD: - return picokdt_specializeDtKnowledgeBase(*kb, this->common, - PICOKDT_KDTTYPE_POSD); - break; - case PICOKNOW_KBID_DT_G2P: - return picokdt_specializeDtKnowledgeBase(*kb, this->common, - PICOKDT_KDTTYPE_G2P); - break; - case PICOKNOW_KBID_DT_PHR: - return picokdt_specializeDtKnowledgeBase(*kb, this->common, - PICOKDT_KDTTYPE_PHR); - break; - case PICOKNOW_KBID_DT_ACC: - return picokdt_specializeDtKnowledgeBase(*kb, this->common, - PICOKDT_KDTTYPE_ACC); - break; - case PICOKNOW_KBID_FST_SPHO_1: - case PICOKNOW_KBID_FST_SPHO_2: - case PICOKNOW_KBID_FST_SPHO_3: - case PICOKNOW_KBID_FST_SPHO_4: - case PICOKNOW_KBID_FST_SPHO_5: - case PICOKNOW_KBID_FST_SPHO_6: - case PICOKNOW_KBID_FST_SPHO_7: - case PICOKNOW_KBID_FST_SPHO_8: - case PICOKNOW_KBID_FST_SPHO_9: - case PICOKNOW_KBID_FST_SPHO_10: - case PICOKNOW_KBID_FST_WPHO_1: - case PICOKNOW_KBID_FST_WPHO_2: - case PICOKNOW_KBID_FST_WPHO_3: - case PICOKNOW_KBID_FST_WPHO_4: - case PICOKNOW_KBID_FST_WPHO_5: - case PICOKNOW_KBID_FST_SVOXPA_PARSE: - case PICOKNOW_KBID_FST_XSAMPA_PARSE: - case PICOKNOW_KBID_FST_XSAMPA2SVOXPA: - - return picokfst_specializeFSTKnowledgeBase(*kb, this->common); - break; - - case PICOKNOW_KBID_DT_DUR: - case PICOKNOW_KBID_DT_LFZ1: - case PICOKNOW_KBID_DT_LFZ2: - case PICOKNOW_KBID_DT_LFZ3: - case PICOKNOW_KBID_DT_LFZ4: - case PICOKNOW_KBID_DT_LFZ5: - case PICOKNOW_KBID_DT_MGC1: - case PICOKNOW_KBID_DT_MGC2: - case PICOKNOW_KBID_DT_MGC3: - case PICOKNOW_KBID_DT_MGC4: - case PICOKNOW_KBID_DT_MGC5: - return picokdt_specializeDtKnowledgeBase(*kb, this->common, - PICOKDT_KDTTYPE_PAM); - break; - case PICOKNOW_KBID_PDF_DUR: - return picokpdf_specializePdfKnowledgeBase(*kb, this->common, - PICOKPDF_KPDFTYPE_DUR); - - break; - case PICOKNOW_KBID_PDF_LFZ: - return picokpdf_specializePdfKnowledgeBase(*kb, this->common, - PICOKPDF_KPDFTYPE_MUL); - break; - case PICOKNOW_KBID_PDF_MGC: - return picokpdf_specializePdfKnowledgeBase(*kb, this->common, - PICOKPDF_KPDFTYPE_MUL); - break; - case PICOKNOW_KBID_PDF_PHS: - return picokpdf_specializePdfKnowledgeBase(*kb, this->common, - PICOKPDF_KPDFTYPE_PHS); - break; - - - -#if defined(PICO_DEBUG) - case PICOKNOW_KBID_DBG: - return picokdbg_specializeDbgKnowledgeBase(*kb, this->common); - break; -#endif - - default: - break; - } - return PICO_OK; -} - - -static pico_status_t picorsrc_releaseKnowledgeBase( - picorsrc_ResourceManager this, - picoknow_KnowledgeBase * kb) -{ - (*kb) = NULL; - return PICO_OK; -} - -static pico_status_t picorsrc_getKbList(picorsrc_ResourceManager this, - picoos_uint8 * data, - picoos_uint32 datalen, - picoknow_KnowledgeBase * kbList) -{ - - pico_status_t status = PICO_OK; - picoos_uint32 curpos = 0, offset, size; - picoos_uint8 i, numKbs, kbid; - picoos_char str[PICOKNOW_MAX_KB_NAME_SIZ]; - picoknow_KnowledgeBase kb; - - *kbList = NULL; - datalen = datalen; - /* read number of fields */ - numKbs = data[curpos++]; - PICODBG_DEBUG(("number of kbs (unrestricted) = %i",numKbs)); - status = (numKbs <= PICOKNOW_MAX_NUM_RESOURCE_KBS) ? PICO_OK : PICO_EXC_FILE_CORRUPT; - /* read in all kb names */ - PICODBG_DEBUG(("number of kbs = %i",numKbs)); - i = 0; - while ((PICO_OK == status) && (i++ < numKbs)) { - status = (picoos_get_str((picoos_char *)data,&curpos,str,PICOOS_MAX_FIELD_STRING_LEN)) ? PICO_OK : PICO_EXC_FILE_CORRUPT; - PICODBG_DEBUG(("contains knowledge base %s (status: %i)",str, status)); - } - /* consume termination of last str */ - curpos++; - i = 0; - while ((PICO_OK == status) && (i++ < numKbs)) { - kbid = data[curpos++]; - PICODBG_DEBUG(("got kb id %i, curpos now %i",kbid, curpos)); - status = picoos_read_mem_pi_uint32(data,&curpos,&offset); - PICODBG_DEBUG(("got kb offset %i, curpos now %i",offset, curpos)); - status = picoos_read_mem_pi_uint32(data,&curpos,&size); - PICODBG_DEBUG(("got kb size %i, curpos now %i",size, curpos)); - if (PICO_OK == status) { - if (0 == offset) { - /* currently we consider a kb mentioned in resource but with offset 0 (no knowledge) as - * different form a kb not mentioned at all. We might reconsider that later. */ - PICODBG_DEBUG((" kb (id %i) is mentioned but empty (base:%i, size:%i)",kb->id, kb->base, kb->size)); - status = picorsrc_createKnowledgeBase(this, NULL, size, (picoknow_kb_id_t)kbid, &kb); - } else { - status = picorsrc_createKnowledgeBase(this, data+offset, size, (picoknow_kb_id_t)kbid, &kb); - } - PICODBG_DEBUG(("found kb (id %i) starting at %i with size %i",kb->id, kb->base, kb->size)); - if (PICO_OK == status) { - kb->next = *kbList; - *kbList = kb; - } - } - } - if (PICO_OK != status) { - kb = *kbList; - while (NULL != kb) { - picorsrc_releaseKnowledgeBase(this,&kb); - } - } - - return status; - -} - -/* load resource file. the type of resource file etc. are in the header, - * then follows the directory, then the knowledge bases themselves (as byte streams) */ - -pico_status_t picorsrc_loadResource(picorsrc_ResourceManager this, - picoos_char * fileName, picorsrc_Resource * resource) -{ - picorsrc_Resource res; - picoos_uint32 headerlen, len,maxlen; - picoos_file_header_t header; - picoos_uint8 rem; - pico_status_t status = PICO_OK; - - if (resource == NULL) { - return PICO_ERR_NULLPTR_ACCESS; - } else { - *resource = NULL; - } - - res = picorsrc_newResource(this->common->mm); - - if (NULL == res) { - return picoos_emRaiseException(this->common->em,PICO_EXC_OUT_OF_MEM,NULL,NULL); - } - - if (PICO_MAX_NUM_RESOURCES <= this->numResources) { - picoos_deallocate(this->common->mm, (void *) &res); - return picoos_emRaiseException(this->common->em,PICO_EXC_MAX_NUM_EXCEED,NULL,(picoos_char *)"no more than %i resources",PICO_MAX_NUM_RESOURCES); - } - - /* ***************** parse file name for file type and parameters */ - - if (PICO_OK != parse_resource_name(fileName)) { - picoos_deallocate(this->common->mm, (void *) &res); - return PICO_EXC_UNEXPECTED_FILE_TYPE; - } - - /* ***************** get header info */ - - /* open binary file for reading (no key, nrOfBufs, bufSize) */ - PICODBG_DEBUG(("trying to open file %s",fileName)); - if (!picoos_OpenBinary(this->common, &res->file, fileName)) { - /* open didn't succeed */ - status = PICO_EXC_CANT_OPEN_FILE; - PICODBG_ERROR(("can't open file %s",fileName)); - picoos_emRaiseException(this->common->em, PICO_EXC_CANT_OPEN_FILE, - NULL, (picoos_char *) "%s", fileName); - } - if (PICO_OK == status) { - status = readHeader(this, &header, &headerlen, res->file); - /* res->file now positioned at first pos after header */ - } - - /* ***************** check header values */ - if (PICO_OK == status && isResourceLoaded(this, header.field[PICOOS_HEADER_NAME].value)) { - /* lingware is allready loaded, do nothing */ - PICODBG_WARN((">>> lingware '%s' allready loaded",header.field[PICOOS_HEADER_NAME].value)); - picoos_emRaiseWarning(this->common->em,PICO_WARN_RESOURCE_DOUBLE_LOAD,NULL,(picoos_char *)"%s",header.field[PICOOS_HEADER_NAME].value); - status = PICO_WARN_RESOURCE_DOUBLE_LOAD; - } - - if (PICO_OK == status) { - /* get data length */ - status = picoos_read_pi_uint32(res->file, &len); - PICODBG_DEBUG(("found net resource len of %i",len)); - /* allocate memory */ - if (PICO_OK == status) { - PICODBG_TRACE((">>> 2")); - maxlen = len + PICOOS_ALIGN_SIZE; /* once would be sufficient? */ - res->raw_mem = picoos_allocProtMem(this->common->mm, maxlen); - /* res->size = maxlen; */ - status = (NULL == res->raw_mem) ? PICO_EXC_OUT_OF_MEM : PICO_OK; - } - if (PICO_OK == status) { - rem = (picoos_uint32) res->raw_mem % PICOOS_ALIGN_SIZE; - if (rem > 0) { - res->start = res->raw_mem + (PICOOS_ALIGN_SIZE - rem); - } else { - res->start = res->raw_mem; - } - - /* read file contents into memory */ - status = (picoos_ReadBytes(res->file, res->start, &len)) ? PICO_OK - : PICO_ERR_OTHER; - /* resources are read-only; the following write protection - has an effect in test configurations only */ - picoos_protectMem(this->common->mm, res->start, len, /*enable*/TRUE); - } - /* note resource unique name */ - if (PICO_OK == status) { - if (picoos_strlcpy(res->name,header.field[PICOOS_HEADER_NAME].value,PICORSRC_MAX_RSRC_NAME_SIZ) < PICORSRC_MAX_RSRC_NAME_SIZ) { - PICODBG_DEBUG(("assigned name %s to resource",res->name)); - status = PICO_OK; - } else { - status = PICO_ERR_INDEX_OUT_OF_RANGE; - PICODBG_ERROR(("failed assigning name %s to resource", - res->name)); - picoos_emRaiseException(this->common->em, - PICO_ERR_INDEX_OUT_OF_RANGE, NULL, - (picoos_char *)"resource %s",res->name); - } - } - - /* get resource type */ - if (PICO_OK == status) { - if (!picoos_strcmp(header.field[PICOOS_HEADER_CONTENT_TYPE].value, PICORSRC_FIELD_VALUE_TEXTANA)) { - res->type = PICORSRC_TYPE_TEXTANA; - } else if (!picoos_strcmp(header.field[PICOOS_HEADER_CONTENT_TYPE].value, PICORSRC_FIELD_VALUE_SIGGEN)) { - res->type = PICORSRC_TYPE_SIGGEN; - } else if (!picoos_strcmp(header.field[PICOOS_HEADER_CONTENT_TYPE].value, PICORSRC_FIELD_VALUE_SIGGEN)) { - res->type = PICORSRC_TYPE_USER_LEX; - } else if (!picoos_strcmp(header.field[PICOOS_HEADER_CONTENT_TYPE].value, PICORSRC_FIELD_VALUE_SIGGEN)) { - res->type = PICORSRC_TYPE_USER_PREPROC; - } else { - res->type = PICORSRC_TYPE_OTHER; - } - } - - if (PICO_OK == status) { - /* create kb list from resource */ - status = picorsrc_getKbList(this, res->start, len, &res->kbList); - } - } - - if (status == PICO_OK) { - /* add resource to rm */ - res->next = this->resources; - this->resources = res; - this->numResources++; - *resource = res; - PICODBG_DEBUG(("done loading resource %s from %s", res->name, fileName)); - } else { - picorsrc_disposeResource(this->common->mm, &res); - PICODBG_ERROR(("failed to load resource")); - } - - if (status < 0) { - return status; - } else { - return PICO_OK; - } -} - -static pico_status_t picorsrc_releaseKbList(picorsrc_ResourceManager this, picoknow_KnowledgeBase * kbList) -{ - picoknow_KnowledgeBase kbprev, kb; - kb = *kbList; - while (NULL != kb) { - kbprev = kb; - kb = kb->next; - picoknow_disposeKnowledgeBase(this->common->mm,&kbprev); - } - *kbList = NULL; - return PICO_OK; -} - -/* unload resource file. (if resource file is busy, warn and don't unload) */ -pico_status_t picorsrc_unloadResource(picorsrc_ResourceManager this, picorsrc_Resource * resource) { - - picorsrc_Resource r1, r2, rsrc; - - if (resource == NULL) { - return PICO_ERR_NULLPTR_ACCESS; - } else { - rsrc = *resource; - } - - if (rsrc->lockCount > 0) { - return PICO_EXC_RESOURCE_BUSY; - } - /* terminate */ - if (rsrc->file != NULL) { - picoos_CloseBinary(this->common, &rsrc->file); - } - if (NULL != rsrc->raw_mem) { - picoos_deallocProtMem(this->common->mm, (void *) &rsrc->raw_mem); - PICODBG_DEBUG(("deallocated raw mem")); - } - - r1 = NULL; - r2 = this->resources; - while (r2 != NULL && r2 != rsrc) { - r1 = r2; - r2 = r2->next; - } - if (NULL == r1) { - this->resources = rsrc->next; - } else if (NULL == r2) { - /* didn't find resource in rm! */ - return PICO_ERR_OTHER; - } else { - r1->next = rsrc->next; - } - - if (NULL != rsrc->kbList) { - picorsrc_releaseKbList(this, &rsrc->kbList); - } - - picoos_deallocate(this->common->mm,(void **)resource); - this->numResources--; - - return PICO_OK; -} - - -pico_status_t picorsrc_createDefaultResource(picorsrc_ResourceManager this - /*, picorsrc_Resource * resource */) -{ - picorsrc_Resource res; - pico_status_t status = PICO_OK; - - - /* *resource = NULL; */ - - if (PICO_MAX_NUM_RESOURCES <= this->numResources) { - return picoos_emRaiseException(this->common->em,PICO_EXC_MAX_NUM_EXCEED,NULL,(picoos_char *)"no more than %i resources",PICO_MAX_NUM_RESOURCES); - } - - res = picorsrc_newResource(this->common->mm); - - if (NULL == res) { - return picoos_emRaiseException(this->common->em,PICO_EXC_OUT_OF_MEM,NULL,NULL); - } - - if (picoos_strlcpy(res->name,PICOKNOW_DEFAULT_RESOURCE_NAME,PICORSRC_MAX_RSRC_NAME_SIZ) < PICORSRC_MAX_RSRC_NAME_SIZ) { - PICODBG_DEBUG(("assigned name %s to default resource",res->name)); - status = PICO_OK; - } else { - PICODBG_ERROR(("failed assigning name %s to default resource",res->name)); - status = PICO_ERR_INDEX_OUT_OF_RANGE; - } - status = picorsrc_createKnowledgeBase(this, NULL, 0, (picoknow_kb_id_t)PICOKNOW_KBID_FIXED_IDS, &res->kbList); - - if (PICO_OK == status) { - res->next = this->resources; - this->resources = res; - this->numResources++; - /* *resource = res; */ - - } - - - return status; - -} - -pico_status_t picorsrc_rsrcGetName(picorsrc_Resource this, - picoos_char * name, picoos_uint32 maxlen) { - if (!picoctrl_isValidResourceHandle(this)) { - return PICO_ERR_INVALID_ARGUMENT; - } - picoos_strlcpy(name, this->name,maxlen); - return PICO_OK; -} - - -/* ******* accessing voice definitions **************************************/ - - -static pico_status_t findVoiceDefinition(picorsrc_ResourceManager this, - const picoos_char * voiceName, picorsrc_VoiceDefinition * vdef) -{ - picorsrc_VoiceDefinition v; - PICODBG_DEBUG(("finding voice name %s",voiceName)); - if (NULL == this) { - return PICO_ERR_NULLPTR_ACCESS; - } - v = this->vdefs; - while (NULL != v && (0 != picoos_strcmp(v->voiceName,voiceName))) { - PICODBG_DEBUG(("%s doesnt match",v->voiceName)); - v = v->next; - } - *vdef = v; - if (v == NULL) { - PICODBG_DEBUG(("didnt find voice name %s",voiceName)); - } else { - PICODBG_DEBUG(("found voice name %s",voiceName)); - } - return PICO_OK; -} - - -pico_status_t picorsrc_addResourceToVoiceDefinition(picorsrc_ResourceManager this, - picoos_char * voiceName, picoos_char * resourceName) -{ - picorsrc_VoiceDefinition vdef; - - if (NULL == this) { - PICODBG_ERROR(("this is NULL")); - return PICO_ERR_NULLPTR_ACCESS; - } - if ((PICO_OK == findVoiceDefinition(this,voiceName,&vdef)) && (NULL != vdef)) { - if (PICO_MAX_NUM_RSRC_PER_VOICE <= vdef->numResources) { - return picoos_emRaiseException(this->common->em,PICO_EXC_MAX_NUM_EXCEED,NULL,(picoos_char *)"no more than %i resources per voice",PICO_MAX_NUM_RSRC_PER_VOICE); - } - if (picoos_strlcpy(vdef->resourceName[vdef->numResources++], resourceName, - PICORSRC_MAX_RSRC_NAME_SIZ) < PICORSRC_MAX_RSRC_NAME_SIZ) { - PICODBG_DEBUG(("vdef added resource '%s' to voice '%s'",resourceName,voiceName)); - return PICO_OK; - } else { - PICODBG_ERROR(("illegal name (%s)",resourceName)); - return picoos_emRaiseException(this->common->em,PICO_EXC_NAME_ILLEGAL,NULL,(picoos_char *)"%s",resourceName); - } - - } else { - return picoos_emRaiseException(this->common->em,PICO_EXC_NAME_UNDEFINED,NULL,(picoos_char *)"%s",voiceName); - } -} - - -pico_status_t picorsrc_createVoiceDefinition(picorsrc_ResourceManager this, - picoos_char * voiceName) -{ - picorsrc_VoiceDefinition vdef; - - if (NULL == this) { - PICODBG_ERROR(("this is NULL")); - return PICO_ERR_NULLPTR_ACCESS; - } - if ((PICO_OK == findVoiceDefinition(this,voiceName,&vdef)) && (NULL != vdef)) { - PICODBG_ERROR(("voice %s allready defined",voiceName)); - return picoos_emRaiseException(this->common->em,PICO_EXC_NAME_CONFLICT,NULL,NULL); - } - if (PICO_MAX_NUM_VOICE_DEFINITIONS <= this->numVdefs) { - PICODBG_ERROR(("max number of vdefs exceeded (%i)",this->numVdefs)); - return picoos_emRaiseException(this->common->em,PICO_EXC_MAX_NUM_EXCEED,NULL,(picoos_char *)"no more than %i voice definitions",PICO_MAX_NUM_VOICE_DEFINITIONS); - } - if (NULL == this->freeVdefs) { - vdef = picorsrc_newVoiceDefinition(this->common->mm); - } else { - vdef = this->freeVdefs; - this->freeVdefs = vdef->next; - vdef->voiceName[0] = NULLC; - vdef->numResources = 0; - vdef->next = NULL; - } - if (NULL == vdef) { - return picoos_emRaiseException(this->common->em,PICO_EXC_OUT_OF_MEM,NULL,NULL); - } - if (picoos_strlcpy(vdef->voiceName, voiceName, - PICO_MAX_VOICE_NAME_SIZE) < PICO_MAX_VOICE_NAME_SIZE) { - vdef->next = this->vdefs; - this->vdefs = vdef; - this->numVdefs++; - if (PICO_OK != picorsrc_addResourceToVoiceDefinition(this,voiceName,PICOKNOW_DEFAULT_RESOURCE_NAME)) { - return picoos_emRaiseException(this->common->em,PICO_ERR_OTHER,NULL,(picoos_char *)"problem loading default resource %s",voiceName); - } - PICODBG_DEBUG(("vdef created (%s)",voiceName)); - return PICO_OK; - } else { - PICODBG_ERROR(("illegal name (%s)",voiceName)); - return picoos_emRaiseException(this->common->em,PICO_EXC_NAME_ILLEGAL,NULL,(picoos_char *)"%s",voiceName); - } -} - - -pico_status_t picorsrc_releaseVoiceDefinition(picorsrc_ResourceManager this, - picoos_char *voiceName) -{ - picorsrc_VoiceDefinition v, l; - - if (this == NULL) { - return PICO_ERR_NULLPTR_ACCESS; - } - - l = NULL; - v = this->vdefs; - while ((v != NULL) && (picoos_strcmp(v->voiceName, voiceName) != 0)) { - l = v; - v = v->next; - } - if (v != NULL) { - /* remove v from vdefs list */ - if (l != NULL) { - l->next = v->next; - } else { - this->vdefs = v->next; - } - /* insert v at head of freeVdefs list */ - v->next = this->freeVdefs; - this->freeVdefs = v; - this->numVdefs--; - return PICO_OK; - } else { - /* we should rather return a warning, here */ - /* return picoos_emRaiseException(this->common->em,PICO_EXC_NAME_UNDEFINED,"%s", NULL); */ - return PICO_OK; - } -} - - - -/* ******* accessing voices **************************************/ - - -/* create voice, given a voice name. the corresponding lock counts are incremented */ - -pico_status_t picorsrc_createVoice(picorsrc_ResourceManager this, const picoos_char * voiceName, picorsrc_Voice * voice) { - - picorsrc_VoiceDefinition vdef; - picorsrc_Resource rsrc; - picoos_uint8 i, required; - picoknow_KnowledgeBase kb; - /* pico_status_t status = PICO_OK; */ - - PICODBG_DEBUG(("creating voice %s",voiceName)); - - if (NULL == this) { - PICODBG_ERROR(("this is NULL")); - return PICO_ERR_NULLPTR_ACCESS; - - } - /* check number of voices */ - if (PICORSRC_MAX_NUM_VOICES <= this->numVoices) { - PICODBG_ERROR(("PICORSRC_MAX_NUM_VOICES exceeded")); - return picoos_emRaiseException(this->common->em,PICO_EXC_MAX_NUM_EXCEED,NULL,(picoos_char *)"no more than %i voices",PICORSRC_MAX_NUM_VOICES); - } - - /* find voice definition for that name */ - if (!(PICO_OK == findVoiceDefinition(this,voiceName,&vdef)) || (NULL == vdef)) { - PICODBG_ERROR(("no voice definition for %s",voiceName)); - return picoos_emRaiseException(this->common->em,PICO_EXC_NAME_UNDEFINED,NULL,(picoos_char *)"voice definition %s",voiceName); - - } - PICODBG_DEBUG(("found voice definition for %s",voiceName)); - - /* check that resources are loaded */ - for (i = 0; i < vdef->numResources; i++) { - required = (NULLC != vdef->resourceName[i][0]); - if (required && !isResourceLoaded(this,vdef->resourceName[i])) { - PICODBG_ERROR(("resource missing")); - return picoos_emRaiseException(this->common->em,PICO_EXC_RESOURCE_MISSING,NULL,(picoos_char *)"resource %s for voice %s",vdef->resourceName[i],voiceName); - } - } - - /* allocate new voice */ - if (NULL == this->freeVoices) { - *voice = picorsrc_newVoice(this->common->mm); - } else { - *voice = this->freeVoices; - this->freeVoices = (*voice)->next; - picorsrc_initializeVoice(*voice); - } - if (*voice == NULL) { - return picoos_emRaiseException(this->common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); - } - this->numVoices++; - - /* copy resource kb pointers into kb array of voice */ - for (i = 0; i < vdef->numResources; i++) { - required = (NULLC != vdef->resourceName[i][0]); - if (required) { - findResource(this,vdef->resourceName[i],&rsrc); - (*voice)->resourceArray[(*voice)->numResources++] = rsrc; - rsrc->lockCount++; - kb = rsrc->kbList; - while (NULL != kb) { - if (NULL != (*voice)->kbArray[kb->id]) { - picoos_emRaiseWarning(this->common->em,PICO_WARN_KB_OVERWRITE,NULL, (picoos_char *)"%i", kb->id); - PICODBG_WARN(("overwriting knowledge base of id %i", kb->id)); - - } - PICODBG_DEBUG(("setting knowledge base of id %i", kb->id)); - - (*voice)->kbArray[kb->id] = kb; - kb = kb->next; - } - } - } /* for */ - - return PICO_OK; -} - -/* dispose voice. the corresponding lock counts are decremented. */ - -pico_status_t picorsrc_releaseVoice(picorsrc_ResourceManager this, picorsrc_Voice * voice) -{ - picoos_uint16 i; - picorsrc_Voice v = *voice; - if (NULL == this || NULL == v) { - return PICO_ERR_NULLPTR_ACCESS; - } - for (i = 0; i < v->numResources; i++) { - v->resourceArray[i]->lockCount--; - } - v->next = this->freeVoices; - this->freeVoices = v; - this->numVoices--; - - return PICO_OK; -} - -#ifdef __cplusplus -} -#endif - -/* end picorsrc.c */ diff --git a/lib/picorsrc.h b/lib/picorsrc.h deleted file mode 100644 index 4dfb19e..0000000 --- a/lib/picorsrc.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * 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 picorsrc.h - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -/** - * @addtogroup picorsrc - * - * Pico Resource Management module \n - * -*/ - -#ifndef PICORSRC_H_ -#define PICORSRC_H_ - -#include "picodefs.h" -#include "picoos.h" -#include "picoknow.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -#define PICORSRC_MAX_RSRC_NAME_SIZ PICO_MAX_RESOURCE_NAME_SIZE /* including terminating NULLC */ - -#define PICORSRC_MAX_NUM_VOICES 64 - -/* size of kb array of a voice */ -#define PICORSRC_KB_ARRAY_SIZE 64 - -typedef picoos_char picorsrc_resource_name_t[PICORSRC_MAX_RSRC_NAME_SIZ]; - -typedef enum picorsrc_resource_type { - PICORSRC_TYPE_NULL, - PICORSRC_TYPE_TEXTANA, - PICORSRC_TYPE_SIGGEN, - PICORSRC_TYPE_USER_LEX, - PICORSRC_TYPE_USER_PREPROC, - PICORSRC_TYPE_OTHER -} picorsrc_resource_type_t; - - -#define PICORSRC_FIELD_VALUE_TEXTANA (picoos_char *) "TEXTANA" -#define PICORSRC_FIELD_VALUE_SIGGEN (picoos_char *) "SIGGEN" -#define PICORSRC_FIELD_VALUE_USERLEX (picoos_char *) "USERLEX" -#define PICORSRC_FIELD_VALUE_USERTPP (picoos_char *) "USERTPP" - - - -typedef struct picorsrc_resource_manager * picorsrc_ResourceManager; -typedef struct picorsrc_voice * picorsrc_Voice; -typedef struct picorsrc_resource * picorsrc_Resource; - - -/* ************************************************************************** - * - * file name extensions - * - ****************************************************************************/ - -#define PICO_BIN_EXTENSION ".bin" -#define PICO_INPLACE_EXTENSION ".inp" - - - -/* ************************************************************************** - * - * construct/destruct resource manager - * - ****************************************************************************/ - -/* create resource manager, given a config file name (or default name, if empty) */ - -picorsrc_ResourceManager picorsrc_newResourceManager(picoos_MemoryManager mm, picoos_Common common /* , picoos_char * configFile */); - -void picorsrc_disposeResourceManager(picoos_MemoryManager mm, picorsrc_ResourceManager * this); - - -/* ************************************************************************** - * - * resources - * - ****************************************************************************/ - -/** - * Returns non-zero if 'resource' is a valid resource handle, zero otherwise. - */ -picoos_int16 picoctrl_isValidResourceHandle(picorsrc_Resource resource); - -/* load resource file. the type of resource file, magic numbers, checksum etc. are in the header, then follows the directory - * (with fixed structure per resource type), then the knowledge bases themselves (as byte streams) */ -pico_status_t picorsrc_loadResource(picorsrc_ResourceManager this, - picoos_char * fileName, picorsrc_Resource * resource); - -/* unload resource file. (warn if resource file is busy) */ -pico_status_t picorsrc_unloadResource(picorsrc_ResourceManager this, picorsrc_Resource * rsrc); - - -pico_status_t picorsrc_createDefaultResource(picorsrc_ResourceManager this /*, - picorsrc_Resource * resource */); - - -pico_status_t picorsrc_rsrcGetName(picorsrc_Resource resource, - picoos_char * name, picoos_uint32 maxlen); - -/* ************************************************************************** - * - * voice definitions - * - ****************************************************************************/ - - -pico_status_t picorsrc_createVoiceDefinition(picorsrc_ResourceManager this, - picoos_char * voiceName); - - -pico_status_t picorsrc_releaseVoiceDefinition(picorsrc_ResourceManager this, - picoos_char * voiceName); - -pico_status_t picorsrc_addResourceToVoiceDefinition(picorsrc_ResourceManager this, - picoos_char * voiceName, picoos_char * resourceName); - -/* ************************************************************************** - * - * voices - * - ****************************************************************************/ - -/** object : Voice - * shortcut : voice - * - */ - -typedef struct picorsrc_voice { - - picorsrc_Voice next; - - picoknow_KnowledgeBase kbArray[PICORSRC_KB_ARRAY_SIZE]; - - picoos_uint8 numResources; - - picorsrc_Resource resourceArray[PICO_MAX_NUM_RSRC_PER_VOICE]; - - -} picorsrc_voice_t; - - - -/* create voice, given a voice name. the corresponding lock counts are incremented */ -pico_status_t picorsrc_createVoice(picorsrc_ResourceManager this, const picoos_char * voiceName, picorsrc_Voice * voice); - -/* dispose voice. the corresponding lock counts are decremented. */ -pico_status_t picorsrc_releaseVoice(picorsrc_ResourceManager this, picorsrc_Voice * voice); - -#ifdef __cplusplus -} -#endif - - - -#endif /*PICORSRC_H_*/ diff --git a/lib/picosa.c b/lib/picosa.c deleted file mode 100644 index 3147c76..0000000 --- a/lib/picosa.c +++ /dev/null @@ -1,1738 +0,0 @@ -/* - * 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 picosa.c - * - * sentence analysis - POS disambiguation - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#include "picoos.h" -#include "picodbg.h" -#include "picobase.h" -#include "picokdt.h" -#include "picoklex.h" -#include "picoktab.h" -#include "picokfst.h" -#include "picotrns.h" -#include "picodata.h" -#include "picosa.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* PU saStep states */ -#define SA_STEPSTATE_COLLECT 0 -#define SA_STEPSTATE_PROCESS_POSD 10 -#define SA_STEPSTATE_PROCESS_WPHO 11 -#define SA_STEPSTATE_PROCESS_TRNS_PARSE 12 -#define SA_STEPSTATE_PROCESS_TRNS_FST 13 -#define SA_STEPSTATE_FEED 2 - -#define SA_MAX_ALTDESC_SIZE (30*(PICOTRNS_MAX_NUM_POSSYM + 2)) - -#define SA_MSGSTR_SIZE 32 - -/* subobject : SentAnaUnit - * shortcut : sa - * context size : one phrase, max. 30 non-PUNC items, for non-processed items - * one item if internal input empty - */ - -/** @addtogroup picosa - - internal buffers: - - - headx: array for extended item heads of fixed size (head plus - index for content, plus two fields for boundary strength/type) - - - cbuf1, cbuf2: buffers for item contents (referenced by index in - headx). Future: replace these two buffers by a single double-sided - buffer (double shrink-grow type) - - 0. bottom up filling of items in headx and cbuf1 - - 1. POS disambiguation (right-to-left, top-to-bottom): - - number and sequence of items unchanged - - item content can only get smaller (reducing nr of results in WORDINDEX) - -> info stays in "headx, cbuf1" and changed in place \n - WORDGRAPH(POSes,NA)graph -> WORDGRAPH(POS,NA)graph \n - WORDINDEX(POSes,NA)POS1ind1...POSNindN -> WORDINDEX(POS,NA)POS|ind \n - - 2. lex-index lookup and G2P (both directions possible, left-to-right done): - - number and sequence of items unchanged, item head info and content - changes - -> headx changed in place; cbuf1 to cbuf2 \n - WORDGRAPH(POS,NA)graph -> WORDPHON(POS,NA)phon \n - WORDINDEX(POS,NA)POS|ind -> WORDPHON(POS,NA)phon \n - - 3. phrasing (right-to-left): - - Previous (before introducing SBEG)\n - ---------------------------------- - 1| 2| 3| 4| \n - e.g. from WP WP WP WP WP PUNC WP WP PUNC WP WP WP PUNC FLUSH \n - e.g. to BINIT WP WP WP BPHR3 WP WP BPHR1 WP WP BSEND WP WP WP BSEND BTERM \n - |1 |2 |3 |4 \n - - 3-level bound state: to keep track of bound strength from end of - previous punc-phrase, then BOUND item output as first item - (strength from prev punc-phrase and type from current - punc-phrase). - - trailing PUNC item bound states - INIT SEND PHR1 - PUNC(SENTEND, T) B(I,T)>SEND B(S,T)>SEND B(P1,T)>SEND - PUNC(SENTEND, Q) B(I,Q)>SEND B(S,Q)>SEND B(P1,Q)>SEND - PUNC(SENTEND, E) B(I,E)>SEND B(S,E)>SEND B(P1,E)>SEND - PUNC(PHRASEEND, P) B(I,P)>PHR1 B(S,P)>PHR1 B(P1,P)>PHR1 - PUNC(PHRASEEND, FORC) B(I,P)>PHR1 B(S,P)>PHR1 B(P1,P)>PHR1 - PUNC(FLUSH, T) B(I,T).. B(S,T).. B(P1,T).. - B(T,NA) B(T,NA) B(T,NA) - >INIT >INIT >INIT - - PHR2/3 case: - trailing PUNC item bound states - INIT SEND PHR1 - PUNC(SENTEND, T) B(I,P)B(P,T)>SEND B(S,P)B(P,T)>SEND B(P1,P)B(P,T)>SEND - PUNC(SENTEND, Q) B(I,P)B(P,Q)>SEND B(S,P)B(P,Q)>SEND B(P1,P)B(P,Q)>SEND - PUNC(SENTEND, E) B(I,P)B(P,E)>SEND B(S,P)B(P,E)>SEND B(P1,P)B(P,E)>SEND - PUNC(PHRASEEND, P) B(I,P)B(P,P)>PHR1 B(S,P)B(P,P)>PHR1 B(P1,P)B(P,P)>PHR1 - PUNC(PHREND, FORC) B(I,P)B(P,P)>PHR1 B(S,P)B(P,P)>PHR1 B(P1,P)B(P,P)>PHR1 - PUNC(FLUSH, T) B(I,P)B(P,T).. B(S,T)B(P,T).. B(P1,T)B(P,T).. - B(T,NA) B(T,NA) B(T,NA) - >INIT >INIT >INIT - - Current - -------- - e.g. from WP WP WP WP WP PUNC WP WP PUNC WP WP WP PUNC FLUSH - e.g. to BSBEG WP WP WP BPHR3 WP WP BPHR1 WP WP BSEND BSBEG WP WP WP BSEND BTERM - |1 |2 |3 |4 - - 2-level bound state: The internal buffer contains one primary phrase (sometimes forced, if buffer - allmost full), with the trailing PUNCT item included (last item). - If the trailing PUNC is a a primary phrase separator, the - item is not output, but instead, the bound state is set to PPHR, so that the correct BOUND can - be output at the start of the next primary phrase. - Otherwise, - the item is converted to the corresponding BOUND and output. the bound state is set to SSEP, - so that a BOUND of type SBEG is output at the start of the next primary phrase. - - trailing PUNC item bound states - SSEP PPHR - PUNC(SENTEND, X) B(B,X)>SSEP B(P1,X)>SSEP (X = T | Q | E) - PUNC(FLUSH, T) B(B,T)>SSEP* B(P1,T)>SSEP - PUNC(PHRASEEND, P) B(B,P)>PPHR B(P1,P)>PPHR - PUNC(PHRASEEND, FORC) B(B,P)>PPHR B(P1,P)>PPHR - -* If more than one sentence separators follow each other (e.g. SEND-FLUSH, SEND-SEND) then - all but the first will be treated as an (empty) phrase containing just this item. - If this (single) item is a flush, creation of SBEG is suppressed. - - - - dtphr phrasing tree (rather subphrasing tree it should be called) - determines - BOUND_PHR2 - BOUND_PHR3 - - boundary strenghts are determined for every word (except the - first one) from right-to-left. The boundary types mark the phrase - type of the phrase following the boundary. - - number of items actually changed (new BOUND items added): because - of fixed size without content, two fields are contained in headx - to indicate if a BOUND needs to be added to the LEFT of the item. - -> headx further extended with boundary strength and type info to - indicate that to the left of the headx ele a BOUND needs to be - inserted when outputting. - - 4. accentuation: - - number of items unchanged, content unchanged, only head info changes - -> changed in place in headx -*/ - - -typedef struct { - picodata_itemhead_t head; - picoos_uint16 cind; -} picosa_headx_t; - - -typedef struct sa_subobj { - picoos_uint8 procState; /* for next processing step decision */ - - picoos_uint8 inspaceok; /* flag: headx/cbuf1 has space for an item */ - picoos_uint8 needsmoreitems; /* flag: need more items */ - picoos_uint8 phonesTransduced; /* flag: */ - - picoos_uint8 tmpbuf[PICODATA_MAX_ITEMSIZE]; /* tmp. location for an item */ - - picosa_headx_t headx[PICOSA_MAXNR_HEADX]; - picoos_uint16 headxBottom; /* bottom */ - picoos_uint16 headxLen; /* length, 0 if empty */ - - picoos_uint8 cbuf1[PICOSA_MAXSIZE_CBUF]; - picoos_uint16 cbuf1BufSize; /* actually allocated size */ - picoos_uint16 cbuf1Len; /* length, 0 if empty */ - - picoos_uint8 cbuf2[PICOSA_MAXSIZE_CBUF]; - picoos_uint16 cbuf2BufSize; /* actually allocated size */ - picoos_uint16 cbuf2Len; /* length, 0 if empty */ - - picotrns_possym_t phonBufA[PICOTRNS_MAX_NUM_POSSYM+1]; - picotrns_possym_t phonBufB[PICOTRNS_MAX_NUM_POSSYM+1]; - picotrns_possym_t * phonBuf; - picotrns_possym_t * phonBufOut; - picoos_uint16 phonReadPos, phonWritePos; /* next pos to read from phonBufIn, next pos to write to phonBufIn */ - picoos_uint16 nextReadPos; /* position of (potential) next item to read from */ - - - /* buffer for internal calculation of transducer */ - picotrns_AltDesc altDescBuf; - /* the number of AltDesc in the buffer */ - picoos_uint16 maxAltDescLen; - - /* tab knowledge base */ - picoktab_Graphs tabgraphs; - picoktab_Phones tabphones; - picoktab_Pos tabpos; - picoktab_FixedIds fixedIds; - - /* dtposd knowledge base */ - picokdt_DtPosD dtposd; - - /* dtg2p knowledge base */ - picokdt_DtG2P dtg2p; - - /* lex knowledge base */ - picoklex_Lex lex; - - /* ulex knowledge bases */ - picoos_uint8 numUlex; - picoklex_Lex ulex[PICOKNOW_MAX_NUM_ULEX]; - - /* fst knowledge bases */ - picoos_uint8 numFsts; - picokfst_FST fst[PICOKNOW_MAX_NUM_WPHO_FSTS]; - picoos_uint8 curFst; /* the fst to be applied next */ - - -} sa_subobj_t; - - -static pico_status_t saInitialize(register picodata_ProcessingUnit this) { - sa_subobj_t * sa; - picoos_uint16 i; - picokfst_FST fst; - picoknow_kb_id_t fstKbIds[PICOKNOW_MAX_NUM_WPHO_FSTS] = PICOKNOW_KBID_WPHO_ARRAY; - picoklex_Lex ulex; - picoknow_kb_id_t ulexKbIds[PICOKNOW_MAX_NUM_ULEX] = PICOKNOW_KBID_ULEX_ARRAY; - - PICODBG_DEBUG(("calling")); - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(this->common->em, - PICO_ERR_NULLPTR_ACCESS, NULL, NULL); - } - sa = (sa_subobj_t *) this->subObj; - - /* sa->common = this->common; */ - - sa->procState = SA_STEPSTATE_COLLECT; - - sa->inspaceok = TRUE; - sa->needsmoreitems = TRUE; - - sa->headxBottom = 0; - sa->headxLen = 0; - sa->cbuf1BufSize = PICOSA_MAXSIZE_CBUF; - sa->cbuf2BufSize = PICOSA_MAXSIZE_CBUF; - sa->cbuf1Len = 0; - sa->cbuf2Len = 0; - - /* init headx, cbuf1, cbuf2 */ - for (i = 0; i < PICOSA_MAXNR_HEADX; i++){ - sa->headx[i].head.type = 0; - sa->headx[i].head.info1 = PICODATA_ITEMINFO1_NA; - sa->headx[i].head.info2 = PICODATA_ITEMINFO2_NA; - sa->headx[i].head.len = 0; - sa->headx[i].cind = 0; - } - for (i = 0; i < PICOSA_MAXSIZE_CBUF; i++) { - sa->cbuf1[i] = 0; - sa->cbuf2[i] = 0; - } - - - /* possym buffer */ - sa->phonesTransduced = FALSE; - sa->phonBuf = sa->phonBufA; - sa->phonBufOut = sa->phonBufB; - sa->phonReadPos = 0; - sa->phonWritePos = 0; - sa->nextReadPos = 0; - - /* kb fst[] */ - sa->numFsts = 0; - for (i = 0; ivoice->kbArray[fstKbIds[i]]); - if (NULL != fst) { - sa->fst[sa->numFsts++] = fst; - } - } - sa->curFst = 0; - PICODBG_DEBUG(("got %i fsts", sa->numFsts)); - /* kb fixedIds */ - sa->fixedIds = picoktab_getFixedIds(this->voice->kbArray[PICOKNOW_KBID_FIXED_IDS]); - - /* kb tabgraphs */ - sa->tabgraphs = - picoktab_getGraphs(this->voice->kbArray[PICOKNOW_KBID_TAB_GRAPHS]); - if (sa->tabgraphs == NULL) { - return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - PICODBG_DEBUG(("got tabgraphs")); - - /* kb tabphones */ - sa->tabphones = - picoktab_getPhones(this->voice->kbArray[PICOKNOW_KBID_TAB_PHONES]); - if (sa->tabphones == NULL) { - return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - PICODBG_DEBUG(("got tabphones")); - -#ifdef PICO_DEBU - { - picoos_uint16 itmp; - for (itmp = 0; itmp < 256; itmp++) { - if (picoktab_hasVowelProp(sa->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones hasVowel: %d", itmp)); - } - if (picoktab_hasDiphthProp(sa->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones hasDiphth: %d", itmp)); - } - if (picoktab_hasGlottProp(sa->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones hasGlott: %d", itmp)); - } - if (picoktab_hasNonsyllvowelProp(sa->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones hasNonsyllvowel: %d", itmp)); - } - if (picoktab_hasSyllconsProp(sa->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones hasSyllcons: %d", itmp)); - } - if (picoktab_isPrimstress(sa->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones isPrimstress: %d", itmp)); - } - if (picoktab_isSecstress(sa->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones isSecstress: %d", itmp)); - } - if (picoktab_isSyllbound(sa->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones isSyllbound: %d", itmp)); - } - if (picoktab_isPause(sa->tabphones, itmp)) { - PICODBG_DEBUG(("tabphones isPause: %d", itmp)); - } - } - - PICODBG_DEBUG(("tabphones primstressID: %d", - picoktab_getPrimstressID(sa->tabphones))); - PICODBG_DEBUG(("tabphones secstressID: %d", - picoktab_getSecstressID(sa->tabphones))); - PICODBG_DEBUG(("tabphones syllboundID: %d", - picoktab_getSyllboundID(sa->tabphones))); - PICODBG_DEBUG(("tabphones pauseID: %d", - picoktab_getPauseID(sa->tabphones))); - } -#endif - - /* kb tabpos */ - sa->tabpos = - picoktab_getPos(this->voice->kbArray[PICOKNOW_KBID_TAB_POS]); - if (sa->tabpos == NULL) { - return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - PICODBG_DEBUG(("got tabpos")); - - /* kb dtposd */ - sa->dtposd = picokdt_getDtPosD(this->voice->kbArray[PICOKNOW_KBID_DT_POSD]); - if (sa->dtposd == NULL) { - return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - PICODBG_DEBUG(("got dtposd")); - - /* kb dtg2p */ - sa->dtg2p = picokdt_getDtG2P(this->voice->kbArray[PICOKNOW_KBID_DT_G2P]); - if (sa->dtg2p == NULL) { - return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - PICODBG_DEBUG(("got dtg2p")); - - /* kb lex */ - sa->lex = picoklex_getLex(this->voice->kbArray[PICOKNOW_KBID_LEX_MAIN]); - if (sa->lex == NULL) { - return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - PICODBG_DEBUG(("got lex")); - - /* kb ulex[] */ - sa->numUlex = 0; - for (i = 0; ivoice->kbArray[ulexKbIds[i]]); - if (NULL != ulex) { - sa->ulex[sa->numUlex++] = ulex; - } - } - PICODBG_DEBUG(("got %i user lexica", sa->numUlex)); - - return PICO_OK; -} - -static picodata_step_result_t saStep(register picodata_ProcessingUnit this, - picoos_int16 mode, - picoos_uint16 *numBytesOutput); - -static pico_status_t saTerminate(register picodata_ProcessingUnit this) { - return PICO_OK; -} - -static pico_status_t saSubObjDeallocate(register picodata_ProcessingUnit this, - picoos_MemoryManager mm) { - sa_subobj_t * sa; - if (NULL != this) { - sa = (sa_subobj_t *) this->subObj; - picotrns_deallocate_alt_desc_buf(mm,&sa->altDescBuf); - picoos_deallocate(mm, (void *) &this->subObj); - } - return PICO_OK; -} - - -picodata_ProcessingUnit picosa_newSentAnaUnit(picoos_MemoryManager mm, - picoos_Common common, - picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, - picorsrc_Voice voice) { - picodata_ProcessingUnit this; - sa_subobj_t * sa; - this = picodata_newProcessingUnit(mm, common, cbIn, cbOut, voice); - if (this == NULL) { - return NULL; - } - - this->initialize = saInitialize; - PICODBG_DEBUG(("set this->step to saStep")); - this->step = saStep; - this->terminate = saTerminate; - this->subDeallocate = saSubObjDeallocate; - - this->subObj = picoos_allocate(mm, sizeof(sa_subobj_t)); - if (this->subObj == NULL) { - picoos_deallocate(mm, (void *)&this); - picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); - return NULL; - } - - sa = (sa_subobj_t *) this->subObj; - - sa->altDescBuf = picotrns_allocate_alt_desc_buf(mm, SA_MAX_ALTDESC_SIZE, &sa->maxAltDescLen); - if (NULL == sa->altDescBuf) { - picotrns_deallocate_alt_desc_buf(mm,&sa->altDescBuf); - picoos_deallocate(mm, (void *)&sa); - picoos_deallocate(mm, (void *)&this); - picoos_emRaiseException(common->em,PICO_EXC_OUT_OF_MEM, NULL, NULL); - } - - - saInitialize(this); - return this; -} - - -/* ***********************************************************************/ -/* PROCESS_POSD disambiguation functions */ -/* ***********************************************************************/ - -/* find next POS to the right of 'ind' and return its POS and index */ -static picoos_uint8 saPosDItemSeqGetPosRight(register picodata_ProcessingUnit this, - register sa_subobj_t *sa, - const picoos_uint16 ind, - const picoos_uint16 top, - picoos_uint16 *rightind) { - picoos_uint8 val; - picoos_int32 i; - - val = PICOKDT_EPSILON; - for (i = ind + 1; ((val == PICOKDT_EPSILON) && (i < top)); i++) { - if ((sa->headx[i].head.type == PICODATA_ITEM_WORDGRAPH) || - (sa->headx[i].head.type == PICODATA_ITEM_WORDINDEX) || - (sa->headx[i].head.type == PICODATA_ITEM_WORDPHON) ) { - val = sa->headx[i].head.info1; - } - } - *rightind = i - 1; - return val; -} - - -/* left-to-right, for each WORDGRAPH/WORDINDEX/WORDPHON do posd */ -static pico_status_t saDisambPos(register picodata_ProcessingUnit this, - register sa_subobj_t *sa) { - picokdt_classify_result_t dtres; - picoos_uint8 half_nratt_posd = PICOKDT_NRATT_POSD >> 1; - picoos_uint16 valbuf[PICOKDT_NRATT_POSD]; /* only [0..half_nratt_posd] can be >2^8 */ - picoos_uint16 prevout; /* direct dt output (hist.) or POS of prev word */ - picoos_uint16 lastprev3; /* last index of POS(es) found to the left */ - picoos_uint16 curPOS; /* POS(es) of current word */ - picoos_int32 first; /* index of first item with POS(es) */ - picoos_int32 ci; - picoos_uint8 okay; /* two uses: processing okay and lexind resovled */ - picoos_uint8 i; - picoos_uint16 inval; - picoos_uint16 fallback; - - /* set initial values */ - okay = TRUE; - prevout = PICOKDT_HISTORY_ZERO; - curPOS = PICODATA_ITEMINFO1_ERR; - first = 0; - - while ((first < sa->headxLen) && - (sa->headx[first].head.type != PICODATA_ITEM_WORDGRAPH) && - (sa->headx[first].head.type != PICODATA_ITEM_WORDINDEX) && - (sa->headx[first].head.type != PICODATA_ITEM_WORDPHON)) { - first++; - } - if (first >= sa->headxLen) { - /* phrase not containing an item with POSes info, e.g. single flush */ - PICODBG_DEBUG(("no item with POSes found")); - return PICO_OK; - } - - lastprev3 = first; - - for (i = 0; i <= half_nratt_posd; i++) { - valbuf[i] = PICOKDT_HISTORY_ZERO; - } - /* set POS(es) of current word, will be shifted afterwards */ - valbuf[half_nratt_posd+1] = sa->headx[first].head.info1; - for (i = half_nratt_posd+2; i < PICOKDT_NRATT_POSD; i++) { - /* find next POS to the right and set valbuf[i] */ - valbuf[i] = saPosDItemSeqGetPosRight(this, sa, lastprev3, sa->headxLen, &lastprev3); - } - - PICODBG_TRACE(("headxLen: %d", sa->headxLen)); - - /* process from left to right all items in headx */ - for (ci = first; ci < sa->headxLen; ci++) { - okay = TRUE; - - PICODBG_TRACE(("iter: %d, type: %c", ci, sa->headx[ci].head.type)); - - /* if not (WORDGRAPH or WORDINDEX) */ - if ((sa->headx[ci].head.type != PICODATA_ITEM_WORDGRAPH) && - (sa->headx[ci].head.type != PICODATA_ITEM_WORDINDEX) && - (sa->headx[ci].head.type != PICODATA_ITEM_WORDPHON)) { - continue; - } - - PICODBG_TRACE(("iter: %d, curPOS: %d", ci, sa->headx[ci].head.info1)); - - /* no continue so far => at [ci] we have a WORDGRAPH / WORDINDEX item */ - /* shift all elements one position to the left */ - /* shift predicted values (history) */ - for (i=1; iheadxLen, &lastprev3); - - /* just to be on the safe side; the following should never happen */ - if (sa->headx[ci].head.info1 != valbuf[half_nratt_posd]) { - PICODBG_WARN(("syncing POS")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, - NULL, NULL); - valbuf[half_nratt_posd] = sa->headx[ci].head.info1; - } - - curPOS = valbuf[half_nratt_posd]; - - /* Check if POS disambiguation not needed */ - if (picoktab_isUniquePos(sa->tabpos, (picoos_uint8) curPOS)) { - /* not needed */ - inval = 0; - fallback = 0; - if (!picokdt_dtPosDreverseMapOutFixed(sa->dtposd, curPOS, - &prevout, &fallback)) { - if (fallback) { - prevout = fallback; - - } else { - PICODBG_ERROR(("problem doing reverse output mapping")); - prevout = curPOS; - } - } - PICODBG_DEBUG(("keeping: %d", sa->headx[ci].head.info1)); - continue; - } - - /* assuming PICOKDT_NRATT_POSD == 7 */ - PICODBG_DEBUG(("%d: [%d %d %d %d %d %d %d]", - ci, valbuf[0], valbuf[1], valbuf[2], - valbuf[3], valbuf[4], valbuf[5], valbuf[6])); - - /* no continue so far => POS disambiguation needed */ - /* construct input vector, which is set in dtposd */ - if (!picokdt_dtPosDconstructInVec(sa->dtposd, valbuf)) { - /* error constructing invec */ - PICODBG_WARN(("problem with invec")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, - NULL, NULL); - okay = FALSE; - } - /* classify */ - if (okay && (!picokdt_dtPosDclassify(sa->dtposd, &prevout))) { - /* error doing classification */ - PICODBG_WARN(("problem classifying")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, - NULL, NULL); - okay = FALSE; - } - /* decompose */ - if (okay && (!picokdt_dtPosDdecomposeOutClass(sa->dtposd, &dtres))) { - /* error decomposing */ - PICODBG_WARN(("problem decomposing")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_OUTVECTOR, - NULL, NULL); - okay = FALSE; - } - if (okay && dtres.set) { - PICODBG_DEBUG(("in: %d, out: %d", valbuf[3], dtres.class)); - } else { - PICODBG_WARN(("problem disambiguating POS")); - dtres.class = PICODATA_ITEMINFO1_ERR; - } - - if (dtres.class > 255) { - PICODBG_WARN(("dt result outside valid range, setting pos to ERR")); - dtres.class = PICODATA_ITEMINFO1_ERR; - } - - sa->headx[ci].head.info1 = (picoos_uint8)dtres.class; - if (sa->headx[ci].head.type == PICODATA_ITEM_WORDINDEX) { - /* find pos/ind entry in cbuf matching unique, - disambiguated POS, adapt current headx cind/len - accordingly */ - PICODBG_DEBUG(("select phon based on POS disambiguation")); - okay = FALSE; - for (i = 0; i < sa->headx[ci].head.len; i += PICOKLEX_POSIND_SIZE) { - PICODBG_DEBUG(("comparing POS at cind + %d", i)); - if (picoktab_isPartOfPosGroup(sa->tabpos, - (picoos_uint8)dtres.class, - sa->cbuf1[sa->headx[ci].cind + i])) { - PICODBG_DEBUG(("found match for entry %d", - i/PICOKLEX_POSIND_SIZE + 1)); - sa->headx[ci].cind += i; - okay = TRUE; - break; - } - } - /* not finding a match is possible if posd predicts a POS that - is not part of any of the input POSes -> no warning */ -#if defined(PICO_DEBUG) - if (!okay) { - PICODBG_DEBUG(("no match found, selecting 1st entry")); - } -#endif - sa->headx[ci].head.len = PICOKLEX_POSIND_SIZE; - } - } - return PICO_OK; -} - - -/* ***********************************************************************/ -/* PROCESS_WPHO functions, copy, lexindex, and g2p */ -/* ***********************************************************************/ - -/* ************** copy ***************/ - -static pico_status_t saCopyItemContent1to2(register picodata_ProcessingUnit this, - register sa_subobj_t *sa, - picoos_uint16 ind) { - picoos_uint16 i; - picoos_uint16 cind1; - - /* set headx.cind, and copy content, head unchanged */ - cind1 = sa->headx[ind].cind; - sa->headx[ind].cind = sa->cbuf2Len; - - /* check cbufLen */ - if (sa->headx[ind].head.len > (sa->cbuf2BufSize - sa->cbuf2Len)) { - sa->headx[ind].head.len = sa->cbuf2BufSize - sa->cbuf2Len; - PICODBG_WARN(("phones skipped")); - picoos_emRaiseWarning(this->common->em, - PICO_WARN_INCOMPLETE, NULL, NULL); - if (sa->headx[ind].head.len == 0) { - sa->headx[ind].cind = 0; - } - } - - for (i = 0; i < sa->headx[ind].head.len; i++) { - sa->cbuf2[sa->cbuf2Len] = sa->cbuf1[cind1 + i]; - sa->cbuf2Len++; - } - - PICODBG_DEBUG(("%c item, len: %d", - sa->headx[ind].head.type, sa->headx[ind].head.len)); - - return PICO_OK; -} - - -/* ************** lexindex ***************/ - -static pico_status_t saLexIndLookup(register picodata_ProcessingUnit this, - register sa_subobj_t *sa, - picoklex_Lex lex, - picoos_uint16 ind) { - picoos_uint8 pos; - picoos_uint8 *phones; - picoos_uint8 plen; - picoos_uint16 i; - - if (picoklex_lexIndLookup(lex, &(sa->cbuf1[sa->headx[ind].cind + 1]), - PICOKLEX_IND_SIZE, &pos, &phones, &plen)) { - sa->headx[ind].cind = sa->cbuf2Len; - - /* check cbufLen */ - if (plen > (sa->cbuf2BufSize - sa->cbuf2Len)) { - plen = sa->cbuf2BufSize - sa->cbuf2Len; - PICODBG_WARN(("phones skipped")); - picoos_emRaiseWarning(this->common->em, - PICO_WARN_INCOMPLETE, NULL, NULL); - if (plen == 0) { - sa->headx[ind].cind = 0; - } - } - - /* set item head, info1, info2 unchanged */ - sa->headx[ind].head.type = PICODATA_ITEM_WORDPHON; - sa->headx[ind].head.len = plen; - - for (i = 0; i < plen; i++) { - sa->cbuf2[sa->cbuf2Len] = phones[i]; - sa->cbuf2Len++; - } - - PICODBG_DEBUG(("%c item, pos: %d, plen: %d", - PICODATA_ITEM_WORDPHON, pos, plen)); - - } else { - PICODBG_WARN(("lexIndLookup problem")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_PU_IRREG_ITEM, - NULL, NULL); - } - return PICO_OK; -} - - - -/* ************** g2p ***************/ - - -/* Name : saGetNvowel - Function: returns vowel info in a word or word seq - Input : sInChar the grapheme string to be converted in phoneme - inLen number of bytes in grapheme buffer - inPos start position of current grapheme (0..inLen-1) - Output : nVow number of vowels in the word - nVord vowel order in the word - Returns : TRUE: processing successful; FALSE: errors -*/ -static picoos_uint8 saGetNrVowel(register picodata_ProcessingUnit this, - register sa_subobj_t *sa, - const picoos_uint8 *sInChar, - const picoos_uint16 inLen, - const picoos_uint8 inPos, - picoos_uint8 *nVow, - picoos_uint8 *nVord) { - picoos_uint32 nCount; - picoos_uint32 pos; - picoos_uint8 cstr[PICOBASE_UTF8_MAXLEN + 1]; - - /*defaults*/ - *nVow = 0; - *nVord = 0; - /*1:check wether the current char is a vowel*/ - pos = inPos; - if (!picobase_get_next_utf8char(sInChar, inLen, &pos, cstr) || - !picoktab_hasVowellikeProp(sa->tabgraphs, cstr, PICOBASE_UTF8_MAXLEN)) { - return FALSE; - } - /*2:count number of vowels in current word and find vowel order*/ - for (nCount = 0; nCount < inLen; ) { - if (!picobase_get_next_utf8char(sInChar, inLen, &nCount, cstr)) { - return FALSE; - } - if (picoktab_hasVowellikeProp(sa->tabgraphs, cstr, - PICOBASE_UTF8_MAXLEN)) { - (*nVow)++; - if (nCount == pos) { - (*nVord) = (*nVow); - } - } - } - return TRUE; -} - - -/* do g2p for a full word, right-to-left */ -static picoos_uint8 saDoG2P(register picodata_ProcessingUnit this, - register sa_subobj_t *sa, - const picoos_uint8 *graph, - const picoos_uint8 graphlen, - const picoos_uint8 pos, - picoos_uint8 *phones, - const picoos_uint16 phonesmaxlen, - picoos_uint16 *plen) { - picoos_uint16 outNp1Ch; /*last 3 outputs produced*/ - picoos_uint16 outNp2Ch; - picoos_uint16 outNp3Ch; - picoos_uint8 nPrimary; - picoos_uint8 nCount; - picoos_uint32 utfpos; - picoos_uint16 nOutVal; - picoos_uint8 okay; - picoos_uint16 phonesind; - picoos_uint8 nrvow; - picoos_uint8 ordvow; - picokdt_classify_vecresult_t dtresv; - picoos_uint16 i; - - *plen = 0; - okay = TRUE; - - /* use sa->tmpbuf[PICOSA_MAXITEMSIZE] to temporarly store the - phones which are predicted in reverse order. Once all are - available put them in phones in usuable order. phonesind is - used to fille item in reverse order starting at the end of - tmpbuf. */ - phonesind = PICOSA_MAXITEMSIZE - 1; - - /* prepare the data for loop operations */ - outNp1Ch = PICOKDT_HISTORY_ZERO; - outNp2Ch = PICOKDT_HISTORY_ZERO; - outNp3Ch = PICOKDT_HISTORY_ZERO; - - /* inner loop */ - nPrimary = 0; - - /* ************************************************/ - /* go backward grapheme by grapheme, it's utf8... */ - /* ************************************************/ - - /* set start nCount to position of start of last utfchar */ - /* ! watch out! somethimes starting at 1, sometimes at 0, - ! sometimes counting per byte, sometimes per UTF8 char */ - /* nCount is (start position + 1) of utf8 char */ - utfpos = graphlen; - if (picobase_get_prev_utf8charpos(graph, 0, &utfpos)) { - nCount = utfpos + 1; - } else { - /* should not occurr */ - PICODBG_ERROR(("invalid utf8 string, graphlen: %d", graphlen)); - return FALSE; - } - - while (nCount > 0) { - PICODBG_TRACE(("right-to-left g2p, count: %d", nCount)); - okay = TRUE; - - if (!saGetNrVowel(this, sa, graph, graphlen, nCount-1, &nrvow, - &ordvow)) { - nrvow = 0; - ordvow = 0; - } - - /* prepare input vector, set inside tree object invec, - * g2pBuildVector will call the constructInVec tree method */ - if (!picokdt_dtG2PconstructInVec(sa->dtg2p, - graph, /*grapheme start*/ - graphlen, /*grapheme length*/ - nCount-1, /*grapheme current position*/ - pos, /*Word POS*/ - nrvow, /*nr vowels if vowel, 0 else */ - ordvow, /*ord of vowel if vowel, 0 el*/ - &nPrimary, /*primary stress flag*/ - outNp1Ch, /*Right phoneme context +1*/ - outNp2Ch, /*Right phoneme context +2*/ - outNp3Ch)) { /*Right phon context +3*/ - /*Errors in preparing the input vector : skip processing*/ - PICODBG_WARN(("problem with invec")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, - NULL, NULL); - okay = FALSE; - } - - /* classify using the invec in the tree object and save the direct - tree output also in the tree object */ - if (okay && (!picokdt_dtG2Pclassify(sa->dtg2p, &nOutVal))) { - /* error doing classification */ - PICODBG_WARN(("problem classifying")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, - NULL, NULL); - okay = FALSE; - } - - /* decompose the invec in the tree object and return result in dtresv */ - if (okay && (!picokdt_dtG2PdecomposeOutClass(sa->dtg2p, &dtresv))) { - /* error decomposing */ - PICODBG_WARN(("problem decomposing")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_OUTVECTOR, - NULL, NULL); - okay = FALSE; - } - - if (okay) { - if ((dtresv.nr == 0) || (dtresv.classvec[0] == PICOKDT_EPSILON)) { - /* no phones to be added */ - PICODBG_TRACE(("epsilon, no phone added %c", graph[nCount-1])); - ; - } else { - /* add decomposed output to tmpbuf, reverse order */ - for (i = dtresv.nr; ((((PICOSA_MAXITEMSIZE - 1) - - phonesind) 0)); ) { - i--; - PICODBG_TRACE(("%c %d",graph[nCount-1],dtresv.classvec[i])); - if (dtresv.classvec[i] > 255) { - PICODBG_WARN(("dt result outside valid range, " - "skipping phone")); - continue; - } - sa->tmpbuf[phonesind--] = (picoos_uint8)dtresv.classvec[i]; - if (!nPrimary) { - if (picoktab_isPrimstress(sa->tabphones, - (picoos_uint8)dtresv.classvec[i])) { - nPrimary = 1; - } - } - (*plen)++; - } - if (i > 0) { - PICODBG_WARN(("phones skipped")); - picoos_emRaiseWarning(this->common->em, - PICO_WARN_INCOMPLETE, NULL, NULL); - } - } - } - - /*shift tree output history and update*/ - outNp3Ch = outNp2Ch; - outNp2Ch = outNp1Ch; - outNp1Ch = nOutVal; - - /* go backward one utf8 char */ - /* nCount is in +1 domain */ - if (nCount <= 1) { - /* end of str */ - nCount = 0; - } else { - utfpos = nCount - 1; - if (!picobase_get_prev_utf8charpos(graph, 0, &utfpos)) { - /* should not occur */ - PICODBG_ERROR(("invalid utf8 string, utfpos: %d", utfpos)); - return FALSE; - } else { - nCount = utfpos + 1; - } - } - } - - /* a must be: (PICOSA_MAXITEMSIZE-1) - phonesind == *plen */ - /* now that we have all phone IDs, copy in correct order to phones */ - /* phonesind point to next free slot in the reverse domainn, - ie. inc first */ - phonesind++; - for (i = 0; i < *plen; i++, phonesind++) { - phones[i] = sa->tmpbuf[phonesind]; - } - return TRUE; -} - - -/* item in headx[ind]/cbuf1, out: modified headx and cbuf2 */ - -static pico_status_t saGraphemeToPhoneme(register picodata_ProcessingUnit this, - register sa_subobj_t *sa, - picoos_uint16 ind) { - picoos_uint16 plen; - - PICODBG_TRACE(("starting g2p")); - - if (saDoG2P(this, sa, &(sa->cbuf1[sa->headx[ind].cind]), - sa->headx[ind].head.len, sa->headx[ind].head.info1, - &(sa->cbuf2[sa->cbuf2Len]), (sa->cbuf2BufSize - sa->cbuf2Len), - &plen)) { - - /* check of cbuf2Len done in saDoG2P, phones skipped if needed */ - if (plen > 255) { - PICODBG_WARN(("maximum number of phones exceeded (%d), skipping", - plen)); - plen = 255; - } - - /* set item head, info1, info2 unchanged */ - sa->headx[ind].head.type = PICODATA_ITEM_WORDPHON; - sa->headx[ind].head.len = (picoos_uint8)plen; - sa->headx[ind].cind = sa->cbuf2Len; - sa->cbuf2Len += plen; - PICODBG_DEBUG(("%c item, plen: %d", - PICODATA_ITEM_WORDPHON, plen)); - } else { - PICODBG_WARN(("problem doing g2p")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_PU_IRREG_ITEM, - NULL, NULL); - } - return PICO_OK; -} - - -/* ***********************************************************************/ -/* extract phonemes of an item into a phonBuf */ -/* ***********************************************************************/ - -static pico_status_t saAddPhoneme(register sa_subobj_t *sa, picoos_uint16 pos, picoos_uint16 sym) { - /* picoos_uint8 plane, unshifted; */ - - /* just for debuging */ - /* - unshifted = picotrns_unplane(sym,&plane); - PICODBG_DEBUG(("adding %i/%i (%c on plane %i) at phonBuf[%i]",pos,sym,unshifted,plane,sa->phonWritePos)); - */ - if (PICOTRNS_MAX_NUM_POSSYM <= sa->phonWritePos) { - /* not an error! */ - PICODBG_DEBUG(("couldn't add because phon buffer full")); - return PICO_EXC_BUF_OVERFLOW; - } else { - sa->phonBuf[sa->phonWritePos].pos = pos; - sa->phonBuf[sa->phonWritePos].sym = sym; - sa->phonWritePos++; - return PICO_OK; - } -} - -/* -static pico_status_t saAddStartPhoneme(register sa_subobj_t *sa) { - return saAddPhoneme(sa, PICOTRNS_POS_IGNORE, - (PICOKFST_PLANE_INTERN << 8) + sa->fixedIds->phonStartId); -} - - -static pico_status_t saAddTermPhoneme(register sa_subobj_t *sa) { - return saAddPhoneme(sa, PICOTRNS_POS_IGNORE, - (PICOKFST_PLANE_INTERN << 8) + sa->fixedIds->phonTermId); -} - -*/ - -static pico_status_t saExtractPhonemes(register picodata_ProcessingUnit this, - register sa_subobj_t *sa, picoos_uint16 pos, - picodata_itemhead_t* head, const picoos_uint8* content) -{ - pico_status_t rv= PICO_OK; - picoos_uint8 i; - picoos_int16 fstSymbol; -#if defined(PICO_DEBUG) - picoos_char msgstr[SA_MSGSTR_SIZE]; -#endif - - PICODBG_TRACE(("doing item %s", - picodata_head_to_string(head,msgstr,SA_MSGSTR_SIZE))); - /* - Items considered in a transduction are WORDPHON item. its starting offset within the inBuf is given as - 'pos'. - Elements that go into the transduction receive "their" position in the buffer. - */ - sa->phonWritePos = 0; - /* WORDPHON(POS,WACC)phon */ - rv = saAddPhoneme(sa, PICOTRNS_POS_IGNORE, - (PICOKFST_PLANE_INTERN << 8) + sa->fixedIds->phonStartId); - for (i = 0; i < head->len; i++) { - fstSymbol = /* (PICOKFST_PLANE_PHONEMES << 8) + */content[i]; - /* */ - PICODBG_TRACE(("adding phoneme %c",fstSymbol)); - rv = saAddPhoneme(sa, pos+PICODATA_ITEM_HEADSIZE+i, fstSymbol); - } - rv = saAddPhoneme(sa, PICOTRNS_POS_IGNORE, - (PICOKFST_PLANE_INTERN << 8) + sa->fixedIds->phonTermId); - sa->nextReadPos = pos + PICODATA_ITEM_HEADSIZE + head->len; - return rv; -} - - -#define SA_POSSYM_OK 0 -#define SA_POSSYM_OUT_OF_RANGE 1 -#define SA_POSSYM_END 2 -#define SA_POSSYM_INVALID -3 -/* *readPos is the next position in phonBuf to be read, and *writePos is the first position not to be read (may be outside - * buf). - * 'rangeEnd' is the first possym position outside the desired range. - * Possible return values: - * SA_POSSYM_OK : 'pos' and 'sym' are set to the read possym, *readPos is advanced - * SA_POSSYM_OUT_OF_RANGE : pos is out of range. 'pos' is set to that of the read possym, 'sym' is undefined - * SA_POSSYM_UNDERFLOW : no more data in buf. 'pos' is set to PICOTRNS_POS_INVALID, 'sym' is undefined - * SA_POSSYM_INVALID : "strange" pos. 'pos' is set to PICOTRNS_POS_INVALID, 'sym' is undefined - */ -static pico_status_t getNextPosSym(sa_subobj_t * sa, picoos_int16 * pos, picoos_int16 * sym, - picoos_int16 rangeEnd) { - /* skip POS_IGNORE */ - while ((sa->phonReadPos < sa->phonWritePos) && (PICOTRNS_POS_IGNORE == sa->phonBuf[sa->phonReadPos].pos)) { - PICODBG_DEBUG(("ignoring phone at sa->phonBuf[%i] because it has pos==IGNORE",sa->phonReadPos)); - sa->phonReadPos++; - } - if ((sa->phonReadPos < sa->phonWritePos)) { - *pos = sa->phonBuf[sa->phonReadPos].pos; - if ((PICOTRNS_POS_INSERT == *pos) || ((0 <= *pos) && (*pos < rangeEnd))) { - *sym = sa->phonBuf[sa->phonReadPos++].sym; - return SA_POSSYM_OK; - } else if (*pos < 0){ /* *pos is "strange" (e.g. POS_INVALID) */ - return SA_POSSYM_INVALID; - } else { - return SA_POSSYM_OUT_OF_RANGE; - } - } else { - /* no more possyms to read */ - *pos = PICOTRNS_POS_INVALID; - return SA_POSSYM_END; - } -} - - - - -/* ***********************************************************************/ -/* saStep function */ -/* ***********************************************************************/ - -/* -complete phrase processed in one step, if not fast enough -> rework - -init, collect into internal buffer, process, and then feed to -output buffer - -init state: INIT ext ext -state trans: in hc1 hc2 out - -INIT | putItem = 0 0 +1 | BUSY -> COLL (put B-SBEG item, - set do-init to false) - - inspace-ok-hc1 - needs-more-items-(phrase-or-flush) -COLL1 |getItems -n +n 0 1 | ATOMIC -> PPOSD (got items, - if flush set do-init) -COLL2 |getItems -n +n 1 0 | ATOMIC -> PPOSD (got items, forced) -COLL3 |getItems -n +n 1 1 | IDLE (got items, need more) -COLL4 |getItems = = 1 1 | IDLE (got no items) - -PPOSD | posd = ~n~n | BUSY -> PWP (posd done) -PWP | lex/g2p = ~n-n 0+n | BUSY -> PPHR (lex/g2p done) -PPHR | phr = -n 0 +m=n | BUSY -> PACC (phr done, m>=n) -PACC | acc = 0 0 ~m=n | BUSY -> FEED (acc done) - - doinit-flag -FEED | putItems 0 0 0 -m-n +m 0 | BUSY -> COLL (put items) -FEED | putItems 0 0 0 -m-n +m 1 | BUSY -> INIT (put items) -FEED | putItems 0 0 0 -d-d +d | OUT_FULL (put some items) -*/ - -static picodata_step_result_t saStep(register picodata_ProcessingUnit this, - picoos_int16 mode, - picoos_uint16 *numBytesOutput) { - register sa_subobj_t *sa; - pico_status_t rv = PICO_OK; - pico_status_t rvP = PICO_OK; - picoos_uint16 blen = 0; - picoos_uint16 clen = 0; - picoos_uint16 i; - picoklex_Lex lex; - - - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - sa = (sa_subobj_t *) this->subObj; - mode = mode; /* avoid warning "var not used in this function"*/ - *numBytesOutput = 0; - while (1) { /* exit via return */ - PICODBG_DEBUG(("doing state %i, hLen|c1Len|c2Len: %d|%d|%d", - sa->procState, sa->headxLen, sa->cbuf1Len, - sa->cbuf2Len)); - - switch (sa->procState) { - - /* *********************************************************/ - /* collect state: get item(s) from charBuf and store in - * internal buffers, need a complete punctuation-phrase - */ - case SA_STEPSTATE_COLLECT: - - while (sa->inspaceok && sa->needsmoreitems - && (PICO_OK == - (rv = picodata_cbGetItem(this->cbIn, sa->tmpbuf, - PICOSA_MAXITEMSIZE, &blen)))) { - rvP = picodata_get_itemparts(sa->tmpbuf, - PICOSA_MAXITEMSIZE, - &(sa->headx[sa->headxLen].head), - &(sa->cbuf1[sa->cbuf1Len]), - sa->cbuf1BufSize-sa->cbuf1Len, - &clen); - if (rvP != PICO_OK) { - PICODBG_ERROR(("problem getting item parts")); - picoos_emRaiseException(this->common->em, rvP, - NULL, NULL); - return PICODATA_PU_ERROR; - } - - /* if CMD(...FLUSH...) -> PUNC(...FLUSH...), - construct PUNC-FLUSH item in headx */ - if ((sa->headx[sa->headxLen].head.type == - PICODATA_ITEM_CMD) && - (sa->headx[sa->headxLen].head.info1 == - PICODATA_ITEMINFO1_CMD_FLUSH)) { - sa->headx[sa->headxLen].head.type = - PICODATA_ITEM_PUNC; - sa->headx[sa->headxLen].head.info1 = - PICODATA_ITEMINFO1_PUNC_FLUSH; - sa->headx[sa->headxLen].head.info2 = - PICODATA_ITEMINFO2_PUNC_SENT_T; - sa->headx[sa->headxLen].head.len = 0; - } - - /* convert opening phoneme command to WORDPHON - * and assign user-POS XX to it (Bug 432) */ - sa->headx[sa->headxLen].cind = sa->cbuf1Len; - /* maybe overwritten later */ - if ((sa->headx[sa->headxLen].head.type == - PICODATA_ITEM_CMD) && - (sa->headx[sa->headxLen].head.info1 == - PICODATA_ITEMINFO1_CMD_PHONEME)&& - (sa->headx[sa->headxLen].head.info2 == - PICODATA_ITEMINFO2_CMD_START)) { - picoos_uint8 i; - picoos_uint8 wordsep = picoktab_getWordboundID(sa->tabphones); - PICODBG_INFO(("wordsep id is %i",wordsep)); - sa->headx[sa->headxLen].head.type = PICODATA_ITEM_WORDPHON; - sa->headx[sa->headxLen].head.info1 = PICODATA_POS_XX; - sa->headx[sa->headxLen].head.info2 = PICODATA_ITEMINFO2_NA; - /* cut off additional words */ - i = 0; - while ((i < sa->headx[sa->headxLen].head.len) && (wordsep != sa->cbuf1[sa->headx[sa->headxLen].cind+i])) { - PICODBG_INFO(("accepting phoneme %i",sa->cbuf1[sa->headx[sa->headxLen].cind+i])); - - i++; - } - if (i < sa->headx[sa->headxLen].head.len) { - PICODBG_INFO(("cutting off superfluous phonetic words at %i",i)); - sa->headx[sa->headxLen].head.len = i; - } - } - - /* check/set needsmoreitems */ - if (sa->headx[sa->headxLen].head.type == - PICODATA_ITEM_PUNC) { - sa->needsmoreitems = FALSE; - } - - /* check/set inspaceok, keep spare slot for forcing */ - if ((sa->headxLen >= (PICOSA_MAXNR_HEADX - 2)) || - ((sa->cbuf1BufSize - sa->cbuf1Len) < - PICOSA_MAXITEMSIZE)) { - sa->inspaceok = FALSE; - } - - if (clen > 0) { - sa->headx[sa->headxLen].cind = sa->cbuf1Len; - sa->cbuf1Len += clen; - } else { - sa->headx[sa->headxLen].cind = 0; - } - sa->headxLen++; - } - - if (!sa->needsmoreitems) { - /* 1, phrase buffered */ - sa->procState = SA_STEPSTATE_PROCESS_POSD; - return PICODATA_PU_ATOMIC; - } else if (!sa->inspaceok) { - /* 2, forced phrase end */ - /* at least one slot is still free, use it to - force a trailing PUNC item */ - sa->headx[sa->headxLen].head.type = PICODATA_ITEM_PUNC; - sa->headx[sa->headxLen].head.info1 = - PICODATA_ITEMINFO1_PUNC_PHRASEEND; - sa->headx[sa->headxLen].head.info2 = - PICODATA_ITEMINFO2_PUNC_PHRASE_FORCED; - sa->headx[sa->headxLen].head.len = 0; - sa->needsmoreitems = FALSE; /* not really needed for now */ - sa->headxLen++; - PICODBG_WARN(("forcing phrase end, added PUNC_PHRASEEND")); - picoos_emRaiseWarning(this->common->em, - PICO_WARN_FALLBACK, NULL, - (picoos_char *)"forced phrase end"); - sa->procState = SA_STEPSTATE_PROCESS_POSD; - return PICODATA_PU_ATOMIC; - } else if (rv == PICO_EOF) { - /* 3, 4 */ - return PICODATA_PU_IDLE; - } else if ((rv == PICO_EXC_BUF_UNDERFLOW) || - (rv == PICO_EXC_BUF_OVERFLOW)) { - /* error, no valid item in cb (UNDER) */ - /* or tmpbuf not large enough, not possible (OVER) */ - /* no exception raised, left for ctrl to handle */ - PICODBG_ERROR(("buffer under/overflow, rv: %d", rv)); - return PICODATA_PU_ERROR; - } else { - /* error, only possible if cbGetItem implementation - changes without this function being adapted*/ - PICODBG_ERROR(("untreated return value, rv: %d", rv)); - return PICODATA_PU_ERROR; - } - break; - - - /* *********************************************************/ - /* process posd state: process items in headx/cbuf1 - * and change in place - */ - case SA_STEPSTATE_PROCESS_POSD: - /* ensure there is an item in inBuf */ - if (sa->headxLen > 0) { - /* we have a phrase in headx, cbuf1 (can be - single PUNC item without POS), do pos disamb */ - if (PICO_OK != saDisambPos(this, sa)) { - picoos_emRaiseException(this->common->em, - PICO_ERR_OTHER, NULL, NULL); - return PICODATA_PU_ERROR; - } - sa->procState = SA_STEPSTATE_PROCESS_WPHO; - - } else if (sa->headxLen == 0) { /* no items in inBuf */ - PICODBG_WARN(("no items in inBuf")); - sa->procState = SA_STEPSTATE_COLLECT; - return PICODATA_PU_BUSY; - } - -#if defined (PICO_DEBUG) - if (1) { - picoos_uint8 i, j, ittype; - for (i = 0; i < sa->headxLen; i++) { - ittype = sa->headx[i].head.type; - PICODBG_INFO_CTX(); - PICODBG_INFO_MSG(("sa-d: (")); - PICODBG_INFO_MSG(("'%c',", ittype)); - if ((32 <= sa->headx[i].head.info1) && - (sa->headx[i].head.info1 < 127) && - (ittype != PICODATA_ITEM_WORDGRAPH) && - (ittype != PICODATA_ITEM_WORDINDEX)) { - PICODBG_INFO_MSG(("'%c',",sa->headx[i].head.info1)); - } else { - PICODBG_INFO_MSG(("%3d,", sa->headx[i].head.info1)); - } - if ((32 <= sa->headx[i].head.info2) && - (sa->headx[i].head.info2 < 127)) { - PICODBG_INFO_MSG(("'%c',",sa->headx[i].head.info2)); - } else { - PICODBG_INFO_MSG(("%3d,", sa->headx[i].head.info2)); - } - PICODBG_INFO_MSG(("%3d)", sa->headx[i].head.len)); - - for (j = 0; j < sa->headx[i].head.len; j++) { - if ((ittype == PICODATA_ITEM_WORDGRAPH) || - (ittype == PICODATA_ITEM_CMD)) { - PICODBG_INFO_MSG(("%c", - sa->cbuf1[sa->headx[i].cind+j])); - } else { - PICODBG_INFO_MSG(("%4d", - sa->cbuf1[sa->headx[i].cind+j])); - } - } - PICODBG_INFO_MSG(("\n")); - } - } -#endif - - break; - - - /* *********************************************************/ - /* process wpho state: process items in headx/cbuf1 and modify - * headx in place and fill cbuf2 - */ - case SA_STEPSTATE_PROCESS_WPHO: - /* ensure there is an item in inBuf */ - if (sa->headxLen > 0) { - /* we have a phrase in headx, cbuf1 (can be single - PUNC item), do lex lookup, g2p, or copy */ - - /* check if cbuf2 is empty as it should be */ - if (sa->cbuf2Len > 0) { - /* enforce emptyness */ - PICODBG_WARN(("forcing empty cbuf2, discarding buf")); - picoos_emRaiseWarning(this->common->em, - PICO_WARN_PU_DISCARD_BUF, - NULL, NULL); - } - - /* cbuf2 overflow avoided in saGrapheme*, saLexInd*, - saCopyItem*, phones skipped if needed */ - for (i = 0; i < sa->headxLen; i++) { - switch (sa->headx[i].head.type) { - case PICODATA_ITEM_WORDGRAPH: - if (PICO_OK != saGraphemeToPhoneme(this, sa, - i)) { - /* not possible, phones skipped if needed */ - picoos_emRaiseException(this->common->em, - PICO_ERR_OTHER, - NULL, NULL); - return PICODATA_PU_ERROR; - } - break; - case PICODATA_ITEM_WORDINDEX: - if (0 == sa->headx[i].head.info2) { - lex = sa->lex; - } else { - lex = sa->ulex[sa->headx[i].head.info2-1]; - } - if (PICO_OK != saLexIndLookup(this, sa, lex, i)) { - /* not possible, phones skipped if needed */ - picoos_emRaiseException(this->common->em, - PICO_ERR_OTHER, - NULL, NULL); - return PICODATA_PU_ERROR; - } - break; - default: - /* copy item unmodified, ie. headx untouched, - content from cbuf1 to cbuf2 */ - if (PICO_OK != saCopyItemContent1to2(this, sa, - i)) { - /* not possible, phones skipped if needed */ - picoos_emRaiseException(this->common->em, - PICO_ERR_OTHER, - NULL, NULL); - return PICODATA_PU_ERROR; - } - break; - } - } - /* set cbuf1 to empty */ - sa->cbuf1Len = 0; - sa->procState = SA_STEPSTATE_PROCESS_TRNS_PARSE; - - } else if (sa->headxLen == 0) { /* no items in inBuf */ - PICODBG_WARN(("no items in inBuf")); - sa->procState = SA_STEPSTATE_COLLECT; - return PICODATA_PU_BUSY; - } - -#if defined (PICO_DEBUG) - if (1) { - picoos_uint8 i, j, ittype; - for (i = 0; i < sa->headxLen; i++) { - ittype = sa->headx[i].head.type; - PICODBG_INFO_CTX(); - PICODBG_INFO_MSG(("sa-g: (")); - PICODBG_INFO_MSG(("'%c',", ittype)); - if ((32 <= sa->headx[i].head.info1) && - (sa->headx[i].head.info1 < 127) && - (ittype != PICODATA_ITEM_WORDPHON)) { - PICODBG_INFO_MSG(("'%c',",sa->headx[i].head.info1)); - } else { - PICODBG_INFO_MSG(("%3d,", sa->headx[i].head.info1)); - } - if ((32 <= sa->headx[i].head.info2) && - (sa->headx[i].head.info2 < 127)) { - PICODBG_INFO_MSG(("'%c',",sa->headx[i].head.info2)); - } else { - PICODBG_INFO_MSG(("%3d,", sa->headx[i].head.info2)); - } - PICODBG_INFO_MSG(("%3d)", sa->headx[i].head.len)); - - for (j = 0; j < sa->headx[i].head.len; j++) { - if ((ittype == PICODATA_ITEM_CMD)) { - PICODBG_INFO_MSG(("%c", - sa->cbuf2[sa->headx[i].cind+j])); - } else { - PICODBG_INFO_MSG(("%4d", - sa->cbuf2[sa->headx[i].cind+j])); - } - } - PICODBG_INFO_MSG(("\n")); - } - } -#endif - - break; - - - /* *********************************************************/ - /* transduction parse state: extract phonemes of item in internal outBuf */ - case SA_STEPSTATE_PROCESS_TRNS_PARSE: - - PICODBG_DEBUG(("transduce item (bot, remain): (%d, %d)", - sa->headxBottom, sa->headxLen)); - - /* check for termination condition first */ - if (0 == sa->headxLen) { - /* reset headx, cbuf2 */ - sa->headxBottom = 0; - sa->cbuf2Len = 0; - /* reset collect state support variables */ - sa->inspaceok = TRUE; - sa->needsmoreitems = TRUE; - - sa->procState = SA_STEPSTATE_COLLECT; - return PICODATA_PU_BUSY; - } - - sa->procState = SA_STEPSTATE_FEED; - /* copy item unmodified */ - rv = picodata_put_itemparts( - &(sa->headx[sa->headxBottom].head), - &(sa->cbuf2[sa->headx[sa->headxBottom].cind]), - sa->headx[sa->headxBottom].head.len, sa->tmpbuf, - PICOSA_MAXITEMSIZE, &blen); - - if (PICODATA_ITEM_WORDPHON == sa->headx[sa->headxBottom].head.type) { - PICODBG_DEBUG(("PARSE found WORDPHON")); - rv = saExtractPhonemes(this, sa, 0, &(sa->headx[sa->headxBottom].head), - &(sa->cbuf2[sa->headx[sa->headxBottom].cind])); - if (PICO_OK == rv) { - PICODBG_DEBUG(("PARSE successfully returned from phoneme extraction")); - sa->procState = SA_STEPSTATE_PROCESS_TRNS_FST; - } else { - PICODBG_WARN(("PARSE phone extraction returned exception %i, output WORDPHON untransduced",rv)); - } - } else { - PICODBG_DEBUG(("PARSE found other item, just copying")); - } - if (SA_STEPSTATE_FEED == sa->procState) { - PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], - (picoos_uint8 *)"sa-p: ", - sa->tmpbuf, PICOSA_MAXITEMSIZE); - - } - - /* consume item */ - sa->headxBottom++; - sa->headxLen--; - - break; - - /* *********************************************************/ - /* transduce state: copy item in internal outBuf to tmpBuf and transduce */ - case SA_STEPSTATE_PROCESS_TRNS_FST: - - - - - - /* if no word-level FSTs: doing trivial syllabification instead */ - if (0 == sa->numFsts) { - PICODBG_DEBUG(("doing trivial sylabification with %i phones", sa->phonWritePos)); -#if defined(PICO_DEBUG) - { - PICODBG_INFO_CTX(); - PICODBG_INFO_MSG(("sa trying to trivially syllabify: ")); - PICOTRNS_PRINTSYMSEQ(this->voice->kbArray[PICOKNOW_KBID_DBG], sa->phonBuf, sa->phonWritePos); - PICODBG_INFO_MSG(("\n")); - } -#endif - - picotrns_trivial_syllabify(sa->tabphones, sa->phonBuf, - sa->phonWritePos, sa->phonBufOut, - &sa->phonWritePos,PICOTRNS_MAX_NUM_POSSYM); - PICODBG_DEBUG(("returned from trivial sylabification with %i phones", sa->phonWritePos)); -#if defined(PICO_DEBUG) - { - PICODBG_INFO_CTX(); - PICODBG_INFO_MSG(("sa returned from syllabification: ")); - PICOTRNS_PRINTSYMSEQ(this->voice->kbArray[PICOKNOW_KBID_DBG], sa->phonBufOut, sa->phonWritePos); - PICODBG_INFO_MSG(("\n")); - } -#endif - - /* eliminate deep epsilons */ - PICODBG_DEBUG(("doing epsilon elimination with %i phones", sa->phonWritePos)); - picotrns_eliminate_epsilons(sa->phonBufOut, - sa->phonWritePos, sa->phonBuf, - &sa->phonWritePos,PICOTRNS_MAX_NUM_POSSYM); - PICODBG_DEBUG(("returning from epsilon elimination with %i phones", sa->phonWritePos)); - sa->phonReadPos = 0; - sa->phonesTransduced = 1; - sa->procState = SA_STEPSTATE_FEED; - break; - } - - /* there are word-level FSTs */ - /* termination condition first */ - if (sa->curFst >= sa->numFsts) { - /* reset for next transduction */ - sa->curFst = 0; - sa->phonReadPos = 0; - sa->phonesTransduced = 1; - sa->procState = SA_STEPSTATE_FEED; - break; - } - - /* transduce from phonBufIn to PhonBufOut */ - { - - picoos_uint32 nrSteps; -#if defined(PICO_DEBUG) - { - PICODBG_INFO_CTX(); - PICODBG_INFO_MSG(("sa trying to transduce: ")); - PICOTRNS_PRINTSYMSEQ(this->voice->kbArray[PICOKNOW_KBID_DBG], sa->phonBuf, sa->phonWritePos); - PICODBG_INFO_MSG(("\n")); - } -#endif - picotrns_transduce(sa->fst[sa->curFst], FALSE, - picotrns_printSolution, sa->phonBuf, sa->phonWritePos, sa->phonBufOut, - &sa->phonWritePos, - PICOTRNS_MAX_NUM_POSSYM, sa->altDescBuf, - sa->maxAltDescLen, &nrSteps); -#if defined(PICO_DEBUG) - { - PICODBG_INFO_CTX(); - PICODBG_INFO_MSG(("sa returned from transduction: ")); - PICOTRNS_PRINTSYMSEQ(this->voice->kbArray[PICOKNOW_KBID_DBG], sa->phonBufOut, sa->phonWritePos); - PICODBG_INFO_MSG(("\n")); - } -#endif - } - - - - /* - The trasduction output will contain equivalent items i.e. (x,y') for each (x,y) plus inserted deep symbols (-1,d). - In case of deletions, (x,0) might also be omitted... - */ - /* eliminate deep epsilons */ - picotrns_eliminate_epsilons(sa->phonBufOut, - sa->phonWritePos, sa->phonBuf, &sa->phonWritePos,PICOTRNS_MAX_NUM_POSSYM); - sa->phonesTransduced = 1; - - sa->curFst++; - - return PICODATA_PU_ATOMIC; - /* break; */ - - /* *********************************************************/ - /* feed state: copy item in internal outBuf to output charBuf */ - - case SA_STEPSTATE_FEED: - - PICODBG_DEBUG(("FEED")); - - if (sa->phonesTransduced) { - /* replace original phones by transduced */ - picoos_uint16 phonWritePos = PICODATA_ITEM_HEADSIZE; - picoos_uint8 plane; - picoos_int16 sym, pos; - while (SA_POSSYM_OK == (rv = getNextPosSym(sa,&pos,&sym,sa->nextReadPos))) { - PICODBG_TRACE(("FEED inserting phoneme %c into inBuf[%i]",sym,phonWritePos)); - sym = picotrns_unplane(sym, &plane); - PICODBG_ASSERT((PICOKFST_PLANE_PHONEMES == plane)); - sa->tmpbuf[phonWritePos++] = (picoos_uint8) sym; - } - PICODBG_DEBUG(("FEED setting item length to %i",phonWritePos - PICODATA_ITEM_HEADSIZE)); - picodata_set_itemlen(sa->tmpbuf,PICODATA_ITEM_HEADSIZE,phonWritePos - PICODATA_ITEM_HEADSIZE); - if (SA_POSSYM_INVALID == rv) { - PICODBG_ERROR(("FEED unexpected symbol or unexpected end of phoneme list")); - return (picodata_step_result_t)picoos_emRaiseException(this->common->em, PICO_WARN_INCOMPLETE, NULL, NULL); - } - sa->phonesTransduced = 0; - - } /* if (sa->phonesTransduced) */ - - - rvP = picodata_cbPutItem(this->cbOut, sa->tmpbuf, - PICOSA_MAXITEMSIZE, &clen); - - *numBytesOutput += clen; - - PICODBG_DEBUG(("put item, status: %d", rvP)); - - if (rvP == PICO_OK) { - } else if (rvP == PICO_EXC_BUF_OVERFLOW) { - /* try again next time */ - PICODBG_DEBUG(("feeding overflow")); - return PICODATA_PU_OUT_FULL; - } else { - /* error, should never happen */ - PICODBG_ERROR(("untreated return value, rvP: %d", rvP)); - return PICODATA_PU_ERROR; - } - - PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], - (picoos_uint8 *)"sana: ", - sa->tmpbuf, PICOSA_MAXITEMSIZE); - - sa->procState = SA_STEPSTATE_PROCESS_TRNS_PARSE; - /* return PICODATA_PU_BUSY; */ - break; - - default: - break; - } /* switch */ - - } /* while */ - - /* should be never reached */ - PICODBG_ERROR(("reached end of function")); - picoos_emRaiseException(this->common->em, PICO_ERR_OTHER, NULL, NULL); - return PICODATA_PU_ERROR; -} - -#ifdef __cplusplus -} -#endif - - -/* end */ diff --git a/lib/picosa.h b/lib/picosa.h deleted file mode 100644 index c35da2e..0000000 --- a/lib/picosa.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * 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 picosa.h - * - * sentence analysis - POS disambiguation - Include file - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - - -/** @addtogroup picosa - * ---------------------------------------------------\n - * Pico Sentence analysis \n - * ---------------------------------------------------\n - * -itemtype, iteminfo1, iteminfo2, content -> TYPE(INFO1,INFO2)content -in the following - -items input -=========== - -processed by sa (POS disambiguation): -- WORDGRAPH(POSes,NA)graph -- WORDINDEX(POSes,NA)POS|1ind1...POSN|indN -- CMD(PICODATA_ITEMINFO1_CMD_FLUSH,PICODATA_ITEMINFO2_NA) - -processed by sa (Phrasing, Accentuation): -- PUNC(PUNCtype,PUNCsubtype) - -unprocessed: -- all other item types are forwarded through the PU without modification: - CMD - - -minimal input size (before processing starts) -================== - -processing (POS disambiguation, g2p, lexind, phrasing, accentuation) -is possible with - -- one punctuation-phrase, consisting of a sequence (see below for - limits) of items terminated by a PUNC item. - -(possible but not implemented: as long as the internal buffer is -empty, non-processed item types can be processed immediately) - -Ensuring terminal PUNC item: -- when reading items from the external buffer a CMD(...FLUSH...) is - converted to a PUNC(...FLUSH...) item -- If needed, a PUNC(PHRASE) is artificially added to ensure a phrase - fits in the PUs memory and processing can start. - - -items processed and output -========================== - -precondition: -CMD(...FLUSH...) already converted to PUNC(...FLUSH...) and trailing -PUNC item enforced if necessary. - ----- -1. PROCESS_POSD: processing input WORDGRAPH or WORDINDEX items, after -POS disambiguation (POSes -> POS), results in a sequence of: - --> WORDGRAPH(POS,NA)graph --> WORDINDEX(POS,NA)POS|ind - ----- -2. PROCESS_WPHO: then, after lex-index lookup and G2P in a -sequence of: - --> WORDPHON(POS,NA)phon - -(phon containing primary and secondary word-level stress) - ----- -3. PROCESS_PHR: then, after processing these WORDPHON items, -together with the trailing PUNC item results in: - --> BOUND(BOUNDstrength,BOUNDtype) - -being added in the sequence of WORDPHON (respectively inserted instead -of the PUNC). All PUNC, incl PUNC(...FLUSH...) now gone. - ----- -4. PROCESS_ACC: then, after processing the WORDPHON and BOUND items -results in: - --> WORDPHON(POS,ACC)phon - -A postprocessing step of accentuation is hard-coded in the -accentuation module: In case the whole word does not have any stress -at all (primary or secondary or both) then do the following mapping: - - ACC0 nostress -> ACC0 - ACC1 nostress -> ACC3 - ACC2 nostress -> ACC3 - ACC3 nostress -> ACC3 - ----- -- POS - a single, unambiguous POS - -cf. picodata.h for -- ACC (sentence-level accent (aka prominence)) %d - PICODATA_ACC0 - PICODATA_ACC1 - PICODATA_ACC2 (<- maybe mapped to ACC1, ie. no ACC2 in output) - PICODATA_ACC3 - -- BOUNDstrength %d - PICODATA_ITEMINFO1_BOUND_SBEG (at sentence start) - PICODATA_ITEMINFO1_BOUND_SEND (at sentence end) - PICODATA_ITEMINFO1_BOUND_TERM (replaces a flush) - PICODATA_ITEMINFO1_BOUND_PHR1 (primary boundary) - PICODATA_ITEMINFO1_BOUND_PHR2 (short break) - PICODATA_ITEMINFO1_BOUND_PHR3 (secondary phrase boundary, no break) - PICODATA_ITEMINFO1_BOUND_PHR0 (no break, not produced by sa, not existing - BOUND in item sequence equals PHR0 bound strength) - -- BOUNDtype (created in sa base on punctuation, indicates type of phrase - following the boundary) %d - PICODATA_ITEMINFO2_BOUNDTYPE_P - PICODATA_ITEMINFO2_BOUNDTYPE_T - PICODATA_ITEMINFO2_BOUNDTYPE_Q - PICODATA_ITEMINFO2_BOUNDTYPE_E - - -output sequence (without CMDs): - - = { BOUND(BOUND_SBEG,PHRASEtype) BOUND(BOUND_SEND,..)} BOUND(BOUND_TERM,..) - - - = { BOUND(BOUND_PHR1|2|3,BOUNDtype) } - - = WORDPHON(POS,ACC)phon { WORDPHON(POS,ACC)phon } - - -Done in later PU: mapping ACC & word-level stress to syllable accent value - ACC0 prim -> 0 - ACC1 prim -> 1 - ACC2 prim -> 2 - ACC3 prim -> 3 - ACC0 sec -> 0 - ACC1 sec -> 4 - ACC2 sec -> 4 - ACC3 sec -> 4 - - -other limitations -================= - -- item size: header plus len=256 (valid for Pico in general) -- see defines below for max nr of items. Item heads plus ref. to contents - buffer are stored in array with fixed size elements. Two restrictions: - - MAXNR_HEADX (max nr elements==items in headx array) - - CONTENTSSIZE (max size of all contents together - */ - - -#ifndef PICOSA_H_ -#define PICOSA_H_ - -#include "picoos.h" -#include "picodata.h" -#include "picorsrc.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* nr item restriction: maximum number of extended item heads in headx */ -#define PICOSA_MAXNR_HEADX 60 -/* nr item restriction: maximum size of all item contents together in cont */ -#define PICOSA_MAXSIZE_CBUF 7680 - -/* maximum length of an item incl. head for input GetItem buffer */ -#define PICOSA_MAXITEMSIZE 260 - - -picodata_ProcessingUnit picosa_newSentAnaUnit( - picoos_MemoryManager mm, - picoos_Common common, - picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, - picorsrc_Voice voice); - -#ifdef __cplusplus -} -#endif - - -#endif /*PICOSA_H_*/ diff --git a/lib/picosig.c b/lib/picosig.c deleted file mode 100644 index be44b3c..0000000 --- a/lib/picosig.c +++ /dev/null @@ -1,1280 +0,0 @@ -/* - * 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 picosig.c - * - * Signal Generation PU - Implementation - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#include "picoos.h" -#include "picodsp.h" -#include "picosig2.h" -#include "picodata.h" -#include "picosig.h" -#include "picodbg.h" -#include "picokpdf.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -#define PICOSIG_IN_BUFF_SIZE PICODATA_BUFSIZE_SIG /*input buffer size for SIG */ -#define PICOSIG_OUT_BUFF_SIZE PICODATA_BUFSIZE_SIG /*output buffer size for SIG*/ - -#define PICOSIG_COLLECT 0 -#define PICOSIG_SCHEDULE 1 -#define PICOSIG_PLAY 2 -#define PICOSIG_PROCESS 3 -#define PICOSIG_FEED 4 - -/*---------------------------------------------------------- - // Internal function declarations - //---------------------------------------------------------*/ - -static picodata_step_result_t sigStep(register picodata_ProcessingUnit this, - picoos_int16 mode, picoos_uint16 * numBytesOutput); - -/*---------------------------------------------------------- - // Name : sig_subobj - // Function: subobject definition for the sig processing - // Shortcut: sig - //---------------------------------------------------------*/ -typedef struct sig_subobj -{ - /*----------------------PU voice management------------------------------*/ - /* picorsrc_Voice voice; */ - /*----------------------PU state management------------------------------*/ - picoos_uint8 procState; /* where to take up work at next processing step */ - picoos_uint8 retState; /* where to return after next processing step */ - picoos_uint8 needMoreInput; /* more data necessary to start processing */ - /*----------------------PU input management------------------------------*/ - picoos_uint8 inBuf[PICOSIG_IN_BUFF_SIZE]; /* internal input buffer */ - picoos_uint16 inBufSize;/* actually allocated size */ - picoos_uint16 inReadPos, inWritePos; /* next pos to read/write from/to inBuf*/ - /*Input audio file management*/ - picoos_char sInSDFileName[255]; - picoos_SDFile sInSDFile; - picoos_uint32 sInSDFilePos; - /*----------------------PU output management-----------------------------*/ - picoos_uint8 outBuf[PICOSIG_OUT_BUFF_SIZE]; /* internal output buffer */ - picoos_uint16 outBufSize; /* actually allocated size */ - picoos_uint16 outReadPos, outWritePos; /* next pos to read/write from/to outBuf*/ - picoos_bool outSwitch; /* output destination switch 0:buffer, 1:file*/ - picoos_char sOutSDFileName[255]; /* output file name */ - picoos_SDFile sOutSDFile; /* output file handle */ - picoos_single fSampNorm; /* running normalization factor */ - picoos_uint32 nNumFrame; /* running count for frame number in output items */ - /*---------------------- other working variables ---------------------------*/ - picoos_uint8 innerProcState; /*where to take up work at next processing step*/ - /*-----------------------Definition of the local storage for this PU--------*/ - sig_innerobj_t sig_inner; - picoos_single pMod; /*pitch modifier*/ - picoos_single vMod; /*Volume modifier*/ - picoos_single sMod; /*speaker modifier*/ - /*knowledge bases */ - picokpdf_PdfMUL pdflfz, pdfmgc; - picoos_uint32 scmeanpowLFZ, scmeanpowMGC; - picoos_uint32 scmeanLFZ, scmeanMGC; - picokpdf_PdfPHS pdfphs; - -} sig_subobj_t; - -/* ****************************************************************************** - * generic PU management - ********************************************************************************/ - -/** - * initialization of the PU (processing unit) - * @param this : sig PU object - * @return PICO_OK : init ok - * @return PICO_ERR_OTHER : init failed - * @callgraph - * @callergraph - */ -static pico_status_t sigInitialize(register picodata_ProcessingUnit this) -{ - sig_subobj_t *sig_subObj; - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - sig_subObj = (sig_subobj_t *) this->subObj; - sig_subObj->inBufSize = PICOSIG_IN_BUFF_SIZE; - sig_subObj->outBufSize = PICOSIG_OUT_BUFF_SIZE; - sig_subObj->inReadPos = 0; - sig_subObj->inWritePos = 0; - sig_subObj->outReadPos = 0; - sig_subObj->outWritePos = 0; - sig_subObj->needMoreInput = 0; - sig_subObj->procState = PICOSIG_COLLECT; - sig_subObj->retState = PICOSIG_COLLECT; - sig_subObj->innerProcState = 0; - sig_subObj->nNumFrame = 0; - - /*----------------------------------------------------------------- - * MANAGE Item I/O control management - ------------------------------------------------------------------*/ - sig_subObj->sInSDFile = NULL; - sig_subObj->sInSDFilePos = 0; - sig_subObj->sInSDFileName[0] = '\0'; - sig_subObj->outSwitch = 0; /*PU sends output to buffer (nextPU)*/ - sig_subObj->sOutSDFile = NULL; - sig_subObj->sOutSDFileName[0] = '\0'; - sig_subObj->nNumFrame = 0; - - /*----------------------------------------------------------------- - * MANAGE LINGWARE INITIALIZATION IF NEEDED - ------------------------------------------------------------------*/ - sig_subObj->pdfmgc = picokpdf_getPdfMUL( - this->voice->kbArray[PICOKNOW_KBID_PDF_MGC]); - sig_subObj->pdflfz = picokpdf_getPdfMUL( - this->voice->kbArray[PICOKNOW_KBID_PDF_LFZ]); - sig_subObj->pdfphs = picokpdf_getPdfPHS( - this->voice->kbArray[PICOKNOW_KBID_PDF_PHS]); - - sig_subObj->scmeanpowLFZ = sig_subObj->pdflfz->bigpow - - sig_subObj->pdflfz->meanpow; - sig_subObj->scmeanpowMGC = sig_subObj->pdfmgc->bigpow - - sig_subObj->pdfmgc->meanpow; - sig_subObj->scmeanLFZ = (1 << (picoos_uint32) sig_subObj->scmeanpowLFZ); - sig_subObj->scmeanMGC = (1 << (picoos_uint32) sig_subObj->scmeanpowMGC); - sig_subObj->fSampNorm = PICOSIG_NORM1 * sig_subObj->pdfmgc->amplif; - - /*----------------------------------------------------------------- - * Initialize memory for DSP - * ------------------------------------------------------------------*/ - sigDspInitialize(&(sig_subObj->sig_inner)); - - /*----------------------------------------------------------------- - * Initialize modifiers - * ------------------------------------------------------------------*/ - /*pitch , volume , speaker modifiers*/ - sig_subObj->pMod = 1.0f; - sig_subObj->vMod = 1.0f; - sig_subObj->sMod = 1.0f; - - return PICO_OK; -}/*sigInitialize*/ - -/** - * terminates the PU (processing unit) - * @param this : sig PU object - * @return PICO_OK : termination ok - * @return PICO_ERR_OTHER : termination failed - * @callgraph - * @callergraph - */ -static pico_status_t sigTerminate(register picodata_ProcessingUnit this) -{ - - sig_subobj_t *sig_subObj; - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - sig_subObj = (sig_subobj_t *) this->subObj; - - return PICO_OK; -}/*sigTerminate*/ - -/** - * deallocates the PU (processing unit) sub object - * @param this : sig PU object - * @param mm : the engine memory manager - * @return PICO_OK : deallocation ok - * @return PICO_ERR_OTHER : deallocation failed - * @callgraph - * @callergraph - */ -static pico_status_t sigSubObjDeallocate(register picodata_ProcessingUnit this, - picoos_MemoryManager mm) -{ - sig_subobj_t *sig_subObj; - if ((NULL == this) || ((this)->subObj == NULL)) { - return PICO_ERR_OTHER; - } - sig_subObj = (sig_subobj_t *) (this)->subObj; - - if (sig_subObj->sInSDFile != NULL) { - picoos_sdfCloseIn(this->common, &(sig_subObj->sInSDFile)); - sig_subObj->sInSDFile = NULL; - sig_subObj->sInSDFileName[0] = '\0'; - } - - if (sig_subObj->sOutSDFile != NULL) { - picoos_sdfCloseOut(this->common, &(sig_subObj->sOutSDFile)); - sig_subObj->sOutSDFile = NULL; - sig_subObj->sOutSDFileName[0] = '\0'; - } - - sigDeallocate(mm, &(sig_subObj->sig_inner)); - - picoos_deallocate(this->common->mm, (void *) &this->subObj); - - return PICO_OK; -}/*sigSubObjDeallocate*/ - -/** - * creates a new sig processing unit - * @param mm : the engine memory manager - * @param common : the engine common object - * @param cbIn : the PU input buffer - * @param cbOut : the PU output buffer - * @param voice : the voice descriptor object - * @return a valid PU handle if creation is OK - * @return NULL if creation is !=OK - * @callgraph - * @callergraph - */ -picodata_ProcessingUnit picosig_newSigUnit(picoos_MemoryManager mm, - picoos_Common common, picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, picorsrc_Voice voice) -{ - sig_subobj_t *sig_subObj; - - picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, - cbOut, voice); - if (NULL == this) { - return NULL; - } - this->initialize = sigInitialize; - - PICODBG_DEBUG(("picosig_newSigUnit -- creating SIG PU")); - /*Init function pointers*/ - this->step = sigStep; - this->terminate = sigTerminate; - this->subDeallocate = sigSubObjDeallocate; - /*sub obj allocation*/ - this->subObj = picoos_allocate(mm, sizeof(sig_subobj_t)); - - if (NULL == this->subObj) { - PICODBG_ERROR(("Error in Sig Object allocation")); - picoos_deallocate(mm, (void *) &this); - return NULL; - } - sig_subObj = (sig_subobj_t *) this->subObj; - - /*----------------------------------------------------------------- - * Allocate memory for DSP inner algorithms - * ------------------------------------------------------------------*/ - if (sigAllocate(mm, &(sig_subObj->sig_inner)) != 0) { - PICODBG_ERROR(("Error in Sig Sub Object Allocation")); - picoos_deallocate(mm, (void *) &this); - return NULL; - } - - /*----------------------------------------------------------------- - * Initialize memory for DSP (this may be re-used elsewhere, e.g.Reset) - * ------------------------------------------------------------------*/ - if (PICO_OK != sigInitialize(this)) { - PICODBG_ERROR(("Error in iSig Sub Object initialization")); - sigDeallocate(mm, &(sig_subObj->sig_inner)); - picoos_deallocate(mm, (void *) &this); - return NULL; - }PICODBG_DEBUG(("SIG PU creation succeded!!")); - return this; -}/*picosig_newSigUnit*/ - -/** - * pdf access for phase - * @param this : sig object pointer - * @param phsIndex : index of phase vectot in the pdf - * @param phsVect : pointer to base of array where to store the phase values - * @param numComponents : pointer to the variable to store the number of components - * @return PICO_OK : pdf retrieved - * @return PICO_ERR_OTHER : pdf not retrieved - * @callgraph - * @callergraph - */ -static pico_status_t getPhsFromPdf(register picodata_ProcessingUnit this, - picoos_uint16 phsIndex, picoos_int32 *phsVect, - picoos_int16 *numComponents) -{ - sig_subobj_t *sig_subObj; - picokpdf_PdfPHS pdf; - static int nFrame = 0; - - picoos_uint32 nIndexValue; - picoos_uint8 *nCurrIndexOffset, *nContent; - picoos_uint16 nI; - - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - sig_subObj = (sig_subobj_t *) this->subObj; - pdf = sig_subObj->pdfphs; - /*check incoming index*/ - if (phsIndex >= pdf->numvectors) { - return PICODATA_PU_ERROR; - } - nCurrIndexOffset = ((picoos_uint8*) pdf->indexBase) + phsIndex * sizeof(picoos_uint32); - nIndexValue = (0xFF000000 & ((*(nCurrIndexOffset+3)) << 24)) | (0x00FF0000 & ((*(nCurrIndexOffset+2)) << 16)) | - (0x0000FF00 & ((*(nCurrIndexOffset+1)) << 8)) | (0x000000FF & ((*nCurrIndexOffset))); - nContent = pdf->contentBase; - nContent += nIndexValue; - *numComponents = (picoos_int16) *nContent++; - if (*numComponents>PICODSP_PHASEORDER) { - PICODBG_DEBUG(("WARNING : Frame %d -- Phase vector[%d] Components = %d --> too big\n", nFrame, phsIndex, *numComponents)); - *numComponents = PICODSP_PHASEORDER; - } - for (nI=0; nI<*numComponents; nI++) { - phsVect[nI] = (picoos_int32) *nContent++; - } - for (nI=*numComponents; nIsubObj; - - numinb = numinb; /* avoid warning "var not used in this function"*/ - - /*defaults to 0 for output bytes*/ - *numoutb = 0; - - /*Input buffer contains an item FRAME_PAR*/ - switch (sig_subObj->innerProcState) { - - case 0: - /*--------------------------------------------- - Shifting old values - ---------------------------------------------*/ - for (n_count = 0; n_count < CEPST_BUFF_SIZE-1; n_count++) { - sig_subObj->sig_inner.F0Buff[n_count]=sig_subObj->sig_inner.F0Buff[n_count+1]; - sig_subObj->sig_inner.PhIdBuff[n_count]=sig_subObj->sig_inner.PhIdBuff[n_count+1]; - sig_subObj->sig_inner.VoicingBuff[n_count]=sig_subObj->sig_inner.VoicingBuff[n_count+1]; - sig_subObj->sig_inner.FuVBuff[n_count]=sig_subObj->sig_inner.FuVBuff[n_count+1]; - } - for (n_count = 0; n_count < PHASE_BUFF_SIZE-1; n_count++) { - sig_subObj->sig_inner.VoxBndBuff[n_count]=sig_subObj->sig_inner.VoxBndBuff[n_count+1]; - } - - tmp1 = sig_subObj->sig_inner.CepBuff[0]; - for (n_count = 0; n_count < CEPST_BUFF_SIZE-1; n_count++) { - sig_subObj->sig_inner.CepBuff[n_count]=sig_subObj->sig_inner.CepBuff[n_count+1]; - } - sig_subObj->sig_inner.CepBuff[CEPST_BUFF_SIZE-1]=tmp1; - - tmp1 = sig_subObj->sig_inner.PhsBuff[0]; - for (n_count = 0; n_count < PHASE_BUFF_SIZE-1; n_count++) { - sig_subObj->sig_inner.PhsBuff[n_count]=sig_subObj->sig_inner.PhsBuff[n_count+1]; - } - sig_subObj->sig_inner.PhsBuff[PHASE_BUFF_SIZE-1]=tmp1; - - /*--------------------------------------------- - Frame related initializations - ---------------------------------------------*/ - sig_subObj->sig_inner.prevVoiced_p = sig_subObj->sig_inner.voiced_p; - /*--------------------------------------------- - Get input data from PU buffer in internal buffers - -------------------------------------------------*/ - /*load the phonetic id code*/ - picoos_mem_copy((void *) &sig_subObj->inBuf[inReadPos - + sizeof(picodata_itemhead_t)], /*src*/ - (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ - sig_subObj->sig_inner.PhIdBuff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16; /*store into newest*/ - tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.PhIdBuff[0]; /*assign oldest*/ - sig_subObj->sig_inner.phId_p = (picoos_int16) tmp_uint16; /*assign oldest*/ - - /*load pitch values*/ - for (i = 0; i < sig_subObj->pdflfz->ceporder; i++) { - picoos_mem_copy((void *) &(sig_subObj->inBuf[inReadPos - + sizeof(picodata_itemhead_t) + sizeof(tmp_uint16) + 3 - * i * sizeof(tmp_uint16)]), /*src*/ - (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ - - sig_subObj->sig_inner.F0Buff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16;/*store into newest*/ - tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.F0Buff[0]; /*assign oldest*/ - - /*convert in float*/ - sig_subObj->sig_inner.F0_p - = (tmp_uint16 ? ((picoos_single) tmp_uint16 - / sig_subObj->scmeanLFZ) : (picoos_single) 0.0); - - if (sig_subObj->sig_inner.F0_p != (picoos_single) 0.0f) { - sig_subObj->sig_inner.F0_p = (picoos_single) exp( - (picoos_single) sig_subObj->sig_inner.F0_p); - - } - /* voicing */ - picoos_mem_copy((void *) &(sig_subObj->inBuf[inReadPos - + sizeof(picodata_itemhead_t) + sizeof(tmp_uint16) + 3 - * i * sizeof(tmp_uint16) + sizeof(tmp_uint16)]),/*src*/ - (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ - - sig_subObj->sig_inner.VoicingBuff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16;/*store into newest*/ - tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.VoicingBuff[0]; /*assign oldest*/ - - sig_subObj->sig_inner.voicing = (picoos_single) ((tmp_uint16 - & 0x01) * 8 + (tmp_uint16 & 0x0e) / 2) - / (picoos_single) 15.0f; - - /* unrectified f0 */ - picoos_mem_copy((void *) &(sig_subObj->inBuf[inReadPos - + sizeof(picodata_itemhead_t) + sizeof(tmp_uint16) + 3 - * i * sizeof(tmp_uint16) + 2 * sizeof(tmp_uint16)]),/*src*/ - (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ - - sig_subObj->sig_inner.FuVBuff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16;/*store into newest*/ - tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.FuVBuff[0]; /*assign oldest*/ - - sig_subObj->sig_inner.Fuv_p = (picoos_single) tmp_uint16 - / sig_subObj->scmeanLFZ; - sig_subObj->sig_inner.Fuv_p = (picoos_single) EXP((double)sig_subObj->sig_inner.Fuv_p); - } - /*load cep values*/ - offset = inReadPos + sizeof(picodata_itemhead_t) - + sizeof(tmp_uint16) + - 3 * sig_subObj->pdflfz->ceporder * sizeof(tmp_int16); - - tmp1 = sig_subObj->sig_inner.CepBuff[CEPST_BUFF_SIZE-1]; /*store into CURR */ - tmp2 = sig_subObj->sig_inner.CepBuff[0]; /*assign oldest*/ - - for (i = 0; i < sig_subObj->pdfmgc->ceporder; i++) { - picoos_mem_copy((void *) &(sig_subObj->inBuf[offset + i - * sizeof(tmp_int16)]), /*src*/ - (void *) &tmp_int16, sizeof(tmp_int16)); /*dest+size*/ - - tmp1 [i] = (picoos_int32) tmp_int16; - sig_subObj->sig_inner.wcep_pI[i] = (picoos_int32) tmp2[i]; - } - - if (sig_subObj->inBuf[inReadPos+ 3] > sig_subObj->inBuf[inReadPos+ 2]*2 + 8) { - /*load phase values*/ - /*get the index*/ - picoos_mem_copy((void *) &(sig_subObj->inBuf[offset + sig_subObj->pdfmgc->ceporder - * sizeof(tmp_int16)]), /*src*/ - (void *) &tmp_int16, sizeof(tmp_int16)); /*dest+size*/ - - /*store into buffers*/ - tmp1 = sig_subObj->sig_inner.PhsBuff[PHASE_BUFF_SIZE-1]; - /*retrieve values from pdf*/ - getPhsFromPdf(this, tmp_int16, tmp1, &(sig_subObj->sig_inner.VoxBndBuff[PHASE_BUFF_SIZE-1])); - } else { - /* no support for phase found */ - sig_subObj->sig_inner.VoxBndBuff[PHASE_BUFF_SIZE-1] = 0; - } - - /*pitch modifier*/ - sig_subObj->sig_inner.F0_p *= sig_subObj->pMod; - sig_subObj->sig_inner.Fuv_p *= sig_subObj->pMod; - if (sig_subObj->sig_inner.F0_p > 0.0f) { - sig_subObj->sig_inner.voiced_p = 1; - } else { - sig_subObj->sig_inner.voiced_p = 0; - } - sig_subObj->sig_inner.n_available++; - if (sig_subObj->sig_inner.n_available>3) sig_subObj->sig_inner.n_available = 3; - - if (sig_subObj->sig_inner.n_available < 3) { - return PICO_STEP_BUSY; - } - - sig_subObj->innerProcState = 3; - return PICO_STEP_BUSY; - - case 3: - /*Convert from mfcc to power spectrum*/ - save_transition_frame(&(sig_subObj->sig_inner)); - mel_2_lin_lookup(&(sig_subObj->sig_inner), sig_subObj->scmeanpowMGC); - sig_subObj->innerProcState += 1; - return PICO_STEP_BUSY; - - case 4: - /*Reconstruct PHASE SPECTRUM */ - phase_spec2(&(sig_subObj->sig_inner)); - sig_subObj->innerProcState += 1; - return PICO_STEP_BUSY; - - case 5: - /*Prepare Envelope spectrum for inverse FFT*/ - env_spec(&(sig_subObj->sig_inner)); - sig_subObj->innerProcState += 1; - return PICO_STEP_BUSY; - - case 6: - /*Generate the impulse response of the vocal tract */ - impulse_response(&(sig_subObj->sig_inner)); - sig_subObj->innerProcState += 1; - return PICO_STEP_BUSY; - - case 7: - /*Sum up N impulse responses according to excitation */ - td_psola2(&(sig_subObj->sig_inner)); - sig_subObj->innerProcState += 1; - return PICO_STEP_BUSY; - - case 8: - /*Ovladd */ - overlap_add(&(sig_subObj->sig_inner)); - sig_subObj->innerProcState += 1; - return PICO_STEP_BUSY; - - case 9: - /*----------------------------------------- - Save the output FRAME item (0:hop-1) - swap remaining buffer - ---------------------------------------------*/ - n_frames = 2; - *numoutb = 0; - hop_p_half = (sig_subObj->sig_inner.hop_p) / 2; - for (n_count = 0; n_count < n_frames; n_count++) { - sig_subObj->outBuf[outWritePos] - = (picoos_uint8) PICODATA_ITEM_FRAME; - sig_subObj->outBuf[outWritePos + 1] - = (picoos_uint8) (hop_p_half); - sig_subObj->outBuf[outWritePos + 2] - = (picoos_uint8) (sig_subObj->nNumFrame % ((hop_p_half))); - sig_subObj->outBuf[outWritePos + 3] - = (picoos_uint8) sig_subObj->sig_inner.hop_p; - s_data = (picoos_int16 *) &(sig_subObj->outBuf[outWritePos + 4]); - - /*range control and clipping*/ - mlt = (picoos_int32) ((sig_subObj->fSampNorm * sig_subObj->vMod) - * PICODSP_END_FLOAT_NORM); - t1 = &(sig_subObj->sig_inner.WavBuff_p[n_count * (hop_p_half)]); - for (n_i = 0; n_i < hop_p_half; n_i++) { /*Normalization*/ - f_data = *t1++ * mlt; - if (f_data >= 0) - f_data >>= 14; - else - f_data = -(-f_data >> 14); - if (f_data > PICOSIG_MAXAMP) - f_data = PICOSIG_MAXAMP; - if (f_data < PICOSIG_MINAMP) - f_data = PICOSIG_MINAMP; - *s_data = (picoos_int16) (f_data); - s_data++; - } - sig_subObj->nNumFrame = sig_subObj->nNumFrame + 1; - *numoutb += ((picoos_int16) n_i * sizeof(picoos_int16)) + 4; - outWritePos += *numoutb; - }/*end for n_count*/ - /*Swap remaining buffer*/ - cnt = sig_subObj->sig_inner.m2_p - sig_subObj->sig_inner.hop_p; - tmp1 = sig_subObj->sig_inner.WavBuff_p; - tmp2 - = &(sig_subObj->sig_inner.WavBuff_p[sig_subObj->sig_inner.hop_p]); - FAST_DEVICE(cnt,*(tmp1++)=*(tmp2++);) - ; - cnt = sig_subObj->sig_inner.m2_p - (sig_subObj->sig_inner.m2_p - - sig_subObj->sig_inner.hop_p); - FAST_DEVICE(cnt,*(tmp1++)=0;) - ; - sig_subObj->innerProcState = 0; /*reset to step 0*/ - sig_subObj->nNumFrame += 2; - return PICO_OK; - default: - return PICO_ERR_OTHER; - } - return PICO_ERR_OTHER; -}/*sigProcess*/ - -/** - * selects items to be dealth with by this PU - * @param item : pointer to current item head - * @return TRUE : item should be managed - * @return FALSE : item should be passed on next PU - * @remarks item pointed to by *item should be already valid - * @callgraph - * @callergraph - */ -static pico_status_t sig_deal_with(const picoos_uint8 *item) -{ - picodata_itemhead_t head; - pico_status_t s_result; - s_result = FALSE; - head.type = item[0]; - head.info1 = item[1]; - head.info2 = item[2]; - head.len = item[3]; - switch (head.type) { - case PICODATA_ITEM_FRAME_PAR: - /*the only item that is managed by sig, so far, is "FRAME_PAR"*/ - s_result = TRUE; - break; - case PICODATA_ITEM_CMD: - if ((head.info1 == PICODATA_ITEMINFO1_CMD_PLAY) || (head.info1 - == PICODATA_ITEMINFO1_CMD_SAVE) || (head.info1 - == PICODATA_ITEMINFO1_CMD_UNSAVE)) { - if (head.info2 == PICODATA_ITEMINFO2_CMD_TO_SIG) { - return TRUE; - } - } - if ((head.info1 == PICODATA_ITEMINFO1_CMD_PITCH) || (head.info1 - == PICODATA_ITEMINFO1_CMD_VOLUME) || (head.info1 - == PICODATA_ITEMINFO1_CMD_SPEAKER)) { - return TRUE; - } - break; - default: - break; - } - return s_result; -} /*sig_deal_with*/ - -/** - * selects items to be managed as commands by this PU - * @param item : pointer to current item head - * @return TRUE : item should be managed as a command - * @return FALSE : item is not a PU command - * @remarks item pointed to by *item should be already valid - * @callgraph - * @callergraph - */ -static pico_status_t sig_is_command(const picoos_uint8 *item) -{ - picodata_itemhead_t head; - head.type = item[0]; - head.info1 = item[1]; - head.info2 = item[2]; - head.len = item[3]; - switch (head.type) { - case PICODATA_ITEM_CMD: - if ((head.info1 == PICODATA_ITEMINFO1_CMD_PLAY) || (head.info1 - == PICODATA_ITEMINFO1_CMD_SAVE) || (head.info1 - == PICODATA_ITEMINFO1_CMD_UNSAVE)) { - if (head.info2 == PICODATA_ITEMINFO2_CMD_TO_SIG) { - return TRUE; - } - } - if ((head.info1 == PICODATA_ITEMINFO1_CMD_PITCH) || (head.info1 - == PICODATA_ITEMINFO1_CMD_VOLUME) || (head.info1 - == PICODATA_ITEMINFO1_CMD_SPEAKER)) { - return TRUE; - } - break; - default: - break; - } - return FALSE; -} /*sig_is_command*/ - -/** - * performs a step of the sig processing - * @param this : pointer to current PU (Control Unit) - * @param mode : mode for the PU - * @param numBytesOutput : pointer to number of bytes produced (output) - * @param this : pointer to current PU (Control Unit) - * @return one of the "picodata_step_result_t" values - * @callgraph - * @callergraph - */ -static picodata_step_result_t sigStep(register picodata_ProcessingUnit this, - picoos_int16 mode, picoos_uint16 * numBytesOutput) -{ - register sig_subobj_t * sig_subObj; - pico_status_t s_result; - picoos_bool b_res; - pico_status_t s_deal_with; - picoos_uint16 blen; - picoos_uint16 numinb, numoutb; - pico_status_t rv; - picoos_int16 *s_data; - picoos_int16 hop_p_half; - picoos_uint32 n_samp, n_i; - picoos_char s_temp_file_name[255]; - picoos_uint32 n_start, n_fram, n_bytes; - picoos_single f_value; - picoos_uint16 n_value; - picoos_uint32 n_pos; - /*wav file play volume control*/ - picoos_int16 *s_t1; - picoos_int32 sf_data, sf_mlt; - picoos_uint32 sf; - picoos_encoding_t enc; - picoos_uint32 numSamples; - - numinb = 0; - numoutb = 0; - rv = PICO_OK; - s_result = PICO_OK; - - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - sig_subObj = (sig_subobj_t *) this->subObj; - - /*Init number of output bytes*/ - *numBytesOutput = 0; - - mode = mode; /* avoid warning "var not used in this function" */ - - while (1) { /* exit via return */ - - PICODBG_DEBUG(("picosig.sigStep -- doing state %i",sig_subObj->procState)); - - switch (sig_subObj->procState) { - - case PICOSIG_COLLECT: - /* ************** item collector ***********************************/ - /*collecting items from the PU input buffer*/ - s_result = picodata_cbGetItem(this->cbIn, - &(sig_subObj->inBuf[sig_subObj->inWritePos]), - sig_subObj->inBufSize - sig_subObj->inWritePos, &blen); - - PICODBG_DEBUG(("picosig.sigStep -- got item, status: %d",rv)); - - if (s_result == PICO_EOF) { - /*no items available : remain in state 0 and return idle*/ - return PICODATA_PU_IDLE; - } - if ((PICO_OK == s_result) && (blen > 0)) { - /* we now have one item : CHECK IT */ - s_result = picodata_is_valid_item( - &(sig_subObj->inBuf[sig_subObj->inWritePos]), blen); - if (s_result != TRUE) { - PICODBG_DEBUG(("picosig.sigStep -- item is not valid: discard")); - /*Item not valid : remain in state PICOSIG_COLLECT*/ - return PICODATA_PU_BUSY; - } - /*item ok: it could be sent to schedule state*/ - sig_subObj->inWritePos += blen; - sig_subObj->needMoreInput = FALSE; - sig_subObj->procState = PICOSIG_SCHEDULE; - /* uncomment next to split into two steps */ - return PICODATA_PU_ATOMIC; - } - /*no EOF, no OK --> errors : remain in state PICOSIG_COLLECT and return error*/ - return PICODATA_PU_ERROR; - break; - - case PICOSIG_SCHEDULE: - /* *************** item processing ***********************************/ - numinb = PICODATA_ITEM_HEADSIZE - + sig_subObj->inBuf[sig_subObj->inReadPos + 3]; - - /*verify that current item has to be dealth with by this PU*/ - s_deal_with = sig_deal_with( - &(sig_subObj->inBuf[sig_subObj->inReadPos])); - - switch (s_deal_with) { - - case TRUE: - /* we have to manage this item */ - if (FALSE == sig_is_command( - &(sig_subObj->inBuf[sig_subObj->inReadPos]))) - { - /*no commands, item to deal with : switch to process state*/ - sig_subObj->procState = PICOSIG_PROCESS; - sig_subObj->retState = PICOSIG_COLLECT; - return PICODATA_PU_BUSY; /*data still to process or to feed*/ - - } else { - - /*we need to manage this item as a SIG command-item*/ - - switch (sig_subObj->inBuf[sig_subObj->inReadPos + 1]) { - - case PICODATA_ITEMINFO1_CMD_PLAY: - /*CMD recognized : consume the command */ - sig_subObj->inReadPos += numinb; - if (sig_subObj->inReadPos - >= sig_subObj->inWritePos) { - sig_subObj->inReadPos = 0; - sig_subObj->inWritePos = 0; - } - /*default next state setting*/ - sig_subObj->procState = - sig_subObj->retState = PICOSIG_COLLECT; - - /*--------- wav file play management --------------*/ - if (sig_subObj->sInSDFile != NULL) { - /*input wav file is already open : return*/ - return PICODATA_PU_BUSY; - } - /*get temp file name*/ - picoos_strlcpy( - (picoos_char*) s_temp_file_name, - (picoos_char*) &(sig_subObj->inBuf[sig_subObj->inReadPos - + 4]), - sig_subObj->inBuf[sig_subObj->inReadPos - + 3] + 1); - /*avoid input/output file name clashes*/ - if (sig_subObj->sOutSDFile != NULL) { - if (picoos_strncmp( - (picoos_char*) s_temp_file_name, - (picoos_char*) sig_subObj->sOutSDFileName, - picoos_strlen( - (picoos_char*) s_temp_file_name)) - == 0) { - PICODBG_WARN(("input and output files has the same name!\n")); - return PICODATA_PU_BUSY; - } - } - /*actual sampled data file open*/ - b_res = picoos_sdfOpenIn(this->common, - &(sig_subObj->sInSDFile), - s_temp_file_name, &sf, - &enc, &numSamples); - if (b_res != TRUE) { - PICODBG_DEBUG(("Error on opening file %s\n", s_temp_file_name)); - sig_subObj->sInSDFile = NULL; - sig_subObj->sInSDFileName[0] = '\0'; - return PICODATA_PU_BUSY; - } - /*input file handle is now valid : store filename*/ - picoos_strlcpy( - (picoos_char*) sig_subObj->sInSDFileName, - (picoos_char*) s_temp_file_name, - sig_subObj->inBuf[sig_subObj->inReadPos - + 3] + 1); - sig_subObj->sInSDFilePos = 0; - /*switch to state PLAY and return*/ - sig_subObj->procState = - sig_subObj->retState = PICOSIG_PLAY; - return PICODATA_PU_BUSY; - break; - - case PICODATA_ITEMINFO1_CMD_SAVE: - /*CMD recognized : consume the command */ - sig_subObj->inReadPos += numinb; - if (sig_subObj->inReadPos - >= sig_subObj->inWritePos) { - sig_subObj->inReadPos = 0; - sig_subObj->inWritePos = 0; - } - /*prepare return state*/ - sig_subObj->procState = PICOSIG_COLLECT; - sig_subObj->retState = PICOSIG_COLLECT; - /*check about output file*/ - if ((sig_subObj->sOutSDFile != NULL) - || (sig_subObj->outSwitch == 1)) { - /*output sig file is already active : return*/ - return PICODATA_PU_BUSY; - } - /*get temp file name*/ - picoos_strlcpy( - (picoos_char*) s_temp_file_name, - (picoos_char*) &(sig_subObj->inBuf[sig_subObj->inReadPos - + 4]), - sig_subObj->inBuf[sig_subObj->inReadPos - + 3] + 1); - /*check extension*/ - if (picoos_has_extension(s_temp_file_name, - PICODATA_PUTYPE_WAV_OUTPUT_EXTENSION) - == FALSE){ - /*extension unsupported : return*/ - return PICODATA_PU_BUSY; - } - /*avoid input/output file name clashes*/ - if (sig_subObj->sInSDFile != NULL) { - if (picoos_strncmp( - (picoos_char*) sig_subObj->sInSDFileName, - (picoos_char*) s_temp_file_name, - picoos_strlen( - (picoos_char*) sig_subObj->sInSDFileName)) - == 0) { - /*input and output files has the same name : do not allow opening for writing*/ - PICODBG_WARN(("input and output files has the same name!\n")); - return PICODATA_PU_BUSY; - } - } - /*try to open*/ - picoos_sdfOpenOut(this->common, - &(sig_subObj->sOutSDFile), - s_temp_file_name, - SAMPLE_FREQ_16KHZ, PICOOS_ENC_LIN); - if (sig_subObj->sOutSDFile == NULL) { - PICODBG_DEBUG(("Error on opening file %s\n", sig_subObj->sOutSDFileName)); - sig_subObj->outSwitch = 0; - sig_subObj->sOutSDFileName[0] = '\0'; - } else { - /*open OK*/ - sig_subObj->outSwitch = 1; - /*store output filename*/ - picoos_strlcpy( - (picoos_char*) sig_subObj->sOutSDFileName, - (picoos_char*) s_temp_file_name, - sig_subObj->inBuf[sig_subObj->inReadPos + 3] + 1); - } - return PICODATA_PU_BUSY; - break; - - case PICODATA_ITEMINFO1_CMD_UNSAVE: - /*CMD recognized : consume the command */ - sig_subObj->inReadPos += numinb; - if (sig_subObj->inReadPos - >= sig_subObj->inWritePos) { - sig_subObj->inReadPos = 0; - sig_subObj->inWritePos = 0; - } - /*prepare return state*/ - sig_subObj->procState = PICOSIG_COLLECT; - sig_subObj->retState = PICOSIG_COLLECT; - /*close the output file if any*/ - if ((sig_subObj->sOutSDFile == NULL) - || (sig_subObj->outSwitch == 0)) { - /*output sig file is not active : return*/ - PICODBG_DEBUG(("Error on requesting a binary samples file output closing : no file output handle exist\n")); - return PICODATA_PU_BUSY; - } - picoos_sdfCloseOut(this->common, - &(sig_subObj->sOutSDFile)); - sig_subObj->outSwitch = 0; - sig_subObj->sOutSDFile = NULL; - sig_subObj->sOutSDFileName[0] = '\0'; - return PICODATA_PU_BUSY; - break; - - case PICODATA_ITEMINFO1_CMD_PITCH: - case PICODATA_ITEMINFO1_CMD_VOLUME: - case PICODATA_ITEMINFO1_CMD_SPEAKER: - n_pos = 4; - picoos_read_mem_pi_uint16( - &(sig_subObj->inBuf[sig_subObj->inReadPos]), - &n_pos, &n_value); - b_res = FALSE; - switch (sig_subObj->inBuf[sig_subObj->inReadPos + 2]) { - case 'a' : - /*absloute modifier*/ - f_value = (picoos_single) n_value - / (picoos_single) 100.0f; - b_res = TRUE; - break; - case 'r' : - /*relative modifier*/ - f_value = (picoos_single) n_value - / (picoos_single) 1000.0f; - b_res = TRUE; - break; - default : - f_value = (picoos_single)0; /*avoid warnings*/ - break; - } - if (b_res) { - switch (sig_subObj->inBuf[sig_subObj->inReadPos + 1]) { - case PICODATA_ITEMINFO1_CMD_PITCH : - sig_subObj->pMod = f_value; - break; - case PICODATA_ITEMINFO1_CMD_VOLUME : - sig_subObj->vMod = f_value; - break; - case PICODATA_ITEMINFO1_CMD_SPEAKER : - sig_subObj->sMod = f_value; - sig_subObj->sig_inner.sMod_p - = sig_subObj->sMod; - /*call the function needed to initialize the speaker factor*/ - mel_2_lin_init( - &(sig_subObj->sig_inner)); - break; - default : - break; - } - } - - /*CMD recognized : consume the command */ - sig_subObj->inReadPos += numinb; - if (sig_subObj->inReadPos - >= sig_subObj->inWritePos) { - sig_subObj->inReadPos = 0; - sig_subObj->inWritePos = 0; - } - /*prepare proc state*/ - sig_subObj->procState = PICOSIG_COLLECT; - sig_subObj->retState = PICOSIG_COLLECT; - return PICODATA_PU_BUSY; - break; - default: - break; - }/*switch command type*/ - } /*end if is command*/ - break; - - case FALSE: - - /*we DO NOT have to deal with this item on this PU. - * Normally these are still alive boundary or flush items*/ - /*copy item from PU input to PU output buffer, - * i.e. make it ready to FEED*/ - s_result = picodata_copy_item( - &(sig_subObj->inBuf[sig_subObj->inReadPos]), - numinb, - &(sig_subObj->outBuf[sig_subObj->outWritePos]), - sig_subObj->outBufSize - sig_subObj->outWritePos, - &numoutb); - if (s_result != PICO_OK) { - /*item not prepared properly to be sent to next PU : - * do not change state and retry next time*/ - sig_subObj->procState = PICOSIG_SCHEDULE; - sig_subObj->retState = PICOSIG_COLLECT; - return PICODATA_PU_BUSY; /*data still to process or to feed*/ - } - - /*if end of sentence reset number of frames(only needed for debugging purposes)*/ - if ((sig_subObj->inBuf[sig_subObj->inReadPos] - == PICODATA_ITEM_BOUND) - && ((sig_subObj->inBuf[sig_subObj->inReadPos + 1] - == PICODATA_ITEMINFO1_BOUND_SEND) - || (sig_subObj->inBuf[sig_subObj->inReadPos - + 1] - == PICODATA_ITEMINFO1_BOUND_TERM))) { - PICODBG_INFO(("End of sentence - Processed frames : %d", - sig_subObj->nNumFrame)); - sig_subObj->nNumFrame = 0; - } - - /*item processed and put in oputput buffer : consume the item*/ - sig_subObj->inReadPos += numinb; - sig_subObj->outWritePos += numoutb; - if (sig_subObj->inReadPos >= sig_subObj->inWritePos) { - /* inBuf exhausted */ - sig_subObj->inReadPos = 0; - sig_subObj->inWritePos = 0; - sig_subObj->needMoreInput = FALSE; - } - sig_subObj->procState = PICOSIG_FEED; - sig_subObj->retState = PICOSIG_COLLECT; - return PICODATA_PU_BUSY; /*data still to process or to feed*/ - break; - - default: - break; - }/*end switch s_deal_with*/ - - break; /*end case sig_schedule*/ - - case PICOSIG_PROCESS: - /* *************** item processing ***********************************/ - numinb = PICODATA_ITEM_HEADSIZE - + sig_subObj->inBuf[sig_subObj->inReadPos + 3]; - - /*Process a full item*/ - s_result = sigProcess(this, sig_subObj->inReadPos, numinb, - sig_subObj->outWritePos, &numoutb); - - if (s_result == PICO_OK) { - sig_subObj->inReadPos += numinb; - if (sig_subObj->inReadPos >= sig_subObj->inWritePos) { - sig_subObj->inReadPos = 0; - sig_subObj->inWritePos = 0; - sig_subObj->needMoreInput = FALSE; - } - sig_subObj->outWritePos += numoutb; - sig_subObj->procState = PICOSIG_FEED; - sig_subObj->retState = PICOSIG_COLLECT; - PICODBG_DEBUG(("picosig.sigStep -- leaving PICO_PROC, inReadPos = %i, outWritePos = %i",sig_subObj->inReadPos, sig_subObj->outWritePos)); - return PICODATA_PU_BUSY; /*data to feed*/ - } - return PICODATA_PU_BUSY; /*data still to process : remain in PROCESS STATE*/ - break; - - case PICOSIG_PLAY: - - /*management of wav file play*/ - s_data = (picoos_int16 *) &(sig_subObj->outBuf[sig_subObj->outWritePos + 4]); - hop_p_half = sig_subObj->sig_inner.hop_p / 2; - /*read directly into PU output buffer*/ - n_samp = hop_p_half; - b_res = picoos_sdfGetSamples(sig_subObj->sInSDFile, - sig_subObj->sInSDFilePos, &n_samp, s_data); - sig_subObj->sInSDFilePos += n_samp; - - if ((FALSE == b_res) || (0 == n_samp)) { - /*file play is complete or file read error*/ - picoos_sdfCloseIn(this->common, &(sig_subObj->sInSDFile)); - sig_subObj->sInSDFile = NULL; - sig_subObj->sInSDFileName[0] = '\0'; - sig_subObj->procState = PICOSIG_COLLECT; - sig_subObj->retState = PICOSIG_COLLECT; - return PICODATA_PU_BUSY; /*check if data in input buffer*/ - } - /*-----------------------------------*/ - /*Volume control of wav file playback*/ - /* (code borrowed from sigProcess)*/ - /*Volume mod and clipping control */ - /* directly into PU output buffer*/ - /*-----------------------------------*/ - sf_mlt = (picoos_int32) ((sig_subObj->vMod) * 16.0f); - s_t1 = &(s_data[0]); - - for (n_i = 0; n_i < n_samp; n_i++) { - if (*s_t1 != 0) { - sf_data = (picoos_int32) (*s_t1) * sf_mlt; - sf_data >>= 4; - if (sf_data > PICOSIG_MAXAMP) { - sf_data = PICOSIG_MAXAMP; - } else if (sf_data < PICOSIG_MINAMP) { - sf_data = PICOSIG_MINAMP; - } - *s_t1 = (picoos_int16) (sf_data); - } - s_t1++; - } - /*Add header info*/ - sig_subObj->outBuf[sig_subObj->outWritePos] - = (picoos_uint8) PICODATA_ITEM_FRAME; - sig_subObj->outBuf[sig_subObj->outWritePos + 1] - = (picoos_uint8) n_samp; - sig_subObj->outBuf[sig_subObj->outWritePos + 2] - = (picoos_uint8) (sig_subObj->nNumFrame % (hop_p_half)); /*number of frame % 64*/ - sig_subObj->outBuf[sig_subObj->outWritePos + 3] - = (picoos_uint8) n_samp * 2; - /*Item content*/ - sig_subObj->outWritePos += (n_samp * sizeof(picoos_int16)) + 4; /*including header*/ - sig_subObj->procState = PICOSIG_FEED; - sig_subObj->retState = PICOSIG_PLAY; - break; - - case PICOSIG_FEED: - /* ************** item output/feeding ***********************************/ - switch (sig_subObj->outSwitch) { - case 0: - /*feeding items to PU output buffer*/ - s_result = picodata_cbPutItem(this->cbOut, - &(sig_subObj->outBuf[sig_subObj->outReadPos]), - sig_subObj->outWritePos - sig_subObj->outReadPos, - &numoutb); - break; - case 1: - /*feeding items to file*/ - if (sig_subObj->outBuf[sig_subObj->outReadPos] - == PICODATA_ITEM_FRAME) { - if ((sig_subObj->sOutSDFile) != NULL) { - n_start = (picoos_uint32) (sig_subObj->outReadPos) - + PICODATA_ITEM_HEADSIZE; - n_bytes = (picoos_uint32) sig_subObj->outBuf[(sig_subObj->outReadPos) - + PICODATA_ITEMIND_LEN]; - n_fram = (picoos_uint32) sig_subObj->outBuf[(sig_subObj->outReadPos) - + PICODATA_ITEMIND_INFO2]; - if (picoos_sdfPutSamples( - sig_subObj->sOutSDFile, - n_bytes / 2, - (picoos_int16*) &(sig_subObj->outBuf[n_start]))) { - PICODBG_DEBUG(("Nframe:%d - Nbytes %d\n", n_fram, n_bytes)); - numoutb = n_bytes + 4; - s_result = PICO_OK; - /* also feed item to next PU */ - s_result = picodata_cbPutItem( - this->cbOut, - &(sig_subObj->outBuf[sig_subObj->outReadPos]), - sig_subObj->outWritePos - - sig_subObj->outReadPos, - &numoutb); - } else { - /*write error : close file + cleanup handles*/ - if (sig_subObj->sOutSDFile != NULL) { - picoos_sdfCloseOut(this->common, &(sig_subObj->sOutSDFile)); - sig_subObj->sOutSDFile = NULL; - } - sig_subObj->sOutSDFileName[0] = '\0'; - sig_subObj->outSwitch = 0; - PICODBG_DEBUG(("Error in writing :%d bytes to output file %s\n", numoutb, &(sig_subObj->sOutSDFileName[0]))); - s_result = PICO_ERR_OTHER; - } - } - } else { - /*continue to feed following PU with items != FRAME */ - s_result = picodata_cbPutItem( - this->cbOut, - &(sig_subObj->outBuf[sig_subObj->outReadPos]), - sig_subObj->outWritePos - sig_subObj->outReadPos, - &numoutb); - } - break; - default: - s_result = PICO_ERR_OTHER; - break; - } - PICODBG_DEBUG(("picosig.sigStep -- put item, status: %d",s_result)); - - if (PICO_OK == s_result) { - - sig_subObj->outReadPos += numoutb; - *numBytesOutput = numoutb; - /*-------------------------*/ - /*reset the output pointers*/ - /*-------------------------*/ - if (sig_subObj->outReadPos >= sig_subObj->outWritePos) { - sig_subObj->outReadPos = 0; - sig_subObj->outWritePos = 0; - sig_subObj->procState = sig_subObj->retState; - } - return PICODATA_PU_BUSY; - - } else if (PICO_EXC_BUF_OVERFLOW == s_result) { - - PICODBG_DEBUG(("picosig.sigStep ** feeding, overflow, PICODATA_PU_OUT_FULL")); - return PICODATA_PU_OUT_FULL; - - } else if ((PICO_EXC_BUF_UNDERFLOW == s_result) - || (PICO_ERR_OTHER == s_result)) { - - PICODBG_DEBUG(("picosig.sigStep ** feeding problem, discarding item")); - sig_subObj->outReadPos = 0; - sig_subObj->outWritePos = 0; - sig_subObj->procState = sig_subObj->retState; - return PICODATA_PU_ERROR; - - } - break; - default: - /*NOT feeding items*/ - s_result = PICO_EXC_BUF_IGNORE; - break; - }/*end switch*/ - return PICODATA_PU_BUSY; /*check if there is more data to process after feeding*/ - - }/*end while*/ - return PICODATA_PU_IDLE; -}/*sigStep*/ - -#ifdef __cplusplus -} -#endif - -/* Picosig.c end */ diff --git a/lib/picosig.h b/lib/picosig.h deleted file mode 100644 index 3e29e8f..0000000 --- a/lib/picosig.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 picosig.h - * - * Signal Generation PU - Header file - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -/** - * @addtogroup picosig - * - * Pico Signal Generation module \n - * - * Pico Sig is the PU that makes the parametric representation produce a speech signal. - * The PU receives parametric vectors and translates them into signal vectors. - * Most of the processing is based on this 1 to 1 relationship between input and output vectors. - * - * NOTE : "picosig" includes logically "picosig2" module, that is the DSP implementation of the signal generation. -*/ - -#ifndef PICOSIG_H_ -#define PICOSIG_H_ - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -/* ******************************************************************************* - * items related to the generic interface - ********************************************************************************/ -picodata_ProcessingUnit picosig_newSigUnit( - picoos_MemoryManager mm, - picoos_Common common, - picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, - picorsrc_Voice voice); - -#ifdef __cplusplus -} -#endif - -#endif /*PICOSIG_H_*/ diff --git a/lib/picosig2.c b/lib/picosig2.c deleted file mode 100644 index e431c90..0000000 --- a/lib/picosig2.c +++ /dev/null @@ -1,4090 +0,0 @@ -/* - * 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 picosig2.c - * - * Signal Generation PU - Internal functions - Implementation - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ -#include "picoos.h" -#include "picodsp.h" -#include "picosig2.h" -#include "picofftsg.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif -/*--------------------------------------------------------------------------- - * INTERNAL FUNCTIONS DECLARATION - *---------------------------------------------------------------------------*/ -static void gen_hann2(sig_innerobj_t *sig_inObj); -static void get_simple_excitation(sig_innerobj_t *sig_inObj, - picoos_int16 *nextPeak); -static void enh_wind_init(sig_innerobj_t *sig_inObj); -static void init_rand(sig_innerobj_t *sig_inObj); -static void get_trig(picoos_int32 ang, picoos_int32 *table, picoos_int32 *cs, - picoos_int32 *sn); - -/*--------------------------------------------------------------------------- - * PICO SYSTEM FUNCTIONS - *---------------------------------------------------------------------------*/ -/** - * allocation of DSP memory for SIG PU - * @param mm : memory manager - * @param sig_inObj : sig PU internal object of the sub-object - * @return PICO_OK : allocation successful - * @return PICO_ERR_OTHER : allocation NOT successful - * @callgraph - * @callergraph - */ -pico_status_t sigAllocate(picoos_MemoryManager mm, sig_innerobj_t *sig_inObj) -{ - picoos_int16 *data_i; - picoos_int32 *d32; - picoos_int32 nCount; - - sig_inObj->int_vec22 = - sig_inObj->int_vec23 = - sig_inObj->int_vec24 = - sig_inObj->int_vec25 = - sig_inObj->int_vec26 = - sig_inObj->int_vec28 = - sig_inObj->int_vec29 = - sig_inObj->int_vec38 = - sig_inObj->int_vec30 = - sig_inObj->int_vec31 = - sig_inObj->int_vec32 = - sig_inObj->int_vec33 = - sig_inObj->int_vec34 = - sig_inObj->int_vec35 = - sig_inObj->int_vec36 = - sig_inObj->int_vec37 = - sig_inObj->int_vec38 = - sig_inObj->int_vec39 = - sig_inObj->int_vec40 = NULL; - - sig_inObj->sig_vec1 = NULL; - - sig_inObj->idx_vect1 = sig_inObj->idx_vect2 = sig_inObj->idx_vect4 = NULL; - sig_inObj->idx_vect5 = sig_inObj->idx_vect6 = sig_inObj->idx_vect7 = - sig_inObj->idx_vect8 = sig_inObj->idx_vect9 = NULL; - sig_inObj->ivalue17 = sig_inObj->ivalue18 = 0; - - /*----------------------------------------------------------------- - * Memory allocations - * NOTE : it would be far better to do a single allocation - * and to do pointer initialization inside this routine - * ------------------------------------------------------------------*/ - data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) - * PICODSP_FFTSIZE); - if (NULL == data_i) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->idx_vect1 = data_i; - - data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) - * PICODSP_HFFTSIZE_P1); - if (NULL == data_i) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->idx_vect2 = data_i; - - data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) - * PICODSP_FFTSIZE); - if (NULL == data_i) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->idx_vect4 = data_i; - - data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) - * PICODSP_FFTSIZE); - if (NULL == data_i) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->idx_vect5 = data_i; - - data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) - * PICODSP_FFTSIZE); - if (NULL == data_i) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->idx_vect6 = data_i; - - data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) - * PICODSP_HFFTSIZE_P1); - if (NULL == data_i) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->idx_vect7 = data_i; - - data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) - * PICODSP_MAX_EX); - if (NULL == data_i) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->idx_vect8 = data_i; - - data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) - * PICODSP_MAX_EX); - if (data_i == NULL) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->idx_vect9 = data_i; - - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_FFTSIZE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec22 = d32; - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_FFTSIZE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec23 = d32; - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_FFTSIZE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec24 = d32; - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_FFTSIZE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec25 = d32; - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_FFTSIZE * 2); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec26 = d32; - - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_FFTSIZE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec28 = d32; - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_FFTSIZE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec29 = d32; - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_FFTSIZE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec38 = d32; - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_FFTSIZE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec30 = d32; - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_FFTSIZE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec31 = d32; - - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_FFTSIZE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec32 = d32; - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_FFTSIZE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec33 = d32; - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_N_RAND_TABLE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec34 = d32; - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_N_RAND_TABLE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec35 = d32; - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_N_RAND_TABLE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec36 = d32; - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_N_RAND_TABLE); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec37 = d32; - - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_HFFTSIZE_P1); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec39 = d32; - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) * (1 - + PICODSP_COS_TABLE_LEN)); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec40 = d32; - - for (nCount = 0; nCount < CEPST_BUFF_SIZE; nCount++) { - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) * (PICODSP_CEPORDER)); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec41[nCount] = d32; - } - - for (nCount = 0; nCount < PHASE_BUFF_SIZE; nCount++) { - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) * (PICODSP_PHASEORDER)); - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->int_vec42[nCount] = d32; - } - - d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) - * PICODSP_FFTSIZE * 2); /* - fixed point */ - if (NULL == d32) { - sigDeallocate(mm, sig_inObj); - return PICO_ERR_OTHER; - } - sig_inObj->sig_vec1 = d32; - - return PICO_OK; -}/*sigAllocate*/ - -/** - * frees DSP memory for SIG PU - * @param mm : memory manager - * @param sig_inObj : sig PU internal object of the sub-object - * @return void - * @callgraph - * @callergraph - */ -void sigDeallocate(picoos_MemoryManager mm, sig_innerobj_t *sig_inObj) -{ - picoos_int32 nCount; - /*----------------------------------------------------------------- - * Memory de-allocations - * ------------------------------------------------------------------*/ - if (NULL != sig_inObj->idx_vect1) - picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect1)); - if (NULL != sig_inObj->idx_vect2) - picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect2)); - if (NULL != sig_inObj->idx_vect4) - picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect4)); - if (NULL != sig_inObj->idx_vect5) - picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect5)); - if (NULL != sig_inObj->idx_vect6) - picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect6)); - if (NULL != sig_inObj->idx_vect7) - picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect7)); - if (NULL != sig_inObj->idx_vect8) - picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect8)); - if (NULL != sig_inObj->idx_vect9) - picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect9)); - - if (NULL != sig_inObj->int_vec22) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec22)); - if (NULL != sig_inObj->int_vec23) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec23)); - if (NULL != sig_inObj->int_vec24) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec24)); - if (NULL != sig_inObj->int_vec25) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec25)); - if (NULL != sig_inObj->int_vec26) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec26)); - if (NULL != sig_inObj->int_vec28) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec28)); - if (NULL != sig_inObj->int_vec29) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec29)); - if (NULL != sig_inObj->int_vec38) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec38)); - if (NULL != sig_inObj->int_vec30) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec30)); - if (NULL != sig_inObj->int_vec31) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec31)); - if (NULL != sig_inObj->int_vec32) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec32)); - if (NULL != sig_inObj->int_vec33) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec33)); - if (NULL != sig_inObj->int_vec34) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec34)); - if (NULL != sig_inObj->int_vec35) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec35)); - if (NULL != sig_inObj->int_vec36) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec36)); - if (NULL != sig_inObj->int_vec37) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec37)); - if (NULL != sig_inObj->int_vec39) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec39)); - if (NULL != sig_inObj->int_vec40) - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec40)); - - for (nCount = 0; nCount < CEPST_BUFF_SIZE; nCount++) { - if (NULL != sig_inObj->int_vec41[nCount]) { - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec41[nCount])); - } - } - - for (nCount = 0; nCount < PHASE_BUFF_SIZE; nCount++) { - if (NULL != sig_inObj->int_vec42[nCount]) { - picoos_deallocate(mm, (void *) &(sig_inObj->int_vec42[nCount])); - } - } - - if (NULL != sig_inObj->sig_vec1) { - picoos_deallocate(mm, (void *) &(sig_inObj->sig_vec1)); - } -}/*sigDeAllocate*/ - -/** - * initializes all memory neededed by DSP at instance creation time - * @param sig_inObj : sig PU internal object of the sub-object - * @return void - * @callgraph - * @callergraph - */ -void sigDspInitialize(sig_innerobj_t *sig_inObj) -{ - picoos_int32 i, j; - picoos_int32 *pnt; - - /*----------------------------------------------------------------- - * Initialization - * ------------------------------------------------------------------*/ - sig_inObj->warp_p = PICODSP_FREQ_WARP_FACT; - sig_inObj->VCutoff_p = PICODSP_V_CUTOFF_FREQ; /*voicing cut off frequency in Hz (will be modeled in the future)*/ - sig_inObj->UVCutoff_p = PICODSP_UV_CUTOFF_FREQ;/*unvoiced frames only (periodize lowest components to mask bad voicing transitions)*/ - sig_inObj->Fs_p = PICODSP_SAMP_FREQ; /*Sampling freq*/ - - sig_inObj->m1_p = PICODSP_CEPORDER; - sig_inObj->m2_p = PICODSP_FFTSIZE; /*also initializes windowLen*/ - sig_inObj->framesz_p = PICODSP_DISPLACE; /*1/4th of the frame size = displacement*/ - sig_inObj->hfftsize_p = PICODSP_H_FFTSIZE; /*half of the FFT size*/ - sig_inObj->voxbnd_p = (picoos_int32) ((picoos_single) sig_inObj->hfftsize_p - / ((picoos_single) sig_inObj->Fs_p / (picoos_single) 2) - * (picoos_single) sig_inObj->VCutoff_p); - sig_inObj->voxbnd2_p - = (picoos_int32) ((picoos_single) sig_inObj->hfftsize_p - / ((picoos_single) sig_inObj->Fs_p / (picoos_single) 2) - * (picoos_single) sig_inObj->UVCutoff_p); - sig_inObj->hop_p = sig_inObj->framesz_p; - sig_inObj->nextPeak_p = (((int) (PICODSP_FFTSIZE)) - / ((int) PICODSP_DISPLACE) - 1) * sig_inObj->hop_p; - sig_inObj->phId_p = 0; /*phonetic id*/ - sig_inObj->E_p = (picoos_single) 0.0f; - sig_inObj->F0_p = (picoos_single) 0.0f; - sig_inObj->voiced_p = 0; - sig_inObj->nV = sig_inObj->nU = 0; - sig_inObj->sMod_p = (picoos_single) 1.0f; - - /*cleanup vectors*/ - for (i = 0; i < 2 * PICODSP_FFTSIZE; i++) { - sig_inObj->sig_vec1[i] = 0; - sig_inObj->int_vec26[i] = 0; /*wav buff cleanup */ - } - - for (i = 0; i < PICODSP_FFTSIZE; i++) { - sig_inObj->idx_vect1[i] = sig_inObj->idx_vect4[i] - = sig_inObj->idx_vect5[i] = sig_inObj->idx_vect6[i] = 0; - sig_inObj->int_vec32[i] = sig_inObj->int_vec33[i] = 0; - } - - for (i = 0; i < PICODSP_HFFTSIZE_P1; i++) { - sig_inObj->idx_vect2[i] = (picoos_int16) 0; - } - - for (i = 0; i < CEPST_BUFF_SIZE; i++) { - sig_inObj->F0Buff[i]=0; - sig_inObj->PhIdBuff[i]=0; - sig_inObj->VoicingBuff[i]=0; - sig_inObj->FuVBuff[i]=0; - if (NULL != sig_inObj->CepBuff[i]) { - pnt = sig_inObj->CepBuff[i]; - for (j = 0; j < PICODSP_CEPORDER; j++) { - pnt[j] = 0; - } - } - } - - for (i = 0; i < PHASE_BUFF_SIZE; i++) { - if (NULL != sig_inObj->int_vec42[i]) { - pnt = sig_inObj->int_vec42[i]; - for (j = 0; j < PICODSP_PHASEORDER; j++) { - pnt[j] = 0; - } - } - } - sig_inObj->n_available=0; - /*--------------------------------------------- - Init formant enhancement window - hanning window, - Post Filter Hermite's interpolator Matrix - Mel-2-Lin lookup tables - ---------------------------------------------*/ - enh_wind_init(sig_inObj); /*creates the formant enhancement window*/ - init_rand(sig_inObj); - gen_hann2(sig_inObj); - mel_2_lin_init(sig_inObj); - -}/*sigDspInitialize*/ - -/*------------------------------------------------------------------------------- - PROCESSING FUNCTIONS : CALLED WITHIN sigStep (cfr. picosig.c) - --------------------------------------------------------------------------------*/ -/** - * convert from mel scale to linear scale - * @param sig_inObj : sig PU internal object of the sub-object - * @param scmeanMGC : mean value of the MGC - * @return void - * @callgraph - * @callergraph - * @remarks translated from matlab code to c-code - * Input - * - c1 : input mfcc vector (ceporder=m1, real) - * - m1 : input order - * - A,B,D : lookup tables - * - m2 : output order - * - Xr,Xi (m2=FFT size, real) temporary arrays for FFT - * - WNr,WNi (m2=FFT size, real) cos and sin precalculated tables - * Output - * - Xr (m2=FFT size, real) linear cepstral vector - */ -void mel_2_lin_lookup(sig_innerobj_t *sig_inObj, picoos_uint32 scmeanMGC) -{ - /*Local vars*/ - picoos_int16 nI, k; - picoos_int32 delta, term1, term2; - - /*Local vars to be linked with sig data object*/ - picoos_int32 *c1, *XXr; - picoos_single K1; - picoos_int32 *D, K2, shift; - picoos_int16 m1, *A, m2, m4, voiced, i; - - /*Link local variables with sig data object*/ - c1 = sig_inObj->wcep_pI; - m1 = sig_inObj->m1_p; - m2 = PICODSP_FFTSIZE; - m4 = m2 >> 1; - - A = sig_inObj->A_p; - D = sig_inObj->d_p; - - XXr = sig_inObj->wcep_pI; - voiced = sig_inObj->voiced_p; - - shift = 27 - scmeanMGC; - K2 = 1 << shift; - K1 = (picoos_single) PICODSP_START_FLOAT_NORM * K2; - XXr[0] = (picoos_int32) ((picoos_single) c1[0] * K1); - for (nI = 1; nI < m1; nI++) { - XXr[nI] = c1[nI] << shift; - } - i = sizeof(picoos_int32) * (PICODSP_FFTSIZE + 1 - m1); - picoos_mem_set(XXr + m1, 0, i); - dfct_nmf(m4, XXr); /* DFCT directly in fixed point */ - - /* ***************************************************************************************** - Linear frequency scale envelope through interpolation. - Two additions and one multiplication per entry. - - Optimization of linear interpolation algorithm - - Start from 1 and stop at PICODSP_H_FFTSIZE-1 because 0 and PICODSP_H_FFTSIZE are invariant points - - B[k]=A[k]+1 except for 0 and PICODSP_H_FFTSIZE - - get rid of extra -1 operation by adapting the table A[] - - *******************************************************************************************/ - for (nI = 1; nI < PICODSP_H_FFTSIZE; nI++) { - k = A[nI]; - term2 = XXr[k]; - term1 = XXr[k + 1]; - delta = term1 - term2; - XXr[nI] = term2 + ((D[nI] * delta) >> 5); /* ok because nI<=A[nI] <=B[nI] */ - } -}/*mel_2_lin_lookup*/ - -/** - * calculate phase - * @remarks voiced phase taken from phase codebook and smoothed, - * @remarks unvoiced phase - random - * @param sig_inObj : sig PU internal object of the sub-object - * @return void - * @callgraph - * @callergraph - */ -void phase_spec2(sig_innerobj_t *sig_inObj) -{ - picoos_int16 nI, iRand, firstUV; - picoos_int32 *tmp1, *tmp2; - picoos_int16 VOXBND_M1; - picoos_int32 *spect, *ang; - picoos_int16 voiced, m2; - picoos_int32 *co, *so, *c, *s, voxbnd, voxbnd2; - picoos_int16 i,j, k, n_comp; - picoos_int16 *Pvoxbnd; - picoos_int32 *phs_p2, *phs_p1, *phs_n1, *phs_n2; - picoos_int32 *phs; - - /*Link local variables to sig data object*/ - spect = sig_inObj->wcep_pI; /* spect_p;*/ - /* current spect scale : times PICODSP_FIX_SCALE1 */ - ang = sig_inObj->ang_p; - voxbnd = (picoos_int32) (sig_inObj->voxbnd_p * sig_inObj->voicing); - voxbnd2 = sig_inObj->voxbnd2_p; - voiced = sig_inObj->voiced_p; - m2 = sig_inObj->m2_p; - VOXBND_M1 = voxbnd - 1; - firstUV = 1; - - /*code starts here*/ - if (voiced == 1) { - firstUV = voxbnd; - Pvoxbnd = sig_inObj->VoxBndBuff; - n_comp = Pvoxbnd[2]; - phs_p2 = sig_inObj->PhsBuff[0]; - phs_p1 = sig_inObj->PhsBuff[1]; - phs = sig_inObj->PhsBuff[2]; - phs_n1 = sig_inObj->PhsBuff[3]; - phs_n2 = sig_inObj->PhsBuff[4]; - - /* find and smooth components which have full context */ - j = n_comp; - for (i=0; i<5; i++) { - if (Pvoxbnd[i]=0)?(*tmp2)>>PICODSP_SHIFT_FACT4:-((-(*tmp2))>>PICODSP_SHIFT_FACT4);tmp2++); - *tmp2 = (*tmp2 >= 0) ? (*tmp2) >> PICODSP_SHIFT_FACT4 : -((-(*tmp2)) - >> PICODSP_SHIFT_FACT4); /*ang[voxbnd-1]/=2;*/ - } - - /* now for the unvoiced part */ - iRand = sig_inObj->iRand; - c = sig_inObj->randCosTbl + iRand; - s = sig_inObj->randSinTbl + iRand; - co = sig_inObj->outCosTbl + firstUV; - so = sig_inObj->outSinTbl + firstUV; - for (nI = firstUV; nI < PICODSP_HFFTSIZE_P1 - 1; nI++) { - *co++ = *c++; - *so++ = *s++; - } - *co = 1; - *so = 0; - sig_inObj->iRand += (PICODSP_HFFTSIZE_P1 - firstUV); - if (sig_inObj->iRand > PICODSP_N_RAND_TABLE - PICODSP_HFFTSIZE_P1) - sig_inObj->iRand = 1 + sig_inObj->iRand + PICODSP_HFFTSIZE_P1 - - PICODSP_N_RAND_TABLE; -}/*phase_spec2*/ - -/** - * Prepare Envelope spectrum for inverse FFT - * @param sig_inObj : sig PU internal object of the sub-object - * @return void - * @remarks make phase bilateral -->> angh (FFT size, real) - * @remarks combine in complex input vector for IFFT F = e**(spet/2+j*ang) - * @remarks Compute energy -->> E (scalar, real) - * @callgraph - * @callergraph - * Input - * - spect (FFT size, real) - * - ang (half FFT size -1, real) - * - m2 fftsize - * - WNr,WNi (FFT size, real) the tabulated sine and cosine values - * - brev (FFT size, real) the tabulated bit reversal indexes - * Output - * - Fr, Fi (FFT size, complex) the envelope spectrum - * - E (scalar, real) the energy - */ -void env_spec(sig_innerobj_t *sig_inObj) -{ - - picoos_int16 nI; - picoos_int32 fcX, fsX, fExp, voxbnd; - picoos_int32 *spect, *ang, *ctbl; - picoos_int16 voiced, prev_voiced; - picoos_int32 *co, *so; - picoos_int32 *Fr, *Fi; - picoos_single mult; - - /*Link local variables to sig object*/ - spect = sig_inObj->wcep_pI; /*spect_p*/ - /* current spect scale : times PICODSP_FIX_SCALE1 */ - ang = sig_inObj->ang_p; - /* current spect scale : PICODSP_M_PI = PICODSP_FIX_SCALE2 */ - Fr = sig_inObj->F2r_p; - Fi = sig_inObj->F2i_p; - voiced = sig_inObj->voiced_p; - prev_voiced = sig_inObj->prevVoiced_p; - voxbnd = (picoos_int32) (sig_inObj->voxbnd_p * sig_inObj->voicing); - ctbl = sig_inObj->cos_table; - /* ctbl scale : times 4096 */ - mult = PICODSP_ENVSPEC_K1 / PICODSP_FIX_SCALE1; - - /*remove dc from real part*/ - if (sig_inObj->F0_p > 120) { - spect[0] = spect[1] = 0; - spect[2] /= PICODSP_ENVSPEC_K2; - } else { - spect[0] = 0; - } - - /* if using rand table, use sin and cos tables as well */ - if (voiced || (prev_voiced)) { - /*Envelope becomes a complex exponential : F=exp(.5*spect + j*angh);*/ - for (nI = 0; nI < voxbnd; nI++) { - get_trig(ang[nI], ctbl, &fcX, &fsX); - fExp = (picoos_int32) EXP((double)spect[nI]*mult); - Fr[nI] = fExp * fcX; - Fi[nI] = fExp * fsX; - } - /* ao=sig_inObj->ang_p+(picoos_int32)voxbnd; */ - co = sig_inObj->outCosTbl + voxbnd; - so = sig_inObj->outSinTbl + voxbnd; - - for (nI = voxbnd; nI < PICODSP_HFFTSIZE_P1; nI++) { - fcX = *co++; - fsX = *so++; - fExp = (picoos_int32) EXP((double)spect[nI]*mult); - Fr[nI] = fExp * fcX; - Fi[nI] = fExp * fsX; - } - } else { - /*ao=sig_inObj->ang_p+1;*/ - co = sig_inObj->outCosTbl + 1; - so = sig_inObj->outSinTbl + 1; - for (nI = 1; nI < PICODSP_HFFTSIZE_P1; nI++) { - fcX = *co++; - fsX = *so++; - fExp = (picoos_int32) EXP((double)spect[nI]*mult); - - Fr[nI] = fExp * fcX; - Fi[nI] = fExp * fsX; - } - } - -}/*env_spec*/ - -/** - * Calculates the impulse response of the comlpex spectrum through inverse rFFT - * @param sig_inObj : sig PU internal object of the sub-object - * @return void - * @remarks Imp corresponds with the real part of the FFT - * @callgraph - * @callergraph - * Input - * - Fr, Fi (FFT size, real & imaginary) the complex envelope spectrum (only first half of spectrum) - * Output - * - Imp: impulse response (length: m2) - * - E (scalar, real) RMS value - */ -void impulse_response(sig_innerobj_t *sig_inObj) -{ - /*Define local variables*/ - picoos_single f; - picoos_int16 nI, nn, m2, m4, voiced; - picoos_single *E; - picoos_int32 *norm_window; /* - fixed point */ - picoos_int32 *fr, *Fr, *Fi, *t1, ff; /* - fixed point */ - - /*Link local variables with sig object*/ - m2 = sig_inObj->m2_p; - m4 = m2 >> 1; - Fr = sig_inObj->F2r_p; - Fi = sig_inObj->F2i_p; - norm_window = sig_inObj->norm_window_p; - E = &(sig_inObj->E_p); /*as pointer: value will be modified*/ - voiced = sig_inObj->voiced_p; - fr = sig_inObj->imp_p; - - /*Inverse FFT*/ - for (nI = 0, nn = 0; nI < m4; nI++, nn += 2) { - fr[nn] = Fr[nI]; /* - fixed point */ - } - - fr[1] = (picoos_int32) (Fr[m4]); - for (nI = 1, nn = 3; nI < m4; nI++, nn += 2) { - fr[nn] = -Fi[nI]; /* - fixed point */ - } - - rdft(m2, -1, fr); - /*window, normalize and differentiate*/ - *E = norm_result(m2, fr, norm_window); - - if (*E > 0) - f = *E * PICODSP_FIXRESP_NORM; - else - f = 20; /*PICODSP_FIXRESP_NORM*/ - ff = (picoos_int32) f; - if (ff < 1) - ff = 1; - /*normalize impulse response*/ - t1 = fr;FAST_DEVICE(PICODSP_FFTSIZE,*(t1++) /= ff;); /* - fixed point */ - -} /* impulse_response */ - -/** - * time domain pitch synchronous overlap add over two frames (when no voicing transition) - * @param sig_inObj : sig PU internal object of the sub-object - * @return void - * @remarks Special treatment at voicing boundaries - * @remarks Introduced to get rid of time-domain aliasing (and additional speed up) - * @callgraph - * @callergraph - */ -void td_psola2(sig_innerobj_t *sig_inObj) -{ - picoos_int16 nI; - picoos_int16 hop, m2, *nextPeak, voiced; - picoos_int32 *t1, *t2; - picoos_int16 cnt; - picoos_int32 *fr, *v1, ff, f; - picoos_int16 a, i; - picoos_int32 *window; - picoos_int16 s = (picoos_int16) 1; - window = sig_inObj->window_p; - - /*Link local variables with sig object*/ - hop = sig_inObj->hop_p; - m2 = sig_inObj->m2_p; - nextPeak = &(sig_inObj->nextPeak_p); - voiced = sig_inObj->voiced_p; - fr = sig_inObj->imp_p; - /*toggle the pointers and initialize signal vector */ - v1 = sig_inObj->sig_vec1; - - t1 = v1; - FAST_DEVICE(PICODSP_FFTSIZE-PICODSP_DISPLACE,*(t1++)=0;); - t1 = &(v1[PICODSP_FFTSIZE - PICODSP_DISPLACE]); - t2 = &(v1[PICODSP_FFTSIZE]); - FAST_DEVICE(PICODSP_FFTSIZE, *(t1++)=*(t2++);); - t1 = &(v1[2 * PICODSP_FFTSIZE - PICODSP_DISPLACE]);FAST_DEVICE(PICODSP_DISPLACE,*(t1++)=0;); - /*calculate excitation points*/ - get_simple_excitation(sig_inObj, nextPeak); - - /*TD-PSOLA based on excitation vector */ - if ((sig_inObj->nU == 0) && (sig_inObj->voiced_p == 1)) { - /* purely voiced */ - for (nI = 0; nI < sig_inObj->nV; nI++) { - f = sig_inObj->EnV[nI]; - a = 0; - cnt = PICODSP_FFTSIZE; - ff = (f * window[sig_inObj->LocV[nI]]) >> PICODSP_SHIFT_FACT1; - t1 = &(v1[a + sig_inObj->LocV[nI]]); - t2 = &(fr[a]); - if (cnt > 0)FAST_DEVICE(cnt,*(t1++)+=*(t2++)*ff;); - } - } else if ((sig_inObj->nV == 0) && (sig_inObj->voiced_p == 0)) { - /* PURELY UNVOICED*/ - for (nI = 0; nI < sig_inObj->nU; nI++) { - f = sig_inObj->EnU[nI]; - s = -s; /*reverse order to reduce the periodicity effect*/ - if (s == 1) { - a = 0; - cnt = PICODSP_FFTSIZE; - ff = (f * window[sig_inObj->LocU[nI]]) >> PICODSP_SHIFT_FACT1; - t1 = &(v1[a + sig_inObj->LocU[nI]]); - t2 = &(fr[a]); - if (cnt > 0)FAST_DEVICE(cnt,*(t1++)+=*(t2++)*ff; ); - } else { /*s==-1*/ - a = 0; - cnt = PICODSP_FFTSIZE; - ff = (f * window[sig_inObj->LocU[nI]]) >> PICODSP_SHIFT_FACT1; - t1 = &(v1[(m2 - 1 - a) + sig_inObj->LocU[nI]]); - t2 = &(fr[a]); - if (cnt > 0)FAST_DEVICE(cnt,*(t1--)+=*(t2++)*ff; ); - } - } - } else if (sig_inObj->VoicTrans == 0) { - /*voicing transition from unvoiced to voiced*/ - for (nI = 0; nI < sig_inObj->nV; nI++) { - f = sig_inObj->EnV[nI]; - a = 0; - cnt = PICODSP_FFTSIZE; - ff = (f * window[sig_inObj->LocV[nI]]) >> PICODSP_SHIFT_FACT1; - t1 = &(v1[a + sig_inObj->LocV[nI]]); - t2 = &(fr[a]); - if (cnt > 0)FAST_DEVICE(cnt,*(t1++)+=*(t2++)*ff;); - } - /*add remaining stuff from unvoiced part*/ - for (nI = 0; nI < sig_inObj->nU; nI++) { - f = sig_inObj->EnU[nI]; - s = -s; /*reverse order to reduce the periodicity effect*/ - if (s == 1) { - a = 0; - cnt = PICODSP_FFTSIZE; - ff = (f * window[sig_inObj->LocU[nI]]) >> PICODSP_SHIFT_FACT1; - t1 = &(v1[a + sig_inObj->LocU[nI]]); - t2 = &(sig_inObj->ImpResp_p[a]); /*saved impulse response*/ - if (cnt > 0)FAST_DEVICE(cnt,*(t1++)+=*(t2++)*ff; ); - } else { - a = 0; - cnt = PICODSP_FFTSIZE; - ff = (f * window[sig_inObj->LocU[nI]]) >> PICODSP_SHIFT_FACT1; - t1 = &(v1[(m2 - 1 - a) + sig_inObj->LocU[nI]]); - t2 = &(sig_inObj->ImpResp_p[a]); - if (cnt > 0)FAST_DEVICE(cnt,*(t1--)+=*(t2++)*ff; ); - } - } - } else { - /*voiced to unvoiced*/ - for (nI = 0; nI < sig_inObj->nU; nI++) { - f = sig_inObj->EnU[nI]; - s = -s; /*reverse order to reduce the periodicity effect*/ - if (s > 0) { - a = 0; - cnt = PICODSP_FFTSIZE; - ff = (f * window[sig_inObj->LocU[nI]]) >> PICODSP_SHIFT_FACT1; - t1 = &(v1[a + sig_inObj->LocU[nI]]); - t2 = &(fr[a]); - if (cnt > 0)FAST_DEVICE(cnt,*(t1++)+=*(t2++)*ff; ); - } else { - a = 0; - cnt = PICODSP_FFTSIZE; - ff = (f * window[sig_inObj->LocU[nI]]) >> PICODSP_SHIFT_FACT1; - t1 = &(v1[(m2 - 1 - a) + sig_inObj->LocU[nI]]); - t2 = &(fr[a]); - if (cnt > 0)FAST_DEVICE(cnt,*(t1--)+=*(t2++)*ff; ); - } - } - /*add remaining stuff from voiced part*/ - for (nI = 0; nI < sig_inObj->nV; nI++) { - f = sig_inObj->EnV[nI]; - a = 0; - cnt = PICODSP_FFTSIZE; - ff = (f * window[sig_inObj->LocV[nI]]) >> PICODSP_SHIFT_FACT1; - t1 = &(v1[a + sig_inObj->LocV[nI]]); - t2 = &(sig_inObj->ImpResp_p[a]); - if (cnt > 0)FAST_DEVICE(cnt,*(t1++)+=*(t2++)*ff;); - } - } - - t1 = sig_inObj->sig_vec1; - for (i = 0; i < PICODSP_FFTSIZE; i++, t1++) { - if (*t1 >= 0) - *t1 >>= PICODSP_SHIFT_FACT5; - else - *t1 = -((-*t1) >> PICODSP_SHIFT_FACT5); - } - -}/*td_psola2*/ - -/** - * overlap + add summing of impulse responses on the final destination sample buffer - * @param sig_inObj : sig PU internal object of the sub-object - * @return void - * @remarks Special treatment at voicing boundaries - * @remarks Introduced to get rid of time-domain aliasing (and additional speed up) - * Input - * - wlet : the generic impulse response (FFT size, real) - * - window : the windowing funcion (FFT size, real) fixed - * - WavBuff : the destination buffer with past samples (FFT size*2, short) - * - m2 : fftsize - * Output - * - WavBuff : the destination buffer with updated samples (FFT size*2, short) - * @callgraph - * @callergraph - */ -void overlap_add(sig_innerobj_t *sig_inObj) -{ - /*Local variables*/ - picoos_int32 *w, *v; - - /*Link local variables with sig object*/ - w = sig_inObj->WavBuff_p; - v = sig_inObj->sig_vec1; - - FAST_DEVICE(PICODSP_FFTSIZE, *(w++)+=*(v++)<window_p; - norm = sig_inObj->norm_window_p; - - norm[0] = 80224; - norm[1] = 320832; - norm[2] = 721696; - norm[3] = 1282560; - norm[4] = 2003104; - norm[5] = 2882880; - norm[6] = 3921376; - norm[7] = 5117984; - norm[8] = 6471952; - norm[9] = 7982496; - norm[10] = 9648720; - norm[11] = 11469616; - norm[12] = 13444080; - norm[13] = 15570960; - norm[14] = 17848976; - norm[15] = 20276752; - norm[16] = 22852864; - norm[17] = 25575744; - norm[18] = 28443776; - norm[19] = 31455264; - norm[20] = 34608368; - norm[21] = 37901248; - norm[22] = 41331904; - norm[23] = 44898304; - norm[24] = 48598304; - norm[25] = 52429696; - norm[26] = 56390192; - norm[27] = 60477408; - norm[28] = 64688944; - norm[29] = 69022240; - norm[30] = 73474720; - norm[31] = 78043744; - norm[32] = 82726544; - norm[33] = 87520352; - norm[34] = 92422272; - norm[35] = 97429408; - norm[36] = 102538752; - norm[37] = 107747248; - norm[38] = 113051776; - norm[39] = 118449184; - norm[40] = 123936224; - norm[41] = 129509648; - norm[42] = 135166080; - norm[43] = 140902192; - norm[44] = 146714528; - norm[45] = 152599584; - norm[46] = 158553904; - norm[47] = 164573888; - norm[48] = 170655936; - norm[49] = 176796448; - norm[50] = 182991712; - norm[51] = 189238064; - norm[52] = 195531744; - norm[53] = 201868992; - norm[54] = 208246016; - norm[55] = 214659040; - norm[56] = 221104176; - norm[57] = 227577616; - norm[58] = 234075488; - norm[59] = 240593872; - norm[60] = 247128912; - norm[61] = 253676688; - norm[62] = 260233280; - norm[63] = 266794768; - norm[64] = 273357248; - norm[65] = 279916768; - norm[66] = 286469440; - norm[67] = 293011360; - norm[68] = 299538560; - norm[69] = 306047168; - norm[70] = 312533312; - norm[71] = 318993088; - norm[72] = 325422656; - norm[73] = 331818144; - norm[74] = 338175744; - norm[75] = 344491680; - norm[76] = 350762176; - norm[77] = 356983424; - norm[78] = 363151808; - norm[79] = 369263520; - norm[80] = 375315008; - norm[81] = 381302592; - norm[82] = 387222720; - norm[83] = 393071872; - norm[84] = 398846528; - norm[85] = 404543232; - norm[86] = 410158560; - norm[87] = 415689216; - norm[88] = 421131840; - norm[89] = 426483200; - norm[90] = 431740096; - norm[91] = 436899392; - norm[92] = 441958016; - norm[93] = 446912928; - norm[94] = 451761152; - norm[95] = 456499840; - norm[96] = 461126080; - norm[97] = 465637152; - norm[98] = 470030400; - norm[99] = 474303104; - norm[100] = 478452800; - norm[101] = 482476960; - norm[102] = 486373184; - norm[103] = 490139200; - norm[104] = 493772640; - norm[105] = 497271424; - norm[106] = 500633440; - norm[107] = 503856704; - norm[108] = 506939200; - norm[109] = 509879168; - norm[110] = 512674880; - norm[111] = 515324544; - norm[112] = 517826688; - norm[113] = 520179776; - norm[114] = 522382368; - norm[115] = 524433184; - norm[116] = 526331008; - norm[117] = 528074688; - norm[118] = 529663200; - norm[119] = 531095552; - norm[120] = 532370944; - norm[121] = 533488576; - norm[122] = 534447808; - norm[123] = 535248000; - norm[124] = 535888768; - norm[125] = 536369664; - norm[126] = 536690432; - norm[127] = 536850880; - norm[128] = 536850880; - norm[129] = 536690432; - norm[130] = 536369664; - norm[131] = 535888768; - norm[132] = 535248000; - norm[133] = 534447808; - norm[134] = 533488576; - norm[135] = 532370944; - norm[136] = 531095552; - norm[137] = 529663200; - norm[138] = 528074688; - norm[139] = 526331008; - norm[140] = 524433216; - norm[141] = 522382368; - norm[142] = 520179776; - norm[143] = 517826688; - norm[144] = 515324544; - norm[145] = 512674880; - norm[146] = 509879168; - norm[147] = 506939200; - norm[148] = 503856704; - norm[149] = 500633472; - norm[150] = 497271424; - norm[151] = 493772672; - norm[152] = 490139200; - norm[153] = 486373184; - norm[154] = 482476992; - norm[155] = 478452800; - norm[156] = 474303104; - norm[157] = 470030400; - norm[158] = 465637184; - norm[159] = 461126080; - norm[160] = 456499840; - norm[161] = 451761152; - norm[162] = 446912960; - norm[163] = 441958016; - norm[164] = 436899424; - norm[165] = 431740096; - norm[166] = 426483200; - norm[167] = 421131840; - norm[168] = 415689216; - norm[169] = 410158560; - norm[170] = 404543232; - norm[171] = 398846528; - norm[172] = 393071872; - norm[173] = 387222720; - norm[174] = 381302592; - norm[175] = 375315008; - norm[176] = 369263552; - norm[177] = 363151808; - norm[178] = 356983456; - norm[179] = 350762176; - norm[180] = 344491712; - norm[181] = 338175776; - norm[182] = 331818144; - norm[183] = 325422656; - norm[184] = 318993088; - norm[185] = 312533312; - norm[186] = 306047168; - norm[187] = 299538560; - norm[188] = 293011360; - norm[189] = 286469472; - norm[190] = 279916800; - norm[191] = 273357248; - norm[192] = 266794784; - norm[193] = 260233280; - norm[194] = 253676688; - norm[195] = 247128928; - norm[196] = 240593888; - norm[197] = 234075488; - norm[198] = 227577632; - norm[199] = 221104192; - norm[200] = 214659040; - norm[201] = 208246032; - norm[202] = 201868992; - norm[203] = 195531744; - norm[204] = 189238080; - norm[205] = 182991728; - norm[206] = 176796448; - norm[207] = 170655952; - norm[208] = 164573888; - norm[209] = 158553920; - norm[210] = 152599600; - norm[211] = 146714528; - norm[212] = 140902208; - norm[213] = 135166096; - norm[214] = 129509648; - norm[215] = 123936240; - norm[216] = 118449184; - norm[217] = 113051776; - norm[218] = 107747248; - norm[219] = 102538752; - norm[220] = 97429424; - norm[221] = 92422288; - norm[222] = 87520352; - norm[223] = 82726544; - norm[224] = 78043744; - norm[225] = 73474736; - norm[226] = 69022240; - norm[227] = 64688944; - norm[228] = 60477424; - norm[229] = 56390192; - norm[230] = 52429696; - norm[231] = 48598304; - norm[232] = 44898304; - norm[233] = 41331904; - norm[234] = 37901248; - norm[235] = 34608384; - norm[236] = 31455264; - norm[237] = 28443792; - norm[238] = 25575744; - norm[239] = 22852864; - norm[240] = 20276752; - norm[241] = 17848976; - norm[242] = 15570960; - norm[243] = 13444080; - norm[244] = 11469616; - norm[245] = 9648720; - norm[246] = 7982512; - norm[247] = 6471952; - norm[248] = 5117984; - norm[249] = 3921376; - norm[250] = 2882880; - norm[251] = 2003104; - norm[252] = 1282560; - norm[253] = 721696; - norm[254] = 320832; - norm[255] = 80224; - hann[0] = 0; - hann[1] = 0; - hann[2] = 1; - hann[3] = 2; - hann[4] = 3; - hann[5] = 5; - hann[6] = 7; - hann[7] = 9; - hann[8] = 12; - hann[9] = 15; - hann[10] = 18; - hann[11] = 21; - hann[12] = 25; - hann[13] = 29; - hann[14] = 34; - hann[15] = 38; - hann[16] = 43; - hann[17] = 48; - hann[18] = 54; - hann[19] = 59; - hann[20] = 66; - hann[21] = 72; - hann[22] = 78; - hann[23] = 85; - hann[24] = 92; - hann[25] = 100; - hann[26] = 107; - hann[27] = 115; - hann[28] = 123; - hann[29] = 131; - hann[30] = 140; - hann[31] = 148; - hann[32] = 157; - hann[33] = 166; - hann[34] = 176; - hann[35] = 185; - hann[36] = 195; - hann[37] = 205; - hann[38] = 215; - hann[39] = 225; - hann[40] = 236; - hann[41] = 247; - hann[42] = 257; - hann[43] = 268; - hann[44] = 279; - hann[45] = 291; - hann[46] = 302; - hann[47] = 313; - hann[48] = 325; - hann[49] = 337; - hann[50] = 349; - hann[51] = 360; - hann[52] = 372; - hann[53] = 385; - hann[54] = 397; - hann[55] = 409; - hann[56] = 421; - hann[57] = 434; - hann[58] = 446; - hann[59] = 458; - hann[60] = 471; - hann[61] = 483; - hann[62] = 496; - hann[63] = 508; - hann[64] = 521; - hann[65] = 533; - hann[66] = 546; - hann[67] = 558; - hann[68] = 571; - hann[69] = 583; - hann[70] = 596; - hann[71] = 608; - hann[72] = 620; - hann[73] = 632; - hann[74] = 645; - hann[75] = 657; - hann[76] = 669; - hann[77] = 680; - hann[78] = 692; - hann[79] = 704; - hann[80] = 715; - hann[81] = 727; - hann[82] = 738; - hann[83] = 749; - hann[84] = 760; - hann[85] = 771; - hann[86] = 782; - hann[87] = 792; - hann[88] = 803; - hann[89] = 813; - hann[90] = 823; - hann[91] = 833; - hann[92] = 842; - hann[93] = 852; - hann[94] = 861; - hann[95] = 870; - hann[96] = 879; - hann[97] = 888; - hann[98] = 896; - hann[99] = 904; - hann[100] = 912; - hann[101] = 920; - hann[102] = 927; - hann[103] = 934; - hann[104] = 941; - hann[105] = 948; - hann[106] = 954; - hann[107] = 961; - hann[108] = 966; - hann[109] = 972; - hann[110] = 977; - hann[111] = 982; - hann[112] = 987; - hann[113] = 992; - hann[114] = 996; - hann[115] = 1000; - hann[116] = 1003; - hann[117] = 1007; - hann[118] = 1010; - hann[119] = 1012; - hann[120] = 1015; - hann[121] = 1017; - hann[122] = 1019; - hann[123] = 1020; - hann[124] = 1022; - hann[125] = 1023; - hann[126] = 1023; - hann[127] = 1023; - hann[128] = 1023; - hann[129] = 1023; - hann[130] = 1023; - hann[131] = 1022; - hann[132] = 1020; - hann[133] = 1019; - hann[134] = 1017; - hann[135] = 1015; - hann[136] = 1012; - hann[137] = 1010; - hann[138] = 1007; - hann[139] = 1003; - hann[140] = 1000; - hann[141] = 996; - hann[142] = 992; - hann[143] = 987; - hann[144] = 982; - hann[145] = 977; - hann[146] = 972; - hann[147] = 966; - hann[148] = 961; - hann[149] = 954; - hann[150] = 948; - hann[151] = 941; - hann[152] = 934; - hann[153] = 927; - hann[154] = 920; - hann[155] = 912; - hann[156] = 904; - hann[157] = 896; - hann[158] = 888; - hann[159] = 879; - hann[160] = 870; - hann[161] = 861; - hann[162] = 852; - hann[163] = 842; - hann[164] = 833; - hann[165] = 823; - hann[166] = 813; - hann[167] = 803; - hann[168] = 792; - hann[169] = 782; - hann[170] = 771; - hann[171] = 760; - hann[172] = 749; - hann[173] = 738; - hann[174] = 727; - hann[175] = 715; - hann[176] = 704; - hann[177] = 692; - hann[178] = 680; - hann[179] = 669; - hann[180] = 657; - hann[181] = 645; - hann[182] = 632; - hann[183] = 620; - hann[184] = 608; - hann[185] = 596; - hann[186] = 583; - hann[187] = 571; - hann[188] = 558; - hann[189] = 546; - hann[190] = 533; - hann[191] = 521; - hann[192] = 508; - hann[193] = 496; - hann[194] = 483; - hann[195] = 471; - hann[196] = 458; - hann[197] = 446; - hann[198] = 434; - hann[199] = 421; - hann[200] = 409; - hann[201] = 397; - hann[202] = 385; - hann[203] = 372; - hann[204] = 360; - hann[205] = 349; - hann[206] = 337; - hann[207] = 325; - hann[208] = 313; - hann[209] = 302; - hann[210] = 291; - hann[211] = 279; - hann[212] = 268; - hann[213] = 257; - hann[214] = 247; - hann[215] = 236; - hann[216] = 225; - hann[217] = 215; - hann[218] = 205; - hann[219] = 195; - hann[220] = 185; - hann[221] = 176; - hann[222] = 166; - hann[223] = 157; - hann[224] = 148; - hann[225] = 140; - hann[226] = 131; - hann[227] = 123; - hann[228] = 115; - hann[229] = 107; - hann[230] = 100; - hann[231] = 92; - hann[232] = 85; - hann[233] = 78; - hann[234] = 72; - hann[235] = 66; - hann[236] = 59; - hann[237] = 54; - hann[238] = 48; - hann[239] = 43; - hann[240] = 38; - hann[241] = 34; - hann[242] = 29; - hann[243] = 25; - hann[244] = 21; - hann[245] = 18; - hann[246] = 15; - hann[247] = 12; - hann[248] = 9; - hann[249] = 7; - hann[250] = 5; - hann[251] = 3; - hann[252] = 2; - hann[253] = 1; - hann[254] = 0; - hann[255] = 0; - -} /* gen_hann2 */ - -/** - * Creates the non uniform enhancement window (bilinearly mapped hannning window) - * in order to reduce the formant enhancement in the high spectrum - * @param mm : memory manager - * @param sig_inObj : sig PU internal object of the sub-object - * @return void - * @callgraph - * @callergraph - * @remarks the outgput is based on the matlab script below\n - matlab script - ------------- - function makeEnhWind(alpha) - N=129; % =HFFTSIZEE_P1 - s=(bilinmap(alpha,N)); - h=[hann(N)']; - x=(1:N)/N; - W=interp1(x,h,s); W(1)=0; - - fid=fopen('enhwind.txt','wt'); - fprintf(fid,'picoos_int16 enh_wind_init(sig_innerobj_t *sig_inObj) {\n'); - for i=1:N, - fprintf(fid,[' sig_inObj->enhwind[' int2str(i) '] = (picoos_single)' num2str(W(i),'%0.7g') ';\n']); - end; - fprintf(fid,' return PICO_OK;\n'); - fprintf(fid,' }; \n'); - fclose(fid); - %figure(1); plot(x*8,W); - */ -static void enh_wind_init(sig_innerobj_t *sig_inObj) -{ - /* picoos_int16 i; */ - picoos_int32 *c; - - c = sig_inObj->cos_table; - - c[0] = 4096; - c[1] = 4095; - c[2] = 4095; - c[3] = 4095; - c[4] = 4095; - c[5] = 4095; - c[6] = 4095; - c[7] = 4095; - c[8] = 4094; - c[9] = 4094; - c[10] = 4094; - c[11] = 4093; - c[12] = 4093; - c[13] = 4092; - c[14] = 4092; - c[15] = 4091; - c[16] = 4091; - c[17] = 4090; - c[18] = 4089; - c[19] = 4089; - c[20] = 4088; - c[21] = 4087; - c[22] = 4086; - c[23] = 4085; - c[24] = 4084; - c[25] = 4083; - c[26] = 4082; - c[27] = 4081; - c[28] = 4080; - c[29] = 4079; - c[30] = 4078; - c[31] = 4077; - c[32] = 4076; - c[33] = 4075; - c[34] = 4073; - c[35] = 4072; - c[36] = 4071; - c[37] = 4069; - c[38] = 4068; - c[39] = 4066; - c[40] = 4065; - c[41] = 4063; - c[42] = 4062; - c[43] = 4060; - c[44] = 4058; - c[45] = 4057; - c[46] = 4055; - c[47] = 4053; - c[48] = 4051; - c[49] = 4049; - c[50] = 4047; - c[51] = 4045; - c[52] = 4043; - c[53] = 4041; - c[54] = 4039; - c[55] = 4037; - c[56] = 4035; - c[57] = 4033; - c[58] = 4031; - c[59] = 4029; - c[60] = 4026; - c[61] = 4024; - c[62] = 4022; - c[63] = 4019; - c[64] = 4017; - c[65] = 4014; - c[66] = 4012; - c[67] = 4009; - c[68] = 4007; - c[69] = 4004; - c[70] = 4001; - c[71] = 3999; - c[72] = 3996; - c[73] = 3993; - c[74] = 3990; - c[75] = 3988; - c[76] = 3985; - c[77] = 3982; - c[78] = 3979; - c[79] = 3976; - c[80] = 3973; - c[81] = 3970; - c[82] = 3967; - c[83] = 3963; - c[84] = 3960; - c[85] = 3957; - c[86] = 3954; - c[87] = 3950; - c[88] = 3947; - c[89] = 3944; - c[90] = 3940; - c[91] = 3937; - c[92] = 3933; - c[93] = 3930; - c[94] = 3926; - c[95] = 3923; - c[96] = 3919; - c[97] = 3915; - c[98] = 3912; - c[99] = 3908; - c[100] = 3904; - c[101] = 3900; - c[102] = 3897; - c[103] = 3893; - c[104] = 3889; - c[105] = 3885; - c[106] = 3881; - c[107] = 3877; - c[108] = 3873; - c[109] = 3869; - c[110] = 3864; - c[111] = 3860; - c[112] = 3856; - c[113] = 3852; - c[114] = 3848; - c[115] = 3843; - c[116] = 3839; - c[117] = 3834; - c[118] = 3830; - c[119] = 3826; - c[120] = 3821; - c[121] = 3816; - c[122] = 3812; - c[123] = 3807; - c[124] = 3803; - c[125] = 3798; - c[126] = 3793; - c[127] = 3789; - c[128] = 3784; - c[129] = 3779; - c[130] = 3774; - c[131] = 3769; - c[132] = 3764; - c[133] = 3759; - c[134] = 3754; - c[135] = 3749; - c[136] = 3744; - c[137] = 3739; - c[138] = 3734; - c[139] = 3729; - c[140] = 3723; - c[141] = 3718; - c[142] = 3713; - c[143] = 3708; - c[144] = 3702; - c[145] = 3697; - c[146] = 3691; - c[147] = 3686; - c[148] = 3680; - c[149] = 3675; - c[150] = 3669; - c[151] = 3664; - c[152] = 3658; - c[153] = 3652; - c[154] = 3647; - c[155] = 3641; - c[156] = 3635; - c[157] = 3629; - c[158] = 3624; - c[159] = 3618; - c[160] = 3612; - c[161] = 3606; - c[162] = 3600; - c[163] = 3594; - c[164] = 3588; - c[165] = 3582; - c[166] = 3576; - c[167] = 3570; - c[168] = 3563; - c[169] = 3557; - c[170] = 3551; - c[171] = 3545; - c[172] = 3538; - c[173] = 3532; - c[174] = 3526; - c[175] = 3519; - c[176] = 3513; - c[177] = 3506; - c[178] = 3500; - c[179] = 3493; - c[180] = 3487; - c[181] = 3480; - c[182] = 3473; - c[183] = 3467; - c[184] = 3460; - c[185] = 3453; - c[186] = 3447; - c[187] = 3440; - c[188] = 3433; - c[189] = 3426; - c[190] = 3419; - c[191] = 3412; - c[192] = 3405; - c[193] = 3398; - c[194] = 3391; - c[195] = 3384; - c[196] = 3377; - c[197] = 3370; - c[198] = 3363; - c[199] = 3356; - c[200] = 3348; - c[201] = 3341; - c[202] = 3334; - c[203] = 3326; - c[204] = 3319; - c[205] = 3312; - c[206] = 3304; - c[207] = 3297; - c[208] = 3289; - c[209] = 3282; - c[210] = 3274; - c[211] = 3267; - c[212] = 3259; - c[213] = 3252; - c[214] = 3244; - c[215] = 3236; - c[216] = 3229; - c[217] = 3221; - c[218] = 3213; - c[219] = 3205; - c[220] = 3197; - c[221] = 3190; - c[222] = 3182; - c[223] = 3174; - c[224] = 3166; - c[225] = 3158; - c[226] = 3150; - c[227] = 3142; - c[228] = 3134; - c[229] = 3126; - c[230] = 3117; - c[231] = 3109; - c[232] = 3101; - c[233] = 3093; - c[234] = 3085; - c[235] = 3076; - c[236] = 3068; - c[237] = 3060; - c[238] = 3051; - c[239] = 3043; - c[240] = 3034; - c[241] = 3026; - c[242] = 3018; - c[243] = 3009; - c[244] = 3000; - c[245] = 2992; - c[246] = 2983; - c[247] = 2975; - c[248] = 2966; - c[249] = 2957; - c[250] = 2949; - c[251] = 2940; - c[252] = 2931; - c[253] = 2922; - c[254] = 2914; - c[255] = 2905; - c[256] = 2896; - c[257] = 2887; - c[258] = 2878; - c[259] = 2869; - c[260] = 2860; - c[261] = 2851; - c[262] = 2842; - c[263] = 2833; - c[264] = 2824; - c[265] = 2815; - c[266] = 2806; - c[267] = 2796; - c[268] = 2787; - c[269] = 2778; - c[270] = 2769; - c[271] = 2760; - c[272] = 2750; - c[273] = 2741; - c[274] = 2732; - c[275] = 2722; - c[276] = 2713; - c[277] = 2703; - c[278] = 2694; - c[279] = 2684; - c[280] = 2675; - c[281] = 2665; - c[282] = 2656; - c[283] = 2646; - c[284] = 2637; - c[285] = 2627; - c[286] = 2617; - c[287] = 2608; - c[288] = 2598; - c[289] = 2588; - c[290] = 2578; - c[291] = 2569; - c[292] = 2559; - c[293] = 2549; - c[294] = 2539; - c[295] = 2529; - c[296] = 2519; - c[297] = 2510; - c[298] = 2500; - c[299] = 2490; - c[300] = 2480; - c[301] = 2470; - c[302] = 2460; - c[303] = 2450; - c[304] = 2439; - c[305] = 2429; - c[306] = 2419; - c[307] = 2409; - c[308] = 2399; - c[309] = 2389; - c[310] = 2379; - c[311] = 2368; - c[312] = 2358; - c[313] = 2348; - c[314] = 2337; - c[315] = 2327; - c[316] = 2317; - c[317] = 2306; - c[318] = 2296; - c[319] = 2286; - c[320] = 2275; - c[321] = 2265; - c[322] = 2254; - c[323] = 2244; - c[324] = 2233; - c[325] = 2223; - c[326] = 2212; - c[327] = 2201; - c[328] = 2191; - c[329] = 2180; - c[330] = 2170; - c[331] = 2159; - c[332] = 2148; - c[333] = 2138; - c[334] = 2127; - c[335] = 2116; - c[336] = 2105; - c[337] = 2094; - c[338] = 2084; - c[339] = 2073; - c[340] = 2062; - c[341] = 2051; - c[342] = 2040; - c[343] = 2029; - c[344] = 2018; - c[345] = 2007; - c[346] = 1997; - c[347] = 1986; - c[348] = 1975; - c[349] = 1964; - c[350] = 1952; - c[351] = 1941; - c[352] = 1930; - c[353] = 1919; - c[354] = 1908; - c[355] = 1897; - c[356] = 1886; - c[357] = 1875; - c[358] = 1864; - c[359] = 1852; - c[360] = 1841; - c[361] = 1830; - c[362] = 1819; - c[363] = 1807; - c[364] = 1796; - c[365] = 1785; - c[366] = 1773; - c[367] = 1762; - c[368] = 1751; - c[369] = 1739; - c[370] = 1728; - c[371] = 1717; - c[372] = 1705; - c[373] = 1694; - c[374] = 1682; - c[375] = 1671; - c[376] = 1659; - c[377] = 1648; - c[378] = 1636; - c[379] = 1625; - c[380] = 1613; - c[381] = 1602; - c[382] = 1590; - c[383] = 1579; - c[384] = 1567; - c[385] = 1555; - c[386] = 1544; - c[387] = 1532; - c[388] = 1520; - c[389] = 1509; - c[390] = 1497; - c[391] = 1485; - c[392] = 1474; - c[393] = 1462; - c[394] = 1450; - c[395] = 1438; - c[396] = 1427; - c[397] = 1415; - c[398] = 1403; - c[399] = 1391; - c[400] = 1379; - c[401] = 1368; - c[402] = 1356; - c[403] = 1344; - c[404] = 1332; - c[405] = 1320; - c[406] = 1308; - c[407] = 1296; - c[408] = 1284; - c[409] = 1272; - c[410] = 1260; - c[411] = 1248; - c[412] = 1237; - c[413] = 1225; - c[414] = 1213; - c[415] = 1201; - c[416] = 1189; - c[417] = 1176; - c[418] = 1164; - c[419] = 1152; - c[420] = 1140; - c[421] = 1128; - c[422] = 1116; - c[423] = 1104; - c[424] = 1092; - c[425] = 1080; - c[426] = 1068; - c[427] = 1056; - c[428] = 1043; - c[429] = 1031; - c[430] = 1019; - c[431] = 1007; - c[432] = 995; - c[433] = 983; - c[434] = 970; - c[435] = 958; - c[436] = 946; - c[437] = 934; - c[438] = 921; - c[439] = 909; - c[440] = 897; - c[441] = 885; - c[442] = 872; - c[443] = 860; - c[444] = 848; - c[445] = 836; - c[446] = 823; - c[447] = 811; - c[448] = 799; - c[449] = 786; - c[450] = 774; - c[451] = 762; - c[452] = 749; - c[453] = 737; - c[454] = 725; - c[455] = 712; - c[456] = 700; - c[457] = 687; - c[458] = 675; - c[459] = 663; - c[460] = 650; - c[461] = 638; - c[462] = 625; - c[463] = 613; - c[464] = 601; - c[465] = 588; - c[466] = 576; - c[467] = 563; - c[468] = 551; - c[469] = 538; - c[470] = 526; - c[471] = 513; - c[472] = 501; - c[473] = 488; - c[474] = 476; - c[475] = 463; - c[476] = 451; - c[477] = 438; - c[478] = 426; - c[479] = 413; - c[480] = 401; - c[481] = 388; - c[482] = 376; - c[483] = 363; - c[484] = 351; - c[485] = 338; - c[486] = 326; - c[487] = 313; - c[488] = 301; - c[489] = 288; - c[490] = 276; - c[491] = 263; - c[492] = 251; - c[493] = 238; - c[494] = 226; - c[495] = 213; - c[496] = 200; - c[497] = 188; - c[498] = 175; - c[499] = 163; - c[500] = 150; - c[501] = 138; - c[502] = 125; - c[503] = 113; - c[504] = 100; - c[505] = 87; - c[506] = 75; - c[507] = 62; - c[508] = 50; - c[509] = 37; - c[510] = 25; - c[511] = 12; - c[512] = 0; -} /*enh_wind_init*/ - -/** - * Initializes a useful large array of random numbers - * @param sig_inObj : sig PU internal object of the sub-object - * @return void - * @callgraph - * @callergraph - */ -static void init_rand(sig_innerobj_t *sig_inObj) -{ - picoos_int32 *q = sig_inObj->int_vec34; - picoos_int32 *r = sig_inObj->int_vec35; - - sig_inObj->iRand = 0; - - q[0] = -2198; - r[0] = 3455; - q[1] = 3226; - r[1] = -2522; - q[2] = -845; - r[2] = 4007; - q[3] = -1227; - r[3] = 3907; - q[4] = -3480; - r[4] = 2158; - q[5] = -1325; - r[5] = -3875; - q[6] = 2089; - r[6] = -3522; - q[7] = -468; - r[7] = 4069; - q[8] = 711; - r[8] = -4033; - q[9] = 3862; - r[9] = 1362; - q[10] = 4054; - r[10] = -579; - q[11] = 2825; - r[11] = 2965; - q[12] = 2704; - r[12] = -3076; - q[13] = 4081; - r[13] = 344; - q[14] = -3912; - r[14] = 1211; - q[15] = -3541; - r[15] = 2058; - q[16] = 2694; - r[16] = 3084; - q[17] = 835; - r[17] = 4009; - q[18] = -2578; - r[18] = -3182; - q[19] = 3205; - r[19] = 2550; - q[20] = -4074; - r[20] = -418; - q[21] = -183; - r[21] = -4091; - q[22] = -2665; - r[22] = -3110; - q[23] = -1367; - r[23] = 3860; - q[24] = -2266; - r[24] = -3411; - q[25] = 3327; - r[25] = -2387; - q[26] = -2807; - r[26] = -2982; - q[27] = -3175; - r[27] = -2587; - q[28] = -4095; - r[28] = 27; - q[29] = -811; - r[29] = -4014; - q[30] = 4082; - r[30] = 332; - q[31] = -2175; - r[31] = 3470; - q[32] = 3112; - r[32] = 2662; - q[33] = 1168; - r[33] = -3925; - q[34] = 2659; - r[34] = 3115; - q[35] = 4048; - r[35] = 622; - q[36] = 4092; - r[36] = -165; - q[37] = -4036; - r[37] = 697; - q[38] = 1081; - r[38] = -3950; - q[39] = -548; - r[39] = 4059; - q[40] = 4038; - r[40] = 685; - q[41] = -511; - r[41] = 4063; - q[42] = 3317; - r[42] = -2402; - q[43] = -3180; - r[43] = 2580; - q[44] = 851; - r[44] = -4006; - q[45] = 2458; - r[45] = -3276; - q[46] = -1453; - r[46] = 3829; - q[47] = -3577; - r[47] = 1995; - q[48] = -3708; - r[48] = -1738; - q[49] = -3890; - r[49] = 1282; - q[50] = 4041; - r[50] = 666; - q[51] = -3511; - r[51] = -2108; - q[52] = -1454; - r[52] = -3828; - q[53] = 2124; - r[53] = 3502; - q[54] = -3159; - r[54] = 2606; - q[55] = 2384; - r[55] = -3330; - q[56] = -3767; - r[56] = -1607; - q[57] = -4063; - r[57] = -513; - q[58] = 3952; - r[58] = -1075; - q[59] = -3778; - r[59] = -1581; - q[60] = -301; - r[60] = -4084; - q[61] = -4026; - r[61] = 751; - q[62] = -3346; - r[62] = 2361; - q[63] = -2426; - r[63] = 3299; - q[64] = 428; - r[64] = -4073; - q[65] = 3968; - r[65] = 1012; - q[66] = 2900; - r[66] = -2892; - q[67] = -263; - r[67] = 4087; - q[68] = 4083; - r[68] = 322; - q[69] = 2024; - r[69] = 3560; - q[70] = 4015; - r[70] = 808; - q[71] = -3971; - r[71] = -1000; - q[72] = 3785; - r[72] = -1564; - q[73] = -3726; - r[73] = 1701; - q[74] = -3714; - r[74] = 1725; - q[75] = 743; - r[75] = 4027; - q[76] = 875; - r[76] = -4001; - q[77] = 294; - r[77] = 4085; - q[78] = 2611; - r[78] = 3155; - q[79] = 2491; - r[79] = -3251; - q[80] = 1558; - r[80] = 3787; - q[81] = -2063; - r[81] = -3538; - q[82] = 3809; - r[82] = -1505; - q[83] = -2987; - r[83] = 2802; - q[84] = -1955; - r[84] = 3599; - q[85] = 1980; - r[85] = -3585; - q[86] = -539; - r[86] = -4060; - q[87] = -3210; - r[87] = 2543; - q[88] = 2415; - r[88] = -3308; - q[89] = 1587; - r[89] = 3775; - q[90] = -3943; - r[90] = 1106; - q[91] = 3476; - r[91] = 2165; - q[92] = 2253; - r[92] = 3420; - q[93] = -2584; - r[93] = 3177; - q[94] = 3804; - r[94] = -1518; - q[95] = -3637; - r[95] = 1883; - q[96] = 3289; - r[96] = -2440; - q[97] = -1621; - r[97] = 3761; - q[98] = 1645; - r[98] = 3751; - q[99] = -3471; - r[99] = 2173; - q[100] = 4071; - r[100] = -449; - q[101] = -872; - r[101] = -4001; - q[102] = -3897; - r[102] = 1259; - q[103] = -3590; - r[103] = 1970; - q[104] = -2456; - r[104] = -3277; - q[105] = -3004; - r[105] = 2783; - q[106] = 2589; - r[106] = 3173; - q[107] = 3727; - r[107] = -1698; - q[108] = 2992; - r[108] = 2796; - q[109] = 794; - r[109] = -4018; - q[110] = -918; - r[110] = 3991; - q[111] = 1446; - r[111] = -3831; - q[112] = 3871; - r[112] = -1338; - q[113] = -612; - r[113] = -4049; - q[114] = -1566; - r[114] = -3784; - q[115] = 672; - r[115] = -4040; - q[116] = 3841; - r[116] = 1422; - q[117] = 3545; - r[117] = -2051; - q[118] = -1982; - r[118] = -3584; - q[119] = -3413; - r[119] = 2263; - q[120] = -3265; - r[120] = -2473; - q[121] = -2876; - r[121] = -2915; - q[122] = 4094; - r[122] = -117; - q[123] = -269; - r[123] = 4087; - q[124] = -4077; - r[124] = 391; - q[125] = -3759; - r[125] = 1626; - q[126] = 1639; - r[126] = 3753; - q[127] = 3041; - r[127] = -2743; - q[128] = 5; - r[128] = 4095; - q[129] = 2778; - r[129] = -3009; - q[130] = 1121; - r[130] = -3939; - q[131] = -455; - r[131] = -4070; - q[132] = 3532; - r[132] = 2073; - q[133] = -143; - r[133] = -4093; - q[134] = -2357; - r[134] = -3349; - q[135] = 458; - r[135] = 4070; - q[136] = -2887; - r[136] = -2904; - q[137] = -1104; - r[137] = 3944; - q[138] = -2104; - r[138] = -3513; - q[139] = 126; - r[139] = 4094; - q[140] = -3655; - r[140] = -1848; - q[141] = -3896; - r[141] = 1263; - q[142] = -3874; - r[142] = -1327; - q[143] = 4058; - r[143] = 553; - q[144] = -1831; - r[144] = -3663; - q[145] = -255; - r[145] = -4088; - q[146] = -1211; - r[146] = 3912; - q[147] = 445; - r[147] = 4071; - q[148] = 2268; - r[148] = 3410; - q[149] = -4010; - r[149] = 833; - q[150] = 2621; - r[150] = 3147; - q[151] = -250; - r[151] = 4088; - q[152] = -3409; - r[152] = -2269; - q[153] = -2710; - r[153] = -3070; - q[154] = 4063; - r[154] = 518; - q[155] = -3611; - r[155] = -1933; - q[156] = -3707; - r[156] = -1741; - q[157] = -1151; - r[157] = -3930; - q[158] = 3976; - r[158] = -983; - q[159] = -1736; - r[159] = 3709; - q[160] = 3669; - r[160] = 1820; - q[161] = -143; - r[161] = 4093; - q[162] = -3879; - r[162] = -1313; - q[163] = -2242; - r[163] = -3427; - q[164] = -4095; - r[164] = 0; - q[165] = -1159; - r[165] = -3928; - q[166] = -3155; - r[166] = 2611; - q[167] = -2887; - r[167] = -2904; - q[168] = -4095; - r[168] = 56; - q[169] = -3861; - r[169] = -1364; - q[170] = -2814; - r[170] = 2976; - q[171] = -3680; - r[171] = -1798; - q[172] = -4094; - r[172] = -107; - q[173] = -3626; - r[173] = 1903; - q[174] = 3403; - r[174] = 2278; - q[175] = -1735; - r[175] = -3710; - q[176] = -2126; - r[176] = -3500; - q[177] = 3183; - r[177] = -2577; - q[178] = -3499; - r[178] = 2128; - q[179] = -1736; - r[179] = 3709; - q[180] = 2592; - r[180] = -3170; - q[181] = 3875; - r[181] = 1326; - q[182] = 3596; - r[182] = 1960; - q[183] = 3915; - r[183] = -1202; - q[184] = 1570; - r[184] = 3783; - q[185] = -3319; - r[185] = -2400; - q[186] = 4019; - r[186] = 787; - q[187] = -187; - r[187] = 4091; - q[188] = 1370; - r[188] = -3859; - q[189] = -4091; - r[189] = 199; - q[190] = 3626; - r[190] = 1904; - q[191] = -2943; - r[191] = 2848; - q[192] = 56; - r[192] = 4095; - q[193] = 2824; - r[193] = 2966; - q[194] = -3994; - r[194] = -904; - q[195] = 56; - r[195] = 4095; - q[196] = -2045; - r[196] = 3548; - q[197] = -3653; - r[197] = 1850; - q[198] = -2864; - r[198] = 2927; - q[199] = -1996; - r[199] = 3576; - q[200] = -4061; - r[200] = 527; - q[201] = 159; - r[201] = 4092; - q[202] = -3363; - r[202] = 2336; - q[203] = -4074; - r[203] = 421; - q[204] = 2043; - r[204] = 3549; - q[205] = 4095; - r[205] = -70; - q[206] = -2107; - r[206] = -3512; - q[207] = -1973; - r[207] = 3589; - q[208] = -3138; - r[208] = 2631; - q[209] = -3625; - r[209] = -1905; - q[210] = 2413; - r[210] = 3309; - q[211] = -50; - r[211] = -4095; - q[212] = 2813; - r[212] = 2976; - q[213] = -535; - r[213] = -4060; - q[214] = 1250; - r[214] = 3900; - q[215] = 1670; - r[215] = -3739; - q[216] = 1945; - r[216] = -3604; - q[217] = -476; - r[217] = -4068; - q[218] = -3659; - r[218] = -1840; - q[219] = 2745; - r[219] = 3039; - q[220] = -674; - r[220] = -4040; - q[221] = 2383; - r[221] = 3330; - q[222] = 4086; - r[222] = 274; - q[223] = -4030; - r[223] = 730; - q[224] = 768; - r[224] = -4023; - q[225] = 3925; - r[225] = 1170; - q[226] = 785; - r[226] = 4019; - q[227] = -3101; - r[227] = -2675; - q[228] = 4030; - r[228] = -729; - q[229] = 3422; - r[229] = 2249; - q[230] = -3847; - r[230] = 1403; - q[231] = 3902; - r[231] = -1243; - q[232] = 2114; - r[232] = -3507; - q[233] = -2359; - r[233] = 3348; - q[234] = 3754; - r[234] = -1638; - q[235] = -4095; - r[235] = -83; - q[236] = 2301; - r[236] = -3388; - q[237] = 3336; - r[237] = 2375; - q[238] = -2045; - r[238] = 3548; - q[239] = -413; - r[239] = -4075; - q[240] = 1848; - r[240] = 3655; - q[241] = 4072; - r[241] = -437; - q[242] = 4069; - r[242] = -463; - q[243] = 1386; - r[243] = -3854; - q[244] = 966; - r[244] = 3980; - q[245] = -1684; - r[245] = -3733; - q[246] = 2953; - r[246] = 2837; - q[247] = -3961; - r[247] = -1040; - q[248] = 3512; - r[248] = -2107; - q[249] = 1363; - r[249] = 3862; - q[250] = 1883; - r[250] = 3637; - q[251] = 2657; - r[251] = 3116; - q[252] = 2347; - r[252] = -3356; - q[253] = -1635; - r[253] = -3755; - q[254] = 3170; - r[254] = 2593; - q[255] = 2856; - r[255] = 2935; - q[256] = 494; - r[256] = 4066; - q[257] = 1936; - r[257] = -3609; - q[258] = 245; - r[258] = 4088; - q[259] = -1211; - r[259] = -3912; - q[260] = -3600; - r[260] = 1952; - q[261] = 1632; - r[261] = 3756; - q[262] = 2341; - r[262] = 3360; - q[263] = 186; - r[263] = -4091; - q[264] = 4011; - r[264] = 829; - q[265] = -3490; - r[265] = -2143; - q[266] = 269; - r[266] = -4087; - q[267] = -2939; - r[267] = 2852; - q[268] = 1600; - r[268] = 3770; - q[269] = -3405; - r[269] = -2275; - q[270] = -3134; - r[270] = -2636; - q[271] = 2642; - r[271] = -3129; - q[272] = 3629; - r[272] = 1898; - q[273] = 3413; - r[273] = 2264; - q[274] = 2050; - r[274] = 3545; - q[275] = 988; - r[275] = -3975; - q[276] = -660; - r[276] = 4042; - q[277] = 978; - r[277] = -3977; - q[278] = 1965; - r[278] = -3593; - q[279] = -1513; - r[279] = -3806; - q[280] = -4076; - r[280] = 401; - q[281] = -4094; - r[281] = -92; - q[282] = -1914; - r[282] = 3621; - q[283] = 2006; - r[283] = -3570; - q[284] = -1550; - r[284] = -3791; - q[285] = 3774; - r[285] = -1591; - q[286] = -3958; - r[286] = 1052; - q[287] = -3576; - r[287] = 1997; - q[288] = -382; - r[288] = 4078; - q[289] = 1288; - r[289] = 3888; - q[290] = -2965; - r[290] = -2825; - q[291] = 1608; - r[291] = 3767; - q[292] = 3052; - r[292] = -2731; - q[293] = -622; - r[293] = 4048; - q[294] = -3836; - r[294] = 1434; - q[295] = -3542; - r[295] = 2056; - q[296] = -2648; - r[296] = 3124; - q[297] = -1178; - r[297] = -3922; - q[298] = -1109; - r[298] = 3942; - q[299] = 3910; - r[299] = 1217; - q[300] = 1199; - r[300] = -3916; - q[301] = -3386; - r[301] = 2303; - q[302] = -3453; - r[302] = 2202; - q[303] = -2877; - r[303] = 2914; - q[304] = 4095; - r[304] = -47; - q[305] = 3635; - r[305] = 1886; - q[306] = -2134; - r[306] = -3495; - q[307] = 613; - r[307] = -4049; - q[308] = -2700; - r[308] = 3079; - q[309] = 4091; - r[309] = -195; - q[310] = 3989; - r[310] = -927; - q[311] = -2385; - r[311] = 3329; - q[312] = 4094; - r[312] = -103; - q[313] = 1044; - r[313] = -3960; - q[314] = -1734; - r[314] = -3710; - q[315] = 1646; - r[315] = 3750; - q[316] = 575; - r[316] = 4055; - q[317] = -2629; - r[317] = -3140; - q[318] = 3266; - r[318] = 2471; - q[319] = 4091; - r[319] = -194; - q[320] = -2154; - r[320] = 3483; - q[321] = 659; - r[321] = 4042; - q[322] = -1785; - r[322] = -3686; - q[323] = -717; - r[323] = -4032; - q[324] = 4095; - r[324] = -37; - q[325] = -2963; - r[325] = -2827; - q[326] = -2645; - r[326] = -3126; - q[327] = 2619; - r[327] = -3148; - q[328] = 1855; - r[328] = -3651; - q[329] = -3726; - r[329] = 1699; - q[330] = -3437; - r[330] = 2227; - q[331] = 2948; - r[331] = 2842; - q[332] = -2125; - r[332] = 3501; - q[333] = -1700; - r[333] = 3726; - q[334] = 4094; - r[334] = -101; - q[335] = 2084; - r[335] = -3525; - q[336] = 3225; - r[336] = -2524; - q[337] = 2220; - r[337] = 3442; - q[338] = 3174; - r[338] = 2588; - q[339] = 229; - r[339] = -4089; - q[340] = -2381; - r[340] = -3332; - q[341] = -3677; - r[341] = -1803; - q[342] = -3191; - r[342] = -2567; - q[343] = 2465; - r[343] = 3270; - q[344] = 2681; - r[344] = -3096; - q[345] = 975; - r[345] = -3978; - q[346] = 2004; - r[346] = -3572; - q[347] = -3442; - r[347] = -2219; - q[348] = 3676; - r[348] = -1805; - q[349] = -3753; - r[349] = 1638; - q[350] = 3544; - r[350] = 2053; - q[351] = 397; - r[351] = -4076; - q[352] = 2221; - r[352] = 3440; - q[353] = -302; - r[353] = 4084; - q[354] = 4083; - r[354] = -323; - q[355] = -2253; - r[355] = -3420; - q[356] = -3038; - r[356] = 2746; - q[357] = 2884; - r[357] = 2908; - q[358] = 4070; - r[358] = 454; - q[359] = -1072; - r[359] = -3953; - q[360] = 3831; - r[360] = 1449; - q[361] = 3663; - r[361] = -1831; - q[362] = -1971; - r[362] = 3590; - q[363] = 3226; - r[363] = -2522; - q[364] = -145; - r[364] = -4093; - q[365] = 1882; - r[365] = -3637; - q[366] = 529; - r[366] = 4061; - q[367] = 2637; - r[367] = 3133; - q[368] = -4077; - r[368] = 389; - q[369] = 2156; - r[369] = -3482; - q[370] = -3276; - r[370] = 2458; - q[371] = -2687; - r[371] = -3090; - q[372] = 3469; - r[372] = -2177; - q[373] = -4093; - r[373] = -139; - q[374] = -850; - r[374] = 4006; - q[375] = -625; - r[375] = 4048; - q[376] = 1110; - r[376] = -3942; - q[377] = -3078; - r[377] = -2702; - q[378] = -2719; - r[378] = 3063; - q[379] = 742; - r[379] = 4028; - q[380] = -3902; - r[380] = -1245; - q[381] = 3888; - r[381] = -1287; - q[382] = -4081; - r[382] = 347; - q[383] = 1070; - r[383] = 3953; - q[384] = -996; - r[384] = -3972; - q[385] = 4041; - r[385] = -668; - q[386] = -2712; - r[386] = 3069; - q[387] = -3403; - r[387] = -2279; - q[388] = -3320; - r[388] = -2398; - q[389] = 3036; - r[389] = -2749; - q[390] = 1308; - r[390] = -3881; - q[391] = 2256; - r[391] = 3418; - q[392] = -1486; - r[392] = 3816; - q[393] = -2771; - r[393] = -3015; - q[394] = -3883; - r[394] = -1302; - q[395] = -3867; - r[395] = -1349; - q[396] = 3952; - r[396] = -1075; - q[397] = -789; - r[397] = 4019; - q[398] = 1458; - r[398] = 3827; - q[399] = 3832; - r[399] = -1446; - q[400] = -3001; - r[400] = -2787; - q[401] = 3463; - r[401] = 2186; - q[402] = 3606; - r[402] = 1942; - q[403] = 4023; - r[403] = 764; - q[404] = 3387; - r[404] = 2303; - q[405] = 2648; - r[405] = -3124; - q[406] = 1370; - r[406] = -3860; - q[407] = -3134; - r[407] = 2636; - q[408] = 4051; - r[408] = -600; - q[409] = -1977; - r[409] = -3587; - q[410] = 3160; - r[410] = 2605; - q[411] = 4042; - r[411] = 659; - q[412] = 3004; - r[412] = 2783; - q[413] = 3370; - r[413] = 2327; - q[414] = -419; - r[414] = -4074; - q[415] = -1968; - r[415] = 3591; - q[416] = -3705; - r[416] = -1746; - q[417] = -3331; - r[417] = -2383; - q[418] = -3634; - r[418] = 1888; - q[419] = -1981; - r[419] = -3584; - q[420] = 4069; - r[420] = -469; - q[421] = -628; - r[421] = -4047; - q[422] = -1900; - r[422] = 3628; - q[423] = 1039; - r[423] = -3961; - q[424] = 2554; - r[424] = -3201; - q[425] = -2955; - r[425] = 2836; - q[426] = 2286; - r[426] = -3398; - q[427] = -1624; - r[427] = 3760; - q[428] = 2213; - r[428] = 3446; - q[429] = -3989; - r[429] = -926; - q[430] = 192; - r[430] = -4091; - q[431] = -723; - r[431] = 4031; - q[432] = 2878; - r[432] = 2913; - q[433] = -2109; - r[433] = 3511; - q[434] = 1463; - r[434] = -3825; - q[435] = -741; - r[435] = -4028; - q[436] = -1314; - r[436] = -3879; - q[437] = 3115; - r[437] = 2659; - q[438] = -3160; - r[438] = -2605; - q[439] = 1868; - r[439] = 3644; - q[440] = -824; - r[440] = 4012; - q[441] = 781; - r[441] = 4020; - q[442] = -1257; - r[442] = -3898; - q[443] = 3331; - r[443] = -2382; - q[444] = 1642; - r[444] = -3752; - q[445] = 3748; - r[445] = -1650; - q[446] = -487; - r[446] = -4066; - q[447] = 3085; - r[447] = -2694; - q[448] = 4009; - r[448] = 839; - q[449] = -2308; - r[449] = -3383; - q[450] = 3850; - r[450] = 1397; - q[451] = -4078; - r[451] = -374; - q[452] = 2989; - r[452] = -2799; - q[453] = 3023; - r[453] = -2762; - q[454] = 1397; - r[454] = -3850; - q[455] = 323; - r[455] = 4083; - q[456] = 268; - r[456] = -4087; - q[457] = 2414; - r[457] = 3308; - q[458] = 3876; - r[458] = 1322; - q[459] = -3584; - r[459] = 1982; - q[460] = 1603; - r[460] = 3769; - q[461] = -1502; - r[461] = 3810; - q[462] = 1318; - r[462] = 3878; - q[463] = 1554; - r[463] = -3789; - q[464] = 2492; - r[464] = 3250; - q[465] = -4093; - r[465] = -154; - q[466] = 4008; - r[466] = 842; - q[467] = -2279; - r[467] = 3403; - q[468] = 3013; - r[468] = 2774; - q[469] = 2557; - r[469] = 3199; - q[470] = 4068; - r[470] = 475; - q[471] = 3324; - r[471] = -2392; - q[472] = 2653; - r[472] = -3120; - q[473] = 796; - r[473] = 4017; - q[474] = -1312; - r[474] = 3880; - q[475] = 1794; - r[475] = 3681; - q[476] = -2347; - r[476] = -3356; - q[477] = -4008; - r[477] = -840; - q[478] = -3773; - r[478] = -1592; - q[479] = 1609; - r[479] = 3766; - q[480] = -1564; - r[480] = -3785; - q[481] = 3004; - r[481] = 2784; - q[482] = 1258; - r[482] = 3897; - q[483] = 3729; - r[483] = 1693; - q[484] = -4095; - r[484] = -28; - q[485] = -4093; - r[485] = -146; - q[486] = 1393; - r[486] = -3851; - q[487] = 297; - r[487] = -4085; - q[488] = 2294; - r[488] = 3393; - q[489] = -2562; - r[489] = 3195; - q[490] = -1716; - r[490] = -3718; - q[491] = 2224; - r[491] = -3439; - q[492] = 2032; - r[492] = 3555; - q[493] = -2968; - r[493] = 2822; - q[494] = 2338; - r[494] = 3363; - q[495] = 1584; - r[495] = -3776; - q[496] = -3072; - r[496] = 2708; - q[497] = -1596; - r[497] = -3771; - q[498] = -2256; - r[498] = -3418; - q[499] = 4095; - r[499] = 89; - q[500] = -1949; - r[500] = 3602; - q[501] = 1844; - r[501] = 3657; - q[502] = -3375; - r[502] = 2319; - q[503] = -1481; - r[503] = -3818; - q[504] = 3228; - r[504] = -2520; - q[505] = 1116; - r[505] = 3940; - q[506] = -2783; - r[506] = 3004; - q[507] = 3915; - r[507] = 1201; - q[508] = 283; - r[508] = 4086; - q[509] = -3732; - r[509] = 1685; - q[510] = -433; - r[510] = -4072; - q[511] = -3667; - r[511] = 1823; - q[512] = 3883; - r[512] = 1300; - q[513] = -3742; - r[513] = 1663; - q[514] = 4093; - r[514] = -143; - q[515] = 3874; - r[515] = 1328; - q[516] = -3800; - r[516] = 1528; - q[517] = -1257; - r[517] = 3898; - q[518] = -1606; - r[518] = 3767; - q[519] = 3394; - r[519] = 2291; - q[520] = 2255; - r[520] = 3419; - q[521] = -4094; - r[521] = 120; - q[522] = -3767; - r[522] = 1606; - q[523] = 1849; - r[523] = -3654; - q[524] = -2883; - r[524] = 2908; - q[525] = 3469; - r[525] = 2176; - q[526] = 2654; - r[526] = 3119; - q[527] = -239; - r[527] = 4088; - q[528] = -651; - r[528] = 4043; - q[529] = -1140; - r[529] = 3934; - q[530] = 328; - r[530] = -4082; - q[531] = 3246; - r[531] = 2497; - q[532] = 4026; - r[532] = -753; - q[533] = -2041; - r[533] = -3550; - q[534] = -1154; - r[534] = 3929; - q[535] = -2710; - r[535] = 3070; - q[536] = -2860; - r[536] = 2932; - q[537] = 2097; - r[537] = 3517; - q[538] = 3492; - r[538] = -2140; - q[539] = 3123; - r[539] = 2649; - q[540] = 3360; - r[540] = 2342; - q[541] = 2498; - r[541] = 3245; - q[542] = 3976; - r[542] = 982; - q[543] = -2441; - r[543] = -3288; - q[544] = 3601; - r[544] = 1951; - q[545] = -4008; - r[545] = -842; - q[546] = 1243; - r[546] = 3902; - q[547] = 4069; - r[547] = 466; - q[548] = -2031; - r[548] = 3556; - q[549] = 4077; - r[549] = 386; - q[550] = -3112; - r[550] = -2663; - q[551] = 4087; - r[551] = -262; - q[552] = 4087; - r[552] = 266; - q[553] = -3907; - r[553] = -1228; - q[554] = -1611; - r[554] = 3765; - q[555] = 3066; - r[555] = -2715; - q[556] = 2657; - r[556] = 3117; - q[557] = 3912; - r[557] = -1213; - q[558] = -2531; - r[558] = -3220; - q[559] = 3500; - r[559] = -2127; - q[560] = -76; - r[560] = -4095; - q[561] = 3413; - r[561] = -2264; - q[562] = -4071; - r[562] = -448; - q[563] = 828; - r[563] = 4011; - q[564] = 3664; - r[564] = 1830; - q[565] = -1578; - r[565] = 3779; - q[566] = 3555; - r[566] = 2033; - q[567] = 3868; - r[567] = -1345; - q[568] = 4054; - r[568] = -580; - q[569] = -4094; - r[569] = 124; - q[570] = -3820; - r[570] = -1477; - q[571] = -3658; - r[571] = -1842; - q[572] = 2595; - r[572] = 3168; - q[573] = 3354; - r[573] = 2350; - q[574] = -701; - r[574] = -4035; - q[575] = -772; - r[575] = -4022; - q[576] = 2799; - r[576] = 2990; - q[577] = -3632; - r[577] = 1893; - q[578] = 310; - r[578] = 4084; - q[579] = 3984; - r[579] = -947; - q[580] = 3794; - r[580] = -1542; - q[581] = -2419; - r[581] = 3304; - q[582] = -3916; - r[582] = 1200; - q[583] = -3886; - r[583] = 1292; - q[584] = -3299; - r[584] = 2426; - q[585] = -437; - r[585] = 4072; - q[586] = 2053; - r[586] = -3544; - q[587] = 3987; - r[587] = 937; - q[588] = -789; - r[588] = -4019; - q[589] = 4055; - r[589] = -575; - q[590] = -3894; - r[590] = 1270; - q[591] = 4003; - r[591] = -864; - q[592] = -3060; - r[592] = 2721; - q[593] = -4009; - r[593] = 836; - q[594] = -1655; - r[594] = -3746; - q[595] = 3954; - r[595] = -1067; - q[596] = -773; - r[596] = 4022; - q[597] = -422; - r[597] = 4074; - q[598] = -3384; - r[598] = 2306; - q[599] = 195; - r[599] = -4091; - q[600] = -298; - r[600] = 4085; - q[601] = -3988; - r[601] = 931; - q[602] = 2014; - r[602] = -3566; - q[603] = 3349; - r[603] = -2357; - q[604] = 3800; - r[604] = 1526; - q[605] = 3858; - r[605] = 1374; - q[606] = 2947; - r[606] = 2844; - q[607] = -1483; - r[607] = -3818; - q[608] = 4056; - r[608] = -565; - q[609] = 2612; - r[609] = -3154; - q[610] = 2326; - r[610] = 3371; - q[611] = -3545; - r[611] = 2051; - q[612] = -1001; - r[612] = -3971; - q[613] = 3211; - r[613] = 2541; - q[614] = -2717; - r[614] = 3065; - q[615] = -3159; - r[615] = -2606; - q[616] = 2869; - r[616] = -2922; - q[617] = -1290; - r[617] = -3887; - q[618] = 2479; - r[618] = 3260; - q[619] = 3420; - r[619] = 2252; - q[620] = 1823; - r[620] = 3667; - q[621] = 3368; - r[621] = 2330; - q[622] = -3819; - r[622] = -1480; - q[623] = 3800; - r[623] = 1528; - q[624] = 3773; - r[624] = 1594; - q[625] = -189; - r[625] = -4091; - q[626] = -4067; - r[626] = -485; - q[627] = 2277; - r[627] = -3404; - q[628] = -4089; - r[628] = -233; - q[629] = -3634; - r[629] = 1889; - q[630] = 3292; - r[630] = 2437; - q[631] = -530; - r[631] = 4061; - q[632] = -3109; - r[632] = 2666; - q[633] = -3741; - r[633] = 1667; - q[634] = -1903; - r[634] = -3626; - q[635] = 3879; - r[635] = -1315; - q[636] = 4083; - r[636] = -315; - q[637] = -1148; - r[637] = 3931; - q[638] = 2630; - r[638] = 3139; - q[639] = -4001; - r[639] = 876; - q[640] = -2295; - r[640] = -3392; - q[641] = 1090; - r[641] = -3948; - q[642] = -3024; - r[642] = 2762; - q[643] = 2728; - r[643] = -3054; - q[644] = -3305; - r[644] = 2419; - q[645] = 60; - r[645] = 4095; - q[646] = 4048; - r[646] = -620; - q[647] = 589; - r[647] = -4053; - q[648] = -3867; - r[648] = 1347; - q[649] = -2944; - r[649] = -2847; - q[650] = -2721; - r[650] = 3060; - q[651] = 2928; - r[651] = 2863; - q[652] = 801; - r[652] = 4016; - q[653] = -3644; - r[653] = 1870; - q[654] = -1648; - r[654] = -3749; - q[655] = 825; - r[655] = -4012; - q[656] = -2036; - r[656] = -3553; - q[657] = -1192; - r[657] = -3918; - q[658] = 2875; - r[658] = 2916; - q[659] = -1831; - r[659] = -3663; - q[660] = -2865; - r[660] = -2926; - q[661] = -575; - r[661] = -4055; - q[662] = -3870; - r[662] = 1340; - q[663] = -4080; - r[663] = -356; - q[664] = -2176; - r[664] = -3469; - q[665] = -2986; - r[665] = -2803; - q[666] = 3978; - r[666] = -972; - q[667] = 2437; - r[667] = 3291; - q[668] = -3528; - r[668] = 2080; - q[669] = -3300; - r[669] = -2425; - q[670] = 3085; - r[670] = 2693; - q[671] = -3700; - r[671] = -1756; - q[672] = 3216; - r[672] = -2535; - q[673] = 4094; - r[673] = -91; - q[674] = 3775; - r[674] = -1589; - q[675] = 1097; - r[675] = -3946; - q[676] = -152; - r[676] = -4093; - q[677] = -3490; - r[677] = 2142; - q[678] = 3747; - r[678] = 1654; - q[679] = -1490; - r[679] = -3815; - q[680] = -3998; - r[680] = -886; - q[681] = 3726; - r[681] = -1700; - q[682] = -1600; - r[682] = 3770; - q[683] = -87; - r[683] = 4095; - q[684] = 2538; - r[684] = -3214; - q[685] = -4095; - r[685] = 52; - q[686] = -3993; - r[686] = -910; - q[687] = 4051; - r[687] = 603; - q[688] = -1242; - r[688] = -3902; - q[689] = 2155; - r[689] = 3482; - q[690] = 1270; - r[690] = 3893; - q[691] = 1919; - r[691] = -3618; - q[692] = -3145; - r[692] = 2623; - q[693] = 2475; - r[693] = 3263; - q[694] = 2226; - r[694] = -3437; - q[695] = -3894; - r[695] = -1269; - q[696] = -429; - r[696] = 4073; - q[697] = -1346; - r[697] = 3868; - q[698] = 1297; - r[698] = 3885; - q[699] = 1699; - r[699] = 3726; - q[700] = -3375; - r[700] = 2319; - q[701] = 1577; - r[701] = -3779; - q[702] = -63; - r[702] = 4095; - q[703] = 1215; - r[703] = -3911; - q[704] = -1492; - r[704] = 3814; - q[705] = -1530; - r[705] = -3799; - q[706] = 3442; - r[706] = 2218; - q[707] = -3867; - r[707] = -1349; - q[708] = -3291; - r[708] = -2437; - q[709] = -2253; - r[709] = -3420; - q[710] = -150; - r[710] = -4093; - q[711] = -2686; - r[711] = -3092; - q[712] = 3470; - r[712] = 2175; - q[713] = -3826; - r[713] = -1461; - q[714] = -3148; - r[714] = 2619; - q[715] = -3858; - r[715] = 1375; - q[716] = -3844; - r[716] = -1412; - q[717] = -3652; - r[717] = 1854; - q[718] = 4018; - r[718] = -791; - q[719] = 179; - r[719] = -4092; - q[720] = 3498; - r[720] = 2129; - q[721] = -1999; - r[721] = -3574; - q[722] = 3531; - r[722] = 2075; - q[723] = 4050; - r[723] = -606; - q[724] = -1639; - r[724] = 3753; - q[725] = -3661; - r[725] = 1835; - q[726] = 4039; - r[726] = 679; - q[727] = 3561; - r[727] = 2023; - q[728] = 528; - r[728] = 4061; - q[729] = -634; - r[729] = -4046; - q[730] = 364; - r[730] = -4079; - q[731] = 2735; - r[731] = 3048; - q[732] = 3978; - r[732] = 973; - q[733] = -4073; - r[733] = -427; - q[734] = -3722; - r[734] = 1708; - q[735] = 2356; - r[735] = -3350; - q[736] = -1125; - r[736] = -3938; - q[737] = 4054; - r[737] = 580; - q[738] = 3328; - r[738] = -2387; - q[739] = 1439; - r[739] = -3834; - q[740] = 1746; - r[740] = 3705; - q[741] = 2507; - r[741] = 3238; - q[742] = 3839; - r[742] = -1427; - q[743] = 488; - r[743] = -4066; - q[744] = 1187; - r[744] = 3920; - q[745] = 2038; - r[745] = -3552; - q[746] = -905; - r[746] = -3994; - q[747] = -236; - r[747] = 4089; - q[748] = 208; - r[748] = -4090; - q[749] = 1660; - r[749] = 3744; - q[750] = -4074; - r[750] = -415; - q[751] = -2304; - r[751] = 3385; - q[752] = -2457; - r[752] = 3276; - q[753] = 3302; - r[753] = 2423; - q[754] = 1778; - r[754] = -3689; - q[755] = 2019; - r[755] = 3563; - q[756] = 4037; - r[756] = 687; - q[757] = -2365; - r[757] = 3343; - q[758] = 5; - r[758] = -4095; - q[759] = 160; - r[759] = -4092; - -} /*initRand*/ - -/** - * initializes the MEL-2_LINEAR LOOKUP TABLE - * @param sig_inObj : sig PU internal object of the sub-object - * @return void - * @remarks translated from matlab code to c-code - * @callgraph - * @callergraph - * - * input - * - bilinTab : base address of bilinTable destination vector - * - alpha : warping factor - * - size : size of the vectors to be generated - * - A,B : base address of array of indexes for lookup table implementation - * - D : base address of delta array for lookup table implementation - * - * output - * - bilinTab, A, B, D : initialized vectors - */ -void mel_2_lin_init(sig_innerobj_t *sig_inObj) -{ - - /*Declare variables tied to I/O PARAMS formerly passed by value or reference*/ - picoos_single alpha; - picoos_int32 *D; - picoos_int32 size; - picoos_int16 *A; - - /*Link local variables with sig data object*/ - - alpha = sig_inObj->warp_p; - size = (sig_inObj->hfftsize_p) + 1; - A = sig_inObj->A_p; - D = sig_inObj->d_p; - /* - fixed point interpolation tables - scaling factor: 0x20 - corresponding bit shift: 5 - */ - - A[0] = 0; - D[0] = 0; - A[1] = 2; - D[1] = 14; - A[2] = 4; - D[2] = 29; - A[3] = 7; - D[3] = 11; - A[4] = 9; - D[4] = 24; - A[5] = 12; - D[5] = 5; - A[6] = 14; - D[6] = 18; - A[7] = 16; - D[7] = 30; - A[8] = 19; - D[8] = 9; - A[9] = 21; - D[9] = 19; - A[10] = 23; - D[10] = 29; - A[11] = 26; - D[11] = 5; - A[12] = 28; - D[12] = 12; - A[13] = 30; - D[13] = 19; - A[14] = 32; - D[14] = 24; - A[15] = 34; - D[15] = 27; - A[16] = 36; - D[16] = 30; - A[17] = 38; - D[17] = 31; - A[18] = 40; - D[18] = 31; - A[19] = 42; - D[19] = 29; - A[20] = 44; - D[20] = 26; - A[21] = 46; - D[21] = 22; - A[22] = 48; - D[22] = 17; - A[23] = 50; - D[23] = 10; - A[24] = 52; - D[24] = 2; - A[25] = 53; - D[25] = 24; - A[26] = 55; - D[26] = 13; - A[27] = 57; - D[27] = 1; - A[28] = 58; - D[28] = 20; - A[29] = 60; - D[29] = 5; - A[30] = 61; - D[30] = 21; - A[31] = 63; - D[31] = 4; - A[32] = 64; - D[32] = 18; - A[33] = 65; - D[33] = 31; - A[34] = 67; - D[34] = 11; - A[35] = 68; - D[35] = 21; - A[36] = 69; - D[36] = 31; - A[37] = 71; - D[37] = 7; - A[38] = 72; - D[38] = 14; - A[39] = 73; - D[39] = 21; - A[40] = 74; - D[40] = 27; - A[41] = 75; - D[41] = 31; - A[42] = 77; - D[42] = 3; - A[43] = 78; - D[43] = 6; - A[44] = 79; - D[44] = 8; - A[45] = 80; - D[45] = 10; - A[46] = 81; - D[46] = 10; - A[47] = 82; - D[47] = 10; - A[48] = 83; - D[48] = 9; - A[49] = 84; - D[49] = 8; - A[50] = 85; - D[50] = 6; - A[51] = 86; - D[51] = 3; - A[52] = 86; - D[52] = 31; - A[53] = 87; - D[53] = 27; - A[54] = 88; - D[54] = 23; - A[55] = 89; - D[55] = 18; - A[56] = 90; - D[56] = 12; - A[57] = 91; - D[57] = 6; - A[58] = 91; - D[58] = 31; - A[59] = 92; - D[59] = 24; - A[60] = 93; - D[60] = 16; - A[61] = 94; - D[61] = 8; - A[62] = 94; - D[62] = 31; - A[63] = 95; - D[63] = 22; - A[64] = 96; - D[64] = 13; - A[65] = 97; - D[65] = 3; - A[66] = 97; - D[66] = 25; - A[67] = 98; - D[67] = 14; - A[68] = 99; - D[68] = 3; - A[69] = 99; - D[69] = 24; - A[70] = 100; - D[70] = 13; - A[71] = 101; - D[71] = 1; - A[72] = 101; - D[72] = 21; - A[73] = 102; - D[73] = 8; - A[74] = 102; - D[74] = 27; - A[75] = 103; - D[75] = 14; - A[76] = 104; - D[76] = 1; - A[77] = 104; - D[77] = 19; - A[78] = 105; - D[78] = 6; - A[79] = 105; - D[79] = 24; - A[80] = 106; - D[80] = 9; - A[81] = 106; - D[81] = 27; - A[82] = 107; - D[82] = 12; - A[83] = 107; - D[83] = 29; - A[84] = 108; - D[84] = 14; - A[85] = 108; - D[85] = 31; - A[86] = 109; - D[86] = 15; - A[87] = 109; - D[87] = 31; - A[88] = 110; - D[88] = 16; - A[89] = 110; - D[89] = 31; - A[90] = 111; - D[90] = 15; - A[91] = 111; - D[91] = 31; - A[92] = 112; - D[92] = 14; - A[93] = 112; - D[93] = 30; - A[94] = 113; - D[94] = 13; - A[95] = 113; - D[95] = 28; - A[96] = 114; - D[96] = 11; - A[97] = 114; - D[97] = 26; - A[98] = 115; - D[98] = 9; - A[99] = 115; - D[99] = 23; - A[100] = 116; - D[100] = 6; - A[101] = 116; - D[101] = 20; - A[102] = 117; - D[102] = 2; - A[103] = 117; - D[103] = 16; - A[104] = 117; - D[104] = 31; - A[105] = 118; - D[105] = 13; - A[106] = 118; - D[106] = 27; - A[107] = 119; - D[107] = 8; - A[108] = 119; - D[108] = 22; - A[109] = 120; - D[109] = 4; - A[110] = 120; - D[110] = 17; - A[111] = 120; - D[111] = 31; - A[112] = 121; - D[112] = 13; - A[113] = 121; - D[113] = 26; - A[114] = 122; - D[114] = 8; - A[115] = 122; - D[115] = 21; - A[116] = 123; - D[116] = 2; - A[117] = 123; - D[117] = 15; - A[118] = 123; - D[118] = 29; - A[119] = 124; - D[119] = 10; - A[120] = 124; - D[120] = 23; - A[121] = 125; - D[121] = 4; - A[122] = 125; - D[122] = 17; - A[123] = 125; - D[123] = 31; - A[124] = 126; - D[124] = 12; - A[125] = 126; - D[125] = 25; - A[126] = 127; - D[126] = 6; - A[127] = 127; - D[127] = 19; - A[128] = 128; - D[128] = 0; - -}/*mel_2_lin_init*/ - -/** - * function to be documented - * @param ang : ?? - * @param table : ?? - * @param cs : ?? - * @param sn : ?? - * @return void - * @callgraph - * @callergraph - */ -static void get_trig(picoos_int32 ang, picoos_int32 *table, picoos_int32 *cs, - picoos_int32 *sn) -{ - picoos_int32 i, j, k; - - i = k = ang >> PICODSP_PI_SHIFT; /* * PICODSP_COS_TABLE_LEN2/PICODSP_FIX_SCALE2 */ - if (i < 0) - i = -i; - j = 1; - i &= (PICODSP_COS_TABLE_LEN4 - 1); - if (i > PICODSP_COS_TABLE_LEN2) - i = PICODSP_COS_TABLE_LEN4 - i; - if (i > PICODSP_COS_TABLE_LEN) { - j = -1; - i = PICODSP_COS_TABLE_LEN2 - i; - } - if (j == 1) - *cs = table[i]; - else - *cs = -table[i]; - - i = k - PICODSP_COS_TABLE_LEN; - if (i < 0) - i = -i; - j = 1; - i &= (PICODSP_COS_TABLE_LEN4 - 1); - if (i > PICODSP_COS_TABLE_LEN2) - i = PICODSP_COS_TABLE_LEN4 - i; - if (i > PICODSP_COS_TABLE_LEN) { - j = -1; - i = PICODSP_COS_TABLE_LEN2 - i; - } - if (j == 1) - *sn = table[i]; - else - *sn = -table[i]; -}/*get_trig*/ - -/** - * function to be documented - * @param sig_inObj : sig PU internal object of the sub-object - * @return void - * @callgraph - * @callergraph - */ -void save_transition_frame(sig_innerobj_t *sig_inObj) -{ - picoos_int32 *tmp, *tmp2; /*for loop unrolling*/ - - if (sig_inObj->voiced_p != sig_inObj->prevVoiced_p) { - sig_inObj->VoicTrans = sig_inObj->prevVoiced_p; /*remember last voicing transition*/ - tmp = sig_inObj->ImpResp_p; - tmp2 = sig_inObj->imp_p; - FAST_DEVICE(PICODSP_FFTSIZE,*(tmp++)=*(tmp2++);); - if (sig_inObj->voiced_p == 1) - sig_inObj->nV = 0; - else - sig_inObj->nU = 0; /*to avoid problems in case of very short voiced or unvoiced parts (less than 4 frames long)*/ - } -}/*save_transition_frame*/ - -/** - * calculates an unweighted excitation window - * @param sig_inObj : sig PU internal object of the sub-object - * @param nextPeak : position of next peak (excitation position) - * @return PICO_OK - * @callgraph - * @callergraph - * input - * - hop : hop size in samples - * - winlen : excitation window length - * - E : energy - * - F0 : pitch - * - nextPeak : state that remembers next excitation index - * - Fs - sampling frequency - * output - * - LocV, LocU : (MAX_EN size) location of excitation points - * - EnV, EnU : (MAX_EN size) RMS values of excitation (scaled) - * - nV, nU : (integers) number of excitation points - * - nextPeak new position of lastPeak to calculate next frame - */ -static void get_simple_excitation(sig_innerobj_t *sig_inObj, - picoos_int16 *nextPeak) -{ - /*Define local variables*/ - picoos_int16 nI, nJ, k; - /* picoos_single InvSqrt3=(picoos_single)2/(picoos_single)sqrt(3.0); *//*constant*/ - picoos_int32 Ti, sqrtTi; - picoos_int16 hop, winlen, Fs; - picoos_single E, F0; - picoos_int16 voiced; - picoos_single fact; /*normalization factor*/ - picoos_single rounding = 0.5f; - - /*Link local variables to sig object*/ - hop = sig_inObj->hop_p; - winlen = sig_inObj->m2_p; - Fs = sig_inObj->Fs_p; - E = sig_inObj->E_p; - F0 = sig_inObj->F0_p; - voiced = sig_inObj->voiced_p; - - /* shift previous excitation window by hop samples*/ - for (nI = 0; nI < sig_inObj->nV; nI++) { - sig_inObj->LocV[nI] = sig_inObj->LocV[nI] - hop; - } - for (nI = 0; nI < sig_inObj->nU; nI++) { - sig_inObj->LocU[nI] = sig_inObj->LocU[nI] - hop; - } - - /*get rid of the voiced points that fall out of the interval*/ - nI = 0; - while ((sig_inObj->LocV[nI] < 0) && nI < sig_inObj->nV) - nI++; - - for (nJ = nI; nJ < sig_inObj->nV; nJ++) { - sig_inObj->LocV[nJ - nI] = sig_inObj->LocV[nJ]; - sig_inObj->EnV[nJ - nI] = sig_inObj->EnV[nJ]; - } - sig_inObj->nV -= nI; - /*get rid of the unvoiced points that fall out of the interval */ - nI = 0; - while ((sig_inObj->LocU[nI] < 0) && nI < sig_inObj->nU) - nI++; - - for (nJ = nI; nJ < sig_inObj->nU; nJ++) { - sig_inObj->LocU[nJ - nI] = sig_inObj->LocU[nJ]; - sig_inObj->EnU[nJ - nI] = sig_inObj->EnU[nJ]; - } - sig_inObj->nU -= nI; - - *nextPeak -= hop; - k = *nextPeak; - - fact = 3; - if (voiced == 0) { /*Unvoiced*/ - - Ti = (picoos_int32) (rounding + (picoos_single) Fs - / (picoos_single) sig_inObj->Fuv_p); /* round Period*/ - sqrtTi = (picoos_int32) (E * sqrt((double) Fs - / (hop * sig_inObj->Fuv_p)) * fact * PICODSP_GETEXC_K1); - while (k < winlen) { - if (k < winlen) { - sig_inObj->LocU[sig_inObj->nU] = k; - sig_inObj->EnU[sig_inObj->nU] = sqrtTi; - sig_inObj->nU++; - k += (picoos_int16) Ti; - } - } - } else { /*Voiced*/ - Ti - = (picoos_int32) (rounding + (picoos_single) Fs - / (picoos_single) F0); /*Period*/ - sqrtTi = (picoos_int32) (E - * sqrt((double) Fs / (hop * sig_inObj->F0_p)) * fact - * PICODSP_GETEXC_K1); - while (k < winlen) { - sig_inObj->LocV[sig_inObj->nV] = k; - sig_inObj->EnV[sig_inObj->nV] = sqrtTi; - sig_inObj->nV++; - k += (picoos_int16) Ti; - } - } - *nextPeak = k; - -}/*get_simple_excitation*/ - -#ifdef __cplusplus -} -#endif - -/* end picosig2.c */ diff --git a/lib/picosig2.h b/lib/picosig2.h deleted file mode 100644 index f239ced..0000000 --- a/lib/picosig2.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * 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 picosig2.h - * - * Signal Generation PU - Internal functions - header file - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#ifndef PICOSIG2_H_ -#define PICOSIG2_H_ - -#include "picoos.h" -#include "picodsp.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -/*---------------------------------------------------------- - // Name : sig_innerobj - // Function: innerobject definition for the sig processing - // Shortcut: sig - //---------------------------------------------------------*/ -typedef struct sig_innerobj -{ - - /*-----------------------Definition of the local storage for this PU--------*/ - picoos_int16 *idx_vect1; /*reserved for bit reversal tables*/ - picoos_int16 *idx_vect2; /*reserved for table lookup "A" vector*/ - picoos_int16 *idx_vect4; /*reserved for max peak index arrax in pchip*/ - picoos_int16 *idx_vect5; /*reserved for min index arrax in sigana_singleIMF*/ - picoos_int16 *idx_vect6; /*reserved for max index arrax in sigana_singleIMF*/ - picoos_int16 *idx_vect7; /*reserved for dispersed phase */ - picoos_int16 *idx_vect8; /*reserved for LocV*/ - picoos_int16 *idx_vect9; /*reserved for LocU*/ - - picoos_int32 *int_vec22; /*reserved for normalized hanning window - fixed point */ - picoos_int32 *int_vec23; /*reserved for impresp - fixed point */ - picoos_int32 *int_vec24; /*reserved for impresp - fixed point */ - picoos_int32 *int_vec25; /*reserved for window - fixed point */ - picoos_int32 *int_vec26; /*reserved for wavBuf - fixed point */ - picoos_int32 *int_vec28; /*reserved for cepstral vectors input - fixed point */ - picoos_int32 *int_vec29; /*reserved for cepstral vectors input - fixed point */ - picoos_int32 *int_vec38; /*reserved for cepstral vectors input - fixed point */ - picoos_int32 *int_vec30; /*reserved for cepstral vectors input - fixed point */ - picoos_int32 *int_vec31; /*reserved for cepstral vectors input - fixed point */ - - picoos_int32 *int_vec32; /*reserved for cepstral vectors input - fixed point */ - picoos_int32 *int_vec33; /*reserved for cepstral vectors input - fixed point */ - - picoos_int32 *int_vec34; /* reserved for sin table- fixed point */ - picoos_int32 *int_vec35; /* reserved for cos table - fixed point */ - picoos_int32 *int_vec36; /* reserved for currently used sin table- fixed point */ - picoos_int32 *int_vec37; /* reserved for currently used cos table - fixed point */ - - picoos_int32 *int_vec39; /* reserved for ang - fixed point */ - picoos_int32 *int_vec40; /* reserved for cos table - fixed point */ - - picoos_int32 *int_vec41[CEPST_BUFF_SIZE]; /*reserved for phase smoothing - cepstrum buffers */ - picoos_int32 *int_vec42[PHASE_BUFF_SIZE]; /*reserved for phase smoothing - phase buffers */ - - picoos_int16 idx_vect10[CEPST_BUFF_SIZE]; /*reserved for pitch value buffering before phase smoothing*/ - picoos_int16 idx_vect11[CEPST_BUFF_SIZE]; /*reserved for phonetic value bufferingid before phase smoothing*/ - picoos_int16 idx_vect12[CEPST_BUFF_SIZE]; /*reserved for voicing value bufferingbefore phase smoothing*/ - picoos_int16 idx_vect13[CEPST_BUFF_SIZE]; /*reserved for unrectified pitch value bufferingbefore phase smoothing*/ - picoos_int16 idx_vect14[PHASE_BUFF_SIZE]; /*reserved for vox_bnd value buffering before phase smoothing*/ - - picoos_int32 *sig_vec1; - - picoos_single bvalue1; /*reserved for warp*/ - picoos_int32 ibvalue2; /*reserved for voxbnd*/ - picoos_int32 ibvalue3; /*reserved for voxbnd2*/ - picoos_single bvalue4; /*reserved for E*/ - picoos_single bvalue5; /*reserved for F0*/ - picoos_single bvalue6; /*reserved for sMod*/ - - picoos_single bvalue7; /*reserved for voicing*/ - picoos_single bvalue8; /*reserved for unrectified pitch*/ - - picoos_int16 ivalue1; /*reserved for m1,ceporder*/ - picoos_int16 ivalue2; /*reserved for m2,fftorder,windowlen*/ - picoos_int16 ivalue3; /*reserved for fftorder/2*/ - picoos_int16 ivalue4; /*reserved for framelen, displacement*/ - picoos_int16 ivalue5; /*reserved for voiced*/ - picoos_int16 ivalue6; /*reserved for generic result code*/ - picoos_int16 ivalue7; /*reserved for i*/ - picoos_int16 ivalue8; /*reserved for j*/ - picoos_int16 ivalue9; /*reserved for hop*/ - picoos_int16 ivalue10; /*reserved for nextPeak*/ - picoos_int16 ivalue11; /*reserved for nFrame*/ - picoos_int16 ivalue12; /*reserved for raw*/ - picoos_int16 ivalue13; /*reserved for hts engine flag*/ - picoos_int16 ivalue14; /*reserved for ph id*/ - picoos_int16 ivalue15; /*reserved for Voiced*/ - picoos_int16 ivalue16; /*reserved for prevVoiced*/ - picoos_int16 ivalue17; /*reserved for nV (size of LocV)*/ - picoos_int16 ivalue18; /*reserved for nU (size of LocU)*/ - - picoos_int16 ivalue19; /*reserved for voicTrans*/ - - picoos_int16 ivalue20; /*reserved for n_availabe index*/ - - picoos_int32 lvalue1; /*reserved for sampling rate*/ - picoos_int32 lvalue2; /*reserved for VCutoff*/ - picoos_int32 lvalue3; /*reserved for UVCutoff*/ - picoos_int32 lvalue4; /*reserved for fMax */ - - picoos_int32 iRand; /*reserved for phase random table poointer ())*/ - -} sig_innerobj_t; - -/*------------------------------------------------------------------ - Exported (to picosig.c) Service routines : - routine name and I/O parameters are to be maintained for PICO compatibility!! - ------------------------------------------------------------------*/ -extern pico_status_t sigAllocate(picoos_MemoryManager mm, - sig_innerobj_t *sig_inObj); -extern void sigDeallocate(picoos_MemoryManager mm, sig_innerobj_t *sig_inObj); -extern void sigDspInitialize(sig_innerobj_t *sig_inObj); - -/*------------------------------------------------------------------ - Exported (to picosig.c) Processing routines : - routine number, name and content can be changed. unique I/O parameter should be "sig" - ------------------------------------------------------------------*/ -extern void mel_2_lin_init(sig_innerobj_t *sig_inObj); -extern void save_transition_frame(sig_innerobj_t *sig_inObj); -extern void mel_2_lin_init(sig_innerobj_t *sig_inObj); -extern void post_filter_init(sig_innerobj_t *sig_inObj); -extern void mel_2_lin_lookup(sig_innerobj_t *sig_inObj, picoos_uint32 mgc); -extern void post_filter(sig_innerobj_t *sig_inObj); -extern void phase_spec2(sig_innerobj_t *sig_inObj); -extern void env_spec(sig_innerobj_t *sig_inObj); -extern void save_transition_frame(sig_innerobj_t *sig_inObj); -extern void td_psola2(sig_innerobj_t *sig_inObj); -extern void impulse_response(sig_innerobj_t *sig_inObj); -extern void overlap_add(sig_innerobj_t *sig_inObj); - -/* ------------------------------------------------------------------- - * symbolic vs area assignements - * -------------------------------------------------------------------*/ -#define WavBuff_p int_vec26 /*output is Wav buffer (2*FFTSize)*/ -#define window_p int_vec25 /*window function (hanning) */ -#define ImpResp_p int_vec23 /*output step 6*/ -#define imp_p int_vec24 /*output step 6*/ -#define warp_p bvalue1 /*warp factor */ -#define voxbnd_p ibvalue2 /*phase spectra reconstruction noise factor V*/ /* fixed point */ -#define voxbnd2_p ibvalue3 /*phase spectra reconstruction noise factor UV */ /* fixed point */ -#define E_p bvalue4 /*energy after Envelope spectrum calculation */ -#define F0_p bvalue5 /*pitch*/ -#define sMod_p bvalue6 /*speaker modification factor*/ -#define voicing bvalue7 /*voicing*/ -#define Fuv_p bvalue8 /*unrectified pitch (for unvoiced too)*/ -#define m1_p ivalue1 /*ceporder(melorder=ceporder-1) */ -#define m2_p ivalue2 /*fftorder*/ -#define windowLen_p ivalue2 /*same as fftorder*/ -#define hfftsize_p ivalue3 /*fftorder/2*/ -#define framesz_p ivalue4 /*displacement*/ -#define voiced_p ivalue5 /*voicing state*/ -#define nRes_p ivalue6 /*generic result*/ -#define i_p ivalue7 /*generic counter*/ -#define j_p ivalue8 /*generic counter*/ -#define hop_p ivalue9 /*hop */ -#define nextPeak_p ivalue10 /*nextPeak*/ -#define phId_p ivalue14 /*phonetic id*/ -#define prevVoiced_p ivalue16 /*previous voicing state (for frame 1)*/ -#define nV ivalue17 -#define nU ivalue18 -#define VoicTrans ivalue19 /* */ -#define Fs_p lvalue1 /*Sampling frequency*/ -#define VCutoff_p lvalue2 /*voicing cut off frequency in Hz*/ -#define UVCutoff_p lvalue3 /*unvoicing cut off frequency in Hz*/ -/* Reusable area */ -#define wcep_pI int_vec28 /*input step1*/ -#define d_p int_vec38 /*output mel_2_lin_init : table lookup vector D*/ -#define A_p idx_vect2 /*output mel_2_lin_init : table lookup vector A*/ -#define ang_p int_vec39 /*output step4*/ -#define EnV int_vec30 -#define EnU int_vec31 -#define randCosTbl int_vec34 -#define randSinTbl int_vec35 -#define outCosTbl int_vec36 -#define outSinTbl int_vec37 -#define cos_table int_vec40 -#define norm_window_p int_vec22 /*window function (hanning) */ -#define norm_window2_p int_vec27 /*window function (hanning) */ -#define F2r_p int_vec32 /*output step 7*/ -#define F2i_p int_vec33 /*output step 7*/ -#define LocV idx_vect8 /*excitation position voiced pulses*/ -#define LocU idx_vect9 /*excitation position unvoiced pulses*/ - -#define CepBuff int_vec41 /*Buffer for incoming cepstral vector pointers*/ -#define PhsBuff int_vec42 /*Buffer for incoming phase vector pointers*/ -#define F0Buff idx_vect10 /*Buffer for incoming F0 values*/ -#define PhIdBuff idx_vect11 /*Buffer for incoming PhId values*/ -#define VoicingBuff idx_vect12 /*Buffer for incoming voicing values*/ -#define FuVBuff idx_vect13 /*Buffer for incoming FuV values*/ -#define VoxBndBuff idx_vect14 /*Buffer for incoming VoxBnd values*/ - -#define n_available ivalue20 /*variable for indexing the incoming buffers*/ - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/picospho.c b/lib/picospho.c deleted file mode 100644 index 0d0cdf8..0000000 --- a/lib/picospho.c +++ /dev/null @@ -1,1694 +0,0 @@ -/* - * 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 picospho.c - * - * sentence phonemic/phonetic FSTs PU - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#include "picoos.h" -#include "picodbg.h" -#include "picodata.h" - -#include "picoknow.h" -#include "picokfst.h" -#include "picoktab.h" -#include "picotrns.h" - -#include "picospho.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -#define SPHO_BUFSIZE (3 * PICODATA_BUFSIZE_DEFAULT) - - - -#define SPHO_MAX_ALTDESC_SIZE (60 * PICOTRNS_MAX_NUM_POSSYM) - - -#define SPHO_SMALLEST_SIL_DUR 1 - - -/** @addtogroup picospho - * - * Algorithmic description - * ======================= - * The main function, sphoStep, is divided into the subprocesses (processing states) described further down. - * - * Flow control: - * ------------ - * The processing flow is controlled by setting - * - 'procState' : the next state to be processed - * - 'feedFollowState' : the state to be processed after the feed state (the feed state is treated like a primitive "subroutine") - * - some other flags - * - * Buffering: - * --------- - * - The input items are mainly stored and processed in two buffers, collectively called 'inBuf' - * - cbuf : unstructured buffer containing item contents - * - headx : structured buffer containing item heads, each expanded by a pointer to the item contents - * and space for a boundary potentially to be inserted (to the left of the original item) - * - For transduction, phonemes and their position are extracted from inBuf into - * - phonBuf, - * processed there, and the resulting phonemes realigned with inBuf. - * - Word items are split into syllables, stored in - * - sylBuf - * - Items to be output are stored in outBuf - * - * Windowing: - * --------- - * Optimal solutions are achieved if a whole sentence is processed at once. However, if any of the buffers are too small, - * only sentence parts are processed. To improve the quality of such sub-optimal solutions, a moving-window-with-overlap is applied: - * - [0,headxReadPos[ : the window considered for transduction - * - [activeStartPos,activeEndPos[ : the "active" subrange of the window actually used for output - * - penultima : the position (within the active range) that should be used as new window start when shifting the window - * - * After PROCESS_PARSE: - * 0 activeStartPos penultima activeEndPos headxReadPos headxWritePos - * | | | | | | - * |-------------=================================---------------| ['----': context '====' : active subrange) - * - * After PROCESS_SHIFT: - * 0 activeStartPos headWritePos - * | | | | - * |------------... (only left context is known; new active range, penultima, and right context to be established at next parse) - * - * Processing states: - * ----------------- - * - INIT : initialize state variables - * - COLLECT : collect items into internal buffers ("inBuf") - * - PROCESS_PARSE : go through inBuf items and extract position/phoneme pairs into phoneme buffer 'phonBuf' - * word boundary phonemes are inserted between words - * - PROCESS_TRANSDUCE : transduce phonBuf - * - PROCESS_BOUNDS : go through inBuf items again and match against transduced pos/phoneme - * this is the first round of alignment, only inserting/deleting/modifying bounds, according to - * - existing BOUND items - * - newly produced word bounds separating WORDPHON items - * - bound upgrades/downgrades from transduction - * - bound upgrades/downgrades/insertions from SIL command items (originating e.g. from text commands) - * all relevant bounds are placed in the corresponding headx extention; original bound items become invalid. - * - PROCESS_RECOMB : go through inBuf items again and match against transduced pos/phoneme - * this is the second round of alignment, treating non-BOUND items - * - WORDPHONs are broken into syllables by "calling" PROCESS_SYL - * - "side-bounds" (in the headx extension) are output by "calling" FEED - * - BOUND items are consumed with no effect - * - other items are output unchanged "calling" FEED - * - PROCESS_SYL : the WORDPHON coming from RECOMB is matched against the phonBuf and (new) SYLLPHON items - * are created. (the original wordphon is consumed) - * - FEED : feeds one item and returns to spho->feedFollowState - * - SHIFT : items in inBuf are shifted left to make room for new items. If a sentence doesn't fit - * inBuf in its entirety, left and/or right contexts are kept so they can be considered in - * the next transduction. - */ - - - -/* PU sphoStep states */ -#define SPHO_STEPSTATE_INIT 0 -#define SPHO_STEPSTATE_COLLECT 1 -#define SPHO_STEPSTATE_PROCESS_PARSE 2 -#define SPHO_STEPSTATE_PROCESS_TRANSDUCE 3 -#define SPHO_STEPSTATE_PROCESS_BOUNDS 4 -#define SPHO_STEPSTATE_PROCESS_RECOMB 5 -#define SPHO_STEPSTATE_PROCESS_SYL 6 -#define SPHO_STEPSTATE_FEED 7 -#define SPHO_STEPSTATE_SHIFT 8 - -#define SPHO_POS_INVALID (PICOTRNS_POS_INVALID) /* indicates that no position was set yet */ - -/* nr item restriction: maximum number of extended item heads in headx */ -#define SPHO_MAXNR_HEADX 60 - -/* nr item restriction: maximum size of all item contents together in cont */ -#define SPHO_MAXSIZE_CBUF (30 * 255) - -/* "expanded head": item head expanded by a content position and a by boundary information - * potentially inserted "to the left" of the item */ -typedef struct { - picodata_itemhead_t head; - picoos_uint16 cind; - picoos_uint8 boundstrength; /* bstrength to the left, 0 if not set */ - picoos_uint8 phrasetype; /* btype for following phrase, 0 if not set */ - picoos_int16 sildur; /* silence duration for boundary, -1 if not set */ -} picospho_headx_t; - - - -#define SPHO_MSGSTR_SIZE 32 - -/** object : SentPhoUnit - * shortcut : spho - * derived from : picodata_ProcessingUnit - */ -typedef struct spho_subobj { - picoos_Common common; - - /* we use int16 for buffer positions so we can indicate exceptional positions (invalid etc.) with negative - * integers */ - picoos_uint8 procState; /* for next processing step decision */ - - /* buffer for item headers */ - picoos_uint8 tmpbuf[PICODATA_MAX_ITEMSIZE]; /* tmp. location for an item */ - - picospho_headx_t headx[SPHO_MAXNR_HEADX]; /* "expanded head" buffer */ - picoos_uint16 headxBufSize; /* actually allocated size (if one day headxBuf is allocated dynamically) */ - picoos_uint16 headxReadPos, headxWritePos; - - picoos_uint8 cbuf[SPHO_MAXSIZE_CBUF]; - picoos_uint16 cbufBufSize; /* actually allocated size */ - picoos_uint16 cbufWritePos; /* next position to write to, 0 if buffer empty */ - - picoos_uint8 outBuf[PICODATA_BUFSIZE_DEFAULT]; /* internal output buffer to hold just one item */ - picoos_uint16 outBufSize; /* actually allocated size (if one day outBuf is allocated dynamically) */ - picoos_uint16 outReadPos; /* next pos to read from inBuf for output */ - - /* picoos_int16 outWritePos; */ /* next pos to output from in buf */ - - picoos_uint8 sylBuf[255]; /* internal buffer to hold contents of syl item to be output */ - picoos_uint8 sylReadPos, sylWritePos; /* next pos to read from sylBuf, next pos to write to sylBuf */ - - /* buffer for internal calculation of transducer */ - picotrns_AltDesc altDescBuf; - /* the number of AltDesc in the buffer */ - picoos_uint16 maxAltDescLen; - - /* the input to a transducer should not be larger than PICOTRNS_MAX_NUM_POSSYM - * so the output may expand (up to 4*PICOTRNS_MAX_NUM_POSSYM) */ - - picotrns_possym_t phonBufA[4 * PICOTRNS_MAX_NUM_POSSYM + 1]; - picotrns_possym_t phonBufB[4 * PICOTRNS_MAX_NUM_POSSYM + 1]; - picotrns_possym_t * phonBuf; - picotrns_possym_t * phonBufOut; - picoos_uint16 phonReadPos, phonWritePos; /* next pos to read from phonBufIn, next pos to write to phonBufIn */ - - picoos_int16 activeStartPos; /* start position of items to be treated (at end of left context) */ - picoos_int16 penultima, activeEndPos; /* positions of last two bounds/words; SPHO_POS_INVALID means uninitialized */ - picoos_int16 lastPhraseBoundPos; /* position of the last bound encountered (<0 if inexistent or not reachable */ - picoos_uint8 lastPhraseType; /* phrase type of the last phrase boundary, 0 if not set */ - - picoos_uint8 needMoreInput, /* more data necessary to decide on token */ - suppressParseWordBound, /* dont produce word boundary */ - suppressRecombWordBound, /* dont produce word boundary */ - breakPending, /* received a break but didn't interpret it yet */ - /* sentEnd, */ /* sentence end detected */ - force, /* in forced state */ - wordStarted, /* is it the first syl in the word: expect POS */ - sentenceStarted; - - picoos_uint16 breakTime; /* time argument of the pending break command */ - - picoos_uint8 feedFollowState; /* where to return after feed */ - - /* fst knowledge bases */ - picoos_uint8 numFsts; - picokfst_FST fst[PICOKNOW_MAX_NUM_SPHO_FSTS]; - picoos_uint8 curFst; /* the fst to be applied next */ - - /* fixed ids knowledge base */ - picoktab_FixedIds fixedIds; - - /* phones kb */ - picoktab_Phones phones; - - /* some soecial ids from phones */ - picoos_uint8 primStressId, secondStressId, syllSepId; - -} spho_subobj_t; - - -static pico_status_t sphoReset(register picodata_ProcessingUnit this) -{ - - spho_subobj_t * spho; - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(this->common->em, - PICO_ERR_NULLPTR_ACCESS, NULL, NULL); - } - spho = (spho_subobj_t *) this->subObj; - - spho->curFst = 0; - -/* processing state */ - spho->procState = SPHO_STEPSTATE_INIT; - spho->needMoreInput = TRUE; - spho->suppressParseWordBound = FALSE; - spho->suppressRecombWordBound = FALSE; - spho->breakPending = FALSE; - spho->force = 0; - spho->sentenceStarted = 0; - - - /* item buffer headx/cbuf */ - spho->headxBufSize = SPHO_MAXNR_HEADX; - spho->headxReadPos = 0; - spho->headxWritePos = 0; - - spho->cbufWritePos = 0; - spho->cbufBufSize = SPHO_MAXSIZE_CBUF; - - /* possym buffer */ - spho->phonBuf = spho->phonBufA; - spho->phonBufOut = spho->phonBufB; - spho->phonReadPos = 0; - - /* overlapping */ - spho->activeStartPos = 0; - spho->penultima = SPHO_POS_INVALID; - spho->activeEndPos = SPHO_POS_INVALID; - - return PICO_OK; -} - - -static pico_status_t sphoInitialize(register picodata_ProcessingUnit this) -{ - picoos_uint8 i; - spho_subobj_t * spho; - picokfst_FST fst; - - picoknow_kb_id_t myKbIds[PICOKNOW_MAX_NUM_SPHO_FSTS] = PICOKNOW_KBID_SPHO_ARRAY; - - PICODBG_DEBUG(("init")); - - if (NULL == this || NULL == this->subObj) { - return picoos_emRaiseException(this->common->em, - PICO_ERR_NULLPTR_ACCESS, NULL, NULL); - } - - spho = (spho_subobj_t *) this->subObj; - - spho->numFsts = 0; - - spho->curFst = 0; - - for (i = 0; ivoice->kbArray[myKbIds[i]]); - if (NULL != fst) { - spho->fst[spho->numFsts++] = fst; - } - } - spho->fixedIds = picoktab_getFixedIds(this->voice->kbArray[PICOKNOW_KBID_FIXED_IDS]); - spho->phones = picoktab_getPhones(this->voice->kbArray[PICOKNOW_KBID_TAB_PHONES]); - - spho->syllSepId = picoktab_getSyllboundID(spho->phones); - spho->primStressId = picoktab_getPrimstressID(spho->phones); - spho->secondStressId = picoktab_getSecstressID(spho->phones); - - PICODBG_DEBUG(("got %i fsts", spho->numFsts)); - - - return sphoReset(this); - -} - -static picodata_step_result_t sphoStep(register picodata_ProcessingUnit this, - picoos_int16 mode, picoos_uint16 *numBytesOutput); - - - - -static pico_status_t sphoTerminate(register picodata_ProcessingUnit this) -{ - return PICO_OK; -} - - -static pico_status_t sphoSubObjDeallocate(register picodata_ProcessingUnit this, - picoos_MemoryManager mm) -{ - spho_subobj_t * spho; - - spho = (spho_subobj_t *) this->subObj; - - if (NULL != this) { - if (NULL != this->subObj) { - spho = (spho_subobj_t *) (this->subObj); - picotrns_deallocate_alt_desc_buf(spho->common->mm,&spho->altDescBuf); - picoos_deallocate(mm, (void *) &this->subObj); - } - } - return PICO_OK; -} - -picodata_ProcessingUnit picospho_newSentPhoUnit(picoos_MemoryManager mm, - picoos_Common common, picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, picorsrc_Voice voice) -{ - spho_subobj_t * spho; - - picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, cbOut, voice); - if (this == NULL) { - return NULL; - } - - this->initialize = sphoInitialize; - this->step = sphoStep; - this->terminate = sphoTerminate; - this->subDeallocate = sphoSubObjDeallocate; - - this->subObj = picoos_allocate(mm, sizeof(spho_subobj_t)); - if (this->subObj == NULL) { - picoos_deallocate(mm, (void **)(void*)&this); - return NULL; - } - spho = (spho_subobj_t *) this->subObj; - - spho->common = this->common; - - /* these are given by the pre-allocated array sizes */ - spho->outBufSize = PICODATA_BUFSIZE_DEFAULT; - - - spho->altDescBuf = picotrns_allocate_alt_desc_buf(spho->common->mm, SPHO_MAX_ALTDESC_SIZE, &spho->maxAltDescLen); - if (NULL == spho->altDescBuf) { - picotrns_deallocate_alt_desc_buf(spho->common->mm,&spho->altDescBuf); - picoos_emRaiseException(spho->common->em,PICO_EXC_OUT_OF_MEM, NULL,NULL); - return NULL; - } - - sphoInitialize(this); - return this; -} - - -/* ***********************************************************************/ -/* process buffered item list */ -/* ***********************************************************************/ - - -/* shift relevant data in headx/'cbuf' (between 'readPos' incl and writePos non-incl) to 'start'. - * modify read/writePos accordingly */ -static picoos_int16 shift_range_left_1(spho_subobj_t *spho, picoos_int16 * from, picoos_int16 to) -{ - - /* remember shift parameters for cbuf */ - picoos_uint16 - c_i, - c_j, - c_diff, - c_writePos, - i, - j, - diff, - writePos; - i = to; - j = *from; - diff = j-i; - writePos = spho->headxWritePos; - c_i = spho->headx[to].cind; - if (j < writePos) { - c_j = spho->headx[j].cind; - } else { - c_j = spho->cbufWritePos; - } - c_diff = c_j - c_i; - c_writePos = spho->cbufWritePos; - - PICODBG_DEBUG(( - "shifting buffer region [%i,%i[ down to %i",*from, writePos, to - )); - - - /* PICODBG_ASSERT((i j) { - return -1; - } - /* shift cbuf */ - while (c_j < c_writePos) { - spho->cbuf[c_i++] = spho->cbuf[c_j++]; - } - /* shift headx */ - while (j < writePos) { - spho->headx[j].cind -= c_diff; - spho->headx[i++] = spho->headx[j++]; - } - spho->headxWritePos -= diff; - *from = to; - spho->cbufWritePos -= c_diff; - /* */ - PICODBG_DEBUG(( - "readPos,WritePos are now [%i,%i[, returning shift amount %i",*from, spho->headxWritePos, diff - )); - return diff; -} - -static pico_status_t sphoAddPhoneme(register spho_subobj_t *spho, picoos_int16 pos, picoos_int16 sym) { - picoos_uint8 plane, unshifted; - /* just for debuging */ - unshifted = picotrns_unplane(sym,&plane); - PICODBG_TRACE(("adding %i/%i (%c on plane %i) at phonBuf[%i]",pos,sym,unshifted,plane,spho->phonWritePos)); - if (2* PICOTRNS_MAX_NUM_POSSYM <= spho->phonWritePos) { - /* not an error! */ - PICODBG_DEBUG(("couldn't add because phon buffer full")); - return PICO_EXC_BUF_OVERFLOW; - } else { - spho->phonBuf[spho->phonWritePos].pos = pos; - spho->phonBuf[spho->phonWritePos].sym = sym; - spho->phonWritePos++; - return PICO_OK; - } -} - -static pico_status_t sphoAddStartPhoneme(register spho_subobj_t *spho) { - return sphoAddPhoneme(spho, PICOTRNS_POS_IGNORE, - (PICOKFST_PLANE_INTERN << 8) + spho->fixedIds->phonStartId); -} - -static pico_status_t sphoAddTermPhonemes(register spho_subobj_t *spho, picoos_uint16 pos) { - return sphoAddPhoneme(spho, pos, - (PICOKFST_PLANE_PB_STRENGTHS << 8) + PICODATA_ITEMINFO1_BOUND_SEND) - && sphoAddPhoneme(spho, PICOTRNS_POS_IGNORE, - (PICOKFST_PLANE_INTERN << 8) + spho->fixedIds->phonTermId); -} - -/* return "syllable accent" (or prominence) symbol, given "word accent" symbol 'wacc' and stress value (no=0, primary=1, secondary=2) */ -static picoos_uint16 sphoGetSylAccent(register spho_subobj_t *spho, - picoos_uint8 wacc, picoos_uint8 sylStress) -{ - PICODBG_ASSERT(sylStress <= 2); - - spho = spho; /* avoid warning "var not used in this function"*/ - - switch (sylStress) { - case 0: /* non-stressed syllable gets no prominence */ - /* return spho->fixedIds->accId[0]; */ - return PICODATA_ACC0; - break; - case 1: /* primary-stressed syllable gets word prominence */ - return wacc; - break; - case 2: /* secondary-stressed syllable gets no prominence or secondary stress prom. (4) */ - return (PICODATA_ACC0 == wacc) ? PICODATA_ACC0 - : PICODATA_ACC4; - /*return (spho->fixedIds->accId[0] == wacc) ? spho->fixedIds->accId[0] - : spho->fixedIds->accId[4]; */ - break; - default: - /* never occurs :-) */ - return PICODATA_ACC0; - break; - } -} - - -/* ***********************************************************************/ -/* extract phonemes of an item into a phonBuf */ -/* ***********************************************************************/ -static pico_status_t sphoExtractPhonemes(register picodata_ProcessingUnit this, - register spho_subobj_t *spho, picoos_uint16 pos, - picoos_uint8 convertAccents, picoos_uint8 * suppressWB) -{ - pico_status_t rv = PICO_OK; - picoos_uint16 i, j; - picoos_int16 fstSymbol; - picoos_uint8 curStress; - picotrns_possym_t tmpPosSym; - picoos_uint16 oldPos, curPos; - picodata_itemhead_t * head; - picoos_uint8* content; - -#if defined(PICO_DEBUG) - picoos_char msgstr[SPHO_MSGSTR_SIZE]; -#endif - - - /* - Items considered in a transduction are a BOUND or a WORDPHON item. its starting offset within the - headxBuf is given as 'pos'. - Elements that go into the transduction receive "their" position in the buffer. - */ - - oldPos = spho->phonWritePos; - - head = &(spho->headx[pos].head); - content = spho->cbuf + spho->headx[pos].cind; - - PICODBG_TRACE(("doing item %s\n", - picodata_head_to_string(head,msgstr,SPHO_MSGSTR_SIZE))); - - switch (head->type) { - case PICODATA_ITEM_BOUND: - /* map SBEG, SEND and TERM (as sentence closing) to SEND */ - fstSymbol = (PICODATA_ITEMINFO1_BOUND_SBEG == head->info1 || PICODATA_ITEMINFO1_BOUND_TERM == head->info1) ? PICODATA_ITEMINFO1_BOUND_SEND : head->info1; - PICODBG_TRACE(("found bound of type %c\n",head->info1)); - /* BOUND() */ - /* insert bound strength */ - PICODBG_TRACE(("inserting phrase bound phoneme %c and setting suppresWB=1\n",fstSymbol)); - fstSymbol += (PICOKFST_PLANE_PB_STRENGTHS << 8); - rv = sphoAddPhoneme(spho,pos,fstSymbol); - /* phrase type not used */ - /* suppress next word boundary */ - (*suppressWB) = 1; - break; - - case PICODATA_ITEM_WORDPHON: - /* WORDPHON(POS,WACC)phon */ - PICODBG_TRACE(("found WORDPHON")); - /* insert word boundary if not suppressed */ - if (!(*suppressWB)) { - fstSymbol = (PICOKFST_PLANE_PB_STRENGTHS << 8) + PICODATA_ITEMINFO1_BOUND_PHR0; - PICODBG_TRACE(("adding word boundary phone")); - rv = sphoAddPhoneme(spho,pos,fstSymbol); - } - (*suppressWB) = 0; - /* for the time being, we force to use POS so we can transduce all fsts in a row without reconsulting the items */ - - - /* If 'convertAccents' then the accentuation is not directly encoded. It rather influences the mapping of - * the word accent symbol to the actual accent phoneme which is put after the syllable separator. */ - if (convertAccents) { - PICODBG_TRACE(("converting accents")); - /* extracting phonemes IN REVERSE order replacing syllable symbols with prominence symbols */ - curPos = spho->phonWritePos; - curStress = 0; /* no stress */ - for (i = head->len; i > 0 ;) { - i--; - if (spho->primStressId == content[i]) { - curStress = 1; - PICODBG_DEBUG(("skipping primary stress at pos %i (in 1 .. %i)",i, head->len)); - continue; /* skip primary stress symbol */ - } else if (spho->secondStressId == content[i]) { - curStress = 2; - PICODBG_DEBUG(("skipping secondary stress at pos %i (in 1 .. %i)",i, head->len)); - continue; /* skip secundary stress symbol */ - } else if (spho->syllSepId == content[i]) { - fstSymbol = (PICOKFST_PLANE_POS << 8) + head->info1; - rv = sphoAddPhoneme(spho, pos, fstSymbol); - /* replace syllSepId by combination of syllable stress and word prominence */ - fstSymbol = sphoGetSylAccent(spho,head->info2,curStress); - curStress = 0; - /* add accent */ - fstSymbol += (PICOKFST_PLANE_ACCENTS << 8); - rv = sphoAddPhoneme(spho,pos,fstSymbol); - if (PICO_OK != rv) { - break; - } - /* and keep syllable boundary */ - fstSymbol = (PICOKFST_PLANE_PHONEMES << 8) + content[i]; - } else { - /* normal phoneme */ - fstSymbol = (PICOKFST_PLANE_PHONEMES << 8) + content[i]; - } - if (PICO_OK == rv) { - rv = sphoAddPhoneme(spho,pos,fstSymbol); - } - } - if (PICO_OK == rv) { - /* bug 366: we position the "head" into the item header and not on the first phoneme - * because there might be no phonemes at all */ - /* insert head of the first syllable of a word */ - fstSymbol = (PICOKFST_PLANE_POS << 8) + head->info1; - rv = sphoAddPhoneme(spho,pos,fstSymbol); - fstSymbol = sphoGetSylAccent(spho,head->info2,curStress); - curStress = 0; - fstSymbol += (PICOKFST_PLANE_ACCENTS << 8); - rv = sphoAddPhoneme(spho,pos,fstSymbol); - } - if (PICO_OK == rv) { - /* invert sympos portion */ - i = curPos; - j=spho->phonWritePos-1; - while (i < j) { - tmpPosSym.pos = spho->phonBuf[i].pos; - tmpPosSym.sym = spho->phonBuf[i].sym; - spho->phonBuf[i].pos = spho->phonBuf[j].pos; - spho->phonBuf[i].sym = spho->phonBuf[j].sym; - spho->phonBuf[j].pos = tmpPosSym.pos; - spho->phonBuf[j].sym = tmpPosSym.sym; - i++; - j--; - } - } - } else { /* convertAccents */ - for (i = 0; i len; i++) { - fstSymbol = (PICOKFST_PLANE_PHONEMES << 8) + content[i]; - rv = sphoAddPhoneme(spho,pos,fstSymbol); - } - } - break; - default: - picoos_emRaiseException(this->common->em,rv,NULL,NULL); - break; - } /* switch(head->type) */ - if (PICO_OK != rv) { - spho->phonWritePos = oldPos; - } - return rv; -} - - - - - -#define SPHO_POSSYM_OK 0 -#define SPHO_POSSYM_OUT_OF_RANGE 1 -#define SPHO_POSSYM_END 2 -#define SPHO_POSSYM_INVALID -3 -/* *readPos is the next position in phonBuf to be read, and *writePos is the first position not to be read (may be outside - * buf). - * 'rangeEnd' is the first possym position outside the desired range. - * Possible return values: - * SPHO_POSSYM_OK : 'pos' and 'sym' are set to the read possym, *readPos is advanced - * SPHO_POSSYM_OUT_OF_RANGE : pos is out of range. 'pos' is set to that of the read possym, 'sym' is undefined - * SPHO_POSSYM_UNDERFLOW : no more data in buf. 'pos' is set to PICOTRNS_POS_INVALID, 'sym' is undefined - * SPHO_POSSYM_INVALID : "strange" pos. 'pos' is set to PICOTRNS_POS_INVALID, 'sym' is undefined - */ -static pico_status_t getNextPosSym(spho_subobj_t * spho, picoos_int16 * pos, picoos_int16 * sym, - picoos_int16 rangeEnd) { - /* skip POS_IGNORE */ - while ((spho->phonReadPos < spho->phonWritePos) && (PICOTRNS_POS_IGNORE == spho->phonBuf[spho->phonReadPos].pos)) { - PICODBG_DEBUG(("ignoring phone at spho->phonBuf[%i] because it has pos==IGNORE",spho->phonReadPos)); - spho->phonReadPos++; - } - if ((spho->phonReadPos < spho->phonWritePos)) { - *pos = spho->phonBuf[spho->phonReadPos].pos; - if ((PICOTRNS_POS_INSERT == *pos) || ((0 <= *pos) && (*pos < rangeEnd))) { - *sym = spho->phonBuf[spho->phonReadPos++].sym; - return SPHO_POSSYM_OK; - } else if (*pos < 0){ /* *pos is "strange" (e.g. POS_INVALID) */ - return SPHO_POSSYM_INVALID; - } else { - return SPHO_POSSYM_OUT_OF_RANGE; - } - } else { - /* no more possyms to read */ - *pos = PICOTRNS_POS_INVALID; - return SPHO_POSSYM_END; - } -} - - - -/** Calculate bound strength modified by transduction - * - * Given the original bound strength 'orig' and the desired target strength 'target' (suggested by fst), - * calculate the modified bound strength. - * - * @param orig original bound strength - * @param target target bound strength - * @return resulting bound strength - */ -static picoos_uint8 fstModifiedBoundStrength(picoos_uint8 orig, picoos_uint8 target) -{ - switch (orig) { - case PICODATA_ITEMINFO1_BOUND_PHR1: - case PICODATA_ITEMINFO1_BOUND_PHR2: - /* don't allow primary phrase bounds to be demoted to word bound */ - if (PICODATA_ITEMINFO1_BOUND_PHR0 == target) { - return PICODATA_ITEMINFO1_BOUND_PHR3; - } - case PICODATA_ITEMINFO1_BOUND_PHR0: - case PICODATA_ITEMINFO1_BOUND_PHR3: - return target; - break; - default: - /* don't allow bounds other than phrase or word bounds to be changed */ - return orig; - break; - } -} - -/** Calculate bound strength modified by a \ command - * - * Given the original (predicted and possibly fst-modified) bound strength, and a time value from an - * overwriding \ command, calculate the modified bound strength. - * - * @param orig original bound strength - * @param time time given as property of \ command - * @param wasPrimary - * @return modified bound strength - */ -static picoos_uint8 breakModifiedBoundStrength(picoos_uint8 orig, picoos_uint16 time, picoos_bool wasPrimary) -{ - picoos_uint8 modified = (0 == time) ? PICODATA_ITEMINFO1_BOUND_PHR3 : - (50 < time) ? PICODATA_ITEMINFO1_BOUND_PHR1 : PICODATA_ITEMINFO1_BOUND_PHR2; - switch (orig) { - /* for word and phrase breaks, return 'modified', unless a non-silence gets time==0, in which - * case return no break (word break) */ - case PICODATA_ITEMINFO1_BOUND_PHR0: - if (0 == time) { - return PICODATA_ITEMINFO1_BOUND_PHR0; - } - case PICODATA_ITEMINFO1_BOUND_PHR3: - if (!wasPrimary && (0 == time)) { - return PICODATA_ITEMINFO1_BOUND_PHR0; - } - case PICODATA_ITEMINFO1_BOUND_PHR1: - case PICODATA_ITEMINFO1_BOUND_PHR2: - return modified; - break; - default: - return orig; - break; - } -} - -static picoos_bool breakStateInterrupting(picodata_itemhead_t * head, - picoos_bool * breakBefore, picoos_bool * breakAfter) { - - picoos_bool result = 1; - - *breakBefore = 0; - *breakAfter = 0; - - if (PICODATA_ITEM_WORDPHON == head->type) { - - } else if (PICODATA_ITEM_CMD == head->type) { - if ((PICODATA_ITEMINFO1_CMD_PLAY == head->info1) - || (PICODATA_ITEMINFO1_CMD_SAVE == head->info1) - || (PICODATA_ITEMINFO1_CMD_UNSAVE == head->info1)) { - *breakBefore = 1; - *breakAfter = 1; - } else if (PICODATA_ITEMINFO1_CMD_SAVE == head->info1) { - *breakBefore = 1; - } else if (PICODATA_ITEMINFO1_CMD_UNSAVE == head->info1) { - *breakAfter = 1; - } else if (PICODATA_ITEMINFO1_CMD_IGNSIG == head->info1) { - if (PICODATA_ITEMINFO2_CMD_START == head->info2) { - *breakBefore = 1; - } else { - *breakAfter = 1; - } - } - } else { - result = 0; - } - return result; -} - - -static void putSideBoundToOutput(spho_subobj_t * spho) -{ - - picodata_itemhead_t ohead; - picoos_uint8 ocontent[2*sizeof(picoos_uint16)]; - picoos_int16 sildur; - picoos_uint16 clen; - - /* create boundary */ - ohead.type = PICODATA_ITEM_BOUND; - ohead.info1 = spho->headx[spho->outReadPos].boundstrength; - ohead.info2 = spho->headx[spho->outReadPos].phrasetype; - sildur = spho->headx[spho->outReadPos].sildur; - if ((sildur < 0) - || (PICODATA_ITEMINFO1_BOUND_PHR0 == ohead.info1) - || (PICODATA_ITEMINFO1_BOUND_PHR3 == ohead.info1)) { - PICODBG_DEBUG(("outputting a bound of strength '%c' and type '%c' without duration constraints",ohead.info1, ohead.info2)); - ohead.len = 0; - } else { - picoos_uint32 pos = 0; - picoos_write_mem_pi_uint16(ocontent,&pos,sildur); - picoos_write_mem_pi_uint16(ocontent,&pos,sildur); - PICODBG_DEBUG(("outputting a bound of strength '%c' and type '%c' with duration constraints [%i,%i]",ohead.info1, ohead.info2,sildur, sildur)); - ohead.len = pos; - } - picodata_put_itemparts(&ohead, ocontent, ohead.len, - spho->outBuf, spho->outBufSize, &clen); - /* disable side bound */ - spho->headx[spho->outReadPos].boundstrength = 0; -} - -/** Set bound strength and sil dur. - * - * given the original bound strength 'orig_strength' and the fst-suggested bound strength 'fst_strength' - * and possibly being in a pending break state, calculate the resulting bound strength and set boundstrength - * and sildur of the current item (spho->headx[spho->outReadPos]) accordingly. - * if a boundstrength was set, also calculate the phrasetype and if necessary (and reachable), modify the phrase type - * of the previous phrase boundary. - * - * @param spho - * @param orig_strength - * @param orig_type - * @param fst_strength - */ -static void setSideBound(spho_subobj_t * spho, picoos_uint8 orig_strength, picoos_uint8 orig_type, picoos_uint8 fst_strength) { - picoos_uint8 strength; - - /* insert modified bound according to transduction symbol, if any */ - if (PICODATA_ITEMINFO1_NA == orig_strength) { - /* no original/fst strength given */ - orig_strength = PICODATA_ITEMINFO1_BOUND_PHR0; - strength = PICODATA_ITEMINFO1_BOUND_PHR0; - } else { - strength = fstModifiedBoundStrength(orig_strength,fst_strength); - spho->headx[spho->outReadPos].boundstrength = strength; - spho->headx[spho->outReadPos].sildur = -1; - PICODBG_DEBUG(("setting bound strength to fst-suggested value %c (was %c)",strength, spho->headx[spho->outReadPos].boundstrength, spho->breakTime)); - } - - /* insert modified bound according to pending break, if any */ - if (spho->breakPending) { - /* the calculation is based on the fst-modified value (because this is what the customer wants to - * override) - */ - strength = breakModifiedBoundStrength(strength, spho->breakTime, (PICODATA_ITEMINFO1_BOUND_PHR1 == orig_strength)); - PICODBG_DEBUG(("setting bound strength to break-imposed value %c (was %c) and time to %i",strength, spho->headx[spho->outReadPos].boundstrength, spho->breakTime)); - spho->headx[spho->outReadPos].boundstrength = strength; - spho->headx[spho->outReadPos].sildur = spho->breakTime; - spho->breakPending = FALSE; - } - if (spho->headx[spho->outReadPos].boundstrength) { - /* we did set a bound strength, possibly promoting or demoting a boundary; now set the phrase type - * possibly also changing the phrase type of the previous phrase bound - */ - picoos_uint8 fromPhrase = ((PICODATA_ITEMINFO1_BOUND_PHR0 != orig_strength)); - picoos_uint8 toPhrase = ((PICODATA_ITEMINFO1_BOUND_PHR0 != strength)); - - PICODBG_DEBUG(("setting phrase type (wasPhrase=%i, isPhrase=%i)",fromPhrase,toPhrase)); - if (toPhrase) { - if (fromPhrase) { - spho->lastPhraseType = orig_type; - } else { /*promote */ - if (spho->activeStartPos <= spho->lastPhraseBoundPos) { - /* we still can change prev phrase bound */ - /* since a new phrase boundary is introduced, we have to 'invent' - * an additional phrase type here. For that, we have to use some of the - * knowledge that otherwise is handled in picoacph. - */ - spho->headx[spho->lastPhraseBoundPos].phrasetype - = PICODATA_ITEMINFO2_BOUNDTYPE_P; - } - } - spho->lastPhraseBoundPos = spho->outReadPos; - spho->headx[spho->lastPhraseBoundPos].phrasetype - = spho->lastPhraseType; - - } else { - spho->headx[spho->outReadPos].phrasetype = PICODATA_ITEMINFO2_NA; - if (fromPhrase) { /* demote */ - spho->lastPhraseType = orig_type; - if (spho->activeStartPos <= spho->lastPhraseBoundPos) { - /* we still can change prev phrase bound */ - spho->headx[spho->lastPhraseBoundPos].phrasetype - = spho->lastPhraseType; - } - } - } - } -} - - -/* ***********************************************************************/ -/* sphoStep function */ -/* ***********************************************************************/ - - -static picodata_step_result_t sphoStep(register picodata_ProcessingUnit this, - picoos_int16 mode, picoos_uint16 * numBytesOutput) -{ - - register spho_subobj_t *spho; - pico_status_t rv= PICO_OK; - picoos_uint16 blen; - picodata_itemhead_t ihead, ohead; - picoos_uint8 *icontent; - picoos_uint16 nextInPos; -#if defined(PICO_DEBUG) - picoos_char msgstr[SPHO_MSGSTR_SIZE]; -#endif - - /* used in FEED and FEED_SYM */ - picoos_uint16 clen; - picoos_int16 pos, sym, sylsym; - picoos_uint8 plane; - - /* used in BOUNDS */ - picoos_bool breakBefore, breakAfter; - - /* pico_status_t rvP= PICO_OK; */ - - picoos_uint16 curPos /*, nextPos */; - picoos_uint16 remHeadxSize, remCbufSize; - - - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - spho = (spho_subobj_t *) this->subObj; - - mode = mode; /* avoid warning "var not used in this function"*/ - - *numBytesOutput = 0; - while (1) { /* exit via return */ - PICODBG_INFO(("doing state %i, headxReadPos: %d, headxWritePos: %d", - spho->procState, spho->headxReadPos, spho->headxWritePos)); - - switch (spho->procState) { - - case SPHO_STEPSTATE_INIT: - /* **********************************************************************/ - /* INIT */ - /* **********************************************************************/ - PICODBG_DEBUG(("INIT")); - /* (re)set values for PARSE */ - spho->penultima = SPHO_POS_INVALID; - spho->activeEndPos = SPHO_POS_INVALID; - spho->headxReadPos = 0; - spho->phonReadPos = 0; - spho->phonWritePos = 0; - spho->lastPhraseType = PICODATA_ITEMINFO2_NA; - spho->lastPhraseBoundPos = -1; - - spho->procState = SPHO_STEPSTATE_COLLECT; - break; - - - case SPHO_STEPSTATE_COLLECT: - /* **********************************************************************/ - /* COLLECT */ - /* **********************************************************************/ - /* collect state: get items from charBuf and store in - * internal inBuf - */ - PICODBG_TRACE(("COLLECT")); - rv = PICO_OK; - remHeadxSize = spho->headxBufSize - spho->headxWritePos; - remCbufSize = spho->cbufBufSize - spho->cbufWritePos; - curPos = spho->headxWritePos; - while ((PICO_OK == rv) && (remHeadxSize > 0) && (remCbufSize > 0)) { - PICODBG_DEBUG(("COLLECT getting item at headxWritePos %i (remaining %i)",spho->headxWritePos, remHeadxSize)); - rv = picodata_cbGetItem(this->cbIn, spho->tmpbuf, PICODATA_MAX_ITEMSIZE, &blen); - if (PICO_OK == rv) { - rv = picodata_get_itemparts(spho->tmpbuf, - PICODATA_MAX_ITEMSIZE, &(spho->headx[spho->headxWritePos].head), - &(spho->cbuf[spho->cbufWritePos]), remCbufSize, &blen); - if (PICO_OK == rv) { - spho->headx[spho->headxWritePos].cind = spho->cbufWritePos; - spho->headx[spho->headxWritePos].boundstrength = 0; - spho->headxWritePos++; - remHeadxSize--; - spho->cbufWritePos += blen; - remCbufSize -= blen; - } - } - } - if ((PICO_OK == rv) && ((remHeadxSize <= 0) || (remCbufSize <= 0))) { - rv = PICO_EXC_BUF_OVERFLOW; - } - - /* in normal circumstances, rv is either PICO_EOF (no more items in cbIn) or PICO_BUF_OVERFLOW - * (if no more items fit into headx) */ - if ((PICO_EOF != rv) && (PICO_EXC_BUF_OVERFLOW != rv)) { - PICODBG_DEBUG(("COLLECT ** problem getting item, unhandled, rv: %i", rv)); - picoos_emRaiseException(this->common->em, rv, - NULL, NULL); - return PICODATA_PU_ERROR; - } - if (PICO_EOF == rv) { /* there are no more items available */ - if (curPos < spho->headxWritePos) { /* we did get some new items */ - PICODBG_DEBUG(("COLLECT read %i items", - spho->headxWritePos - curPos)); - spho->needMoreInput = FALSE; - } - if (spho->needMoreInput) { /* not enough items to proceed */ - PICODBG_DEBUG(("COLLECT need more data, returning IDLE")); - return PICODATA_PU_IDLE; - } else { - spho->procState = SPHO_STEPSTATE_PROCESS_PARSE; - /* uncomment next to split into two steps */ - /* return PICODATA_PU_ATOMIC; */ - } - } else { /* input buffer full */ - PICODBG_DEBUG(("COLLECT input buffer full")); - if (spho->needMoreInput) { /* forced output because we can't get more data */ - spho->needMoreInput = FALSE; - spho->force = TRUE; - } - spho->procState = SPHO_STEPSTATE_PROCESS_PARSE; - } - break; - - case SPHO_STEPSTATE_PROCESS_PARSE: - - /* **********************************************************************/ - /* PARSE: items -> input pos/phon pairs */ - /* **********************************************************************/ - - /* parse one item at a time */ - /* If - * - the item is a sentence end or - * - it is the last item and force=1 or - * - the phon buffer is full - * then set inReadPos to 0 and go to TRANSDUCE - * else advance by one item */ - - /* look at the current item */ - PICODBG_TRACE(("PARSE")); - if (spho->headxReadPos >= spho->headxWritePos) { - /* no more items in headx */ - if (spho->force) { - PICODBG_INFO(("no more items in headx but we are forced to transduce")); - - /* headx is full; we are forced to transduce before reaching the sentence end */ - spho->force = FALSE; - if (SPHO_POS_INVALID == spho->activeEndPos) { - spho->activeEndPos = spho->headxReadPos; - } - spho->procState = SPHO_STEPSTATE_PROCESS_TRANSDUCE; - } else { - /* we try to get more data */ - PICODBG_INFO(("no more items in headx, try to collect more")); - spho->needMoreInput = TRUE; - spho->procState = SPHO_STEPSTATE_COLLECT; - } - break; - } - - ihead = spho->headx[spho->headxReadPos].head; - icontent = spho->cbuf + spho->headx[spho->headxReadPos].cind; - - PICODBG_DEBUG(("PARSE looking at item %s",picodata_head_to_string(&ihead,msgstr,SPHO_MSGSTR_SIZE))); - /* treat header */ - if (PICODATA_ITEM_BOUND == ihead.type) { - /* see if it is a sentence end or termination boundary (flush) */ - if ((PICODATA_ITEMINFO1_BOUND_SEND == ihead.info1) - || (PICODATA_ITEMINFO1_BOUND_TERM == ihead.info1)) { - PICODBG_INFO(("PARSE found sentence end or term BOUND")); - - if (spho->sentenceStarted) { - /* its the end of the sentence */ - PICODBG_INFO(("PARSE found sentence end")); - spho->sentenceStarted = 0; - /* there is no need for a right context; move the active end to the end */ - /* add sentence termination phonemes */ - sphoAddTermPhonemes(spho, spho->headxReadPos); - spho->headxReadPos++; - spho->activeEndPos = spho->headxReadPos; - /* we may discard all information up to activeEndPos, after processing of last - * sentence part - */ - spho->penultima = spho->activeEndPos; - - /* transduce */ - spho->procState = SPHO_STEPSTATE_PROCESS_TRANSDUCE; - /* uncomment to split */ - /* return PICODATA_PU_BUSY; */ - break; - } else { - if (PICODATA_ITEMINFO1_BOUND_TERM == ihead.info1) { - /* its the end of input (flush) */ - PICODBG_INFO(("PARSE forwarding input end (flush)")); - /* copy item unmodified */ - picodata_put_itemparts(&ihead, - icontent, - ihead.len, - spho->outBuf, spho->outBufSize, - &clen); - - spho->headxReadPos++; - spho->activeEndPos = spho->headxReadPos; - spho->penultima = SPHO_POS_INVALID; - spho->feedFollowState = SPHO_STEPSTATE_SHIFT; - spho->procState = SPHO_STEPSTATE_FEED; - break; - } else { - /* this should never happen */ - /* eliminate bound */ - spho->headxReadPos++; - spho->activeEndPos = spho->headxReadPos; - spho->penultima = SPHO_POS_INVALID; - PICODBG_ERROR(("PARSE found a sentence end without a sentence start; eliminated")); - } - } - } else if (PICODATA_ITEMINFO1_BOUND_SBEG == ihead.info1) { - /* its the start of the sentence */ - PICODBG_INFO(("PARSE found sentence start")); - /* add sentence starting phoneme */ - sphoAddStartPhoneme(spho); - - spho->sentenceStarted = 1; - } - } - - if ((PICODATA_ITEM_WORDPHON == ihead.type) - || (PICODATA_ITEM_BOUND == ihead.type)) { - /* if it is a word or a bound try to extract phonemes */ - PICODBG_INFO(("PARSE found WORD phon or phrase BOUND")); - rv = sphoExtractPhonemes(this, spho, spho->headxReadPos, - TRUE /* convertAccents */, - &spho->suppressParseWordBound); - if (PICO_OK == rv) { - PICODBG_INFO(("PARSE successfully returned from phoneme extraction")); - /* replace activeEndPos if the new item is a word, or activeEndPos was not set yet, or - * activeEndPos was a bound */ - if ((spho->activeStartPos <= spho->headxReadPos) && ((PICODATA_ITEM_WORDPHON == ihead.type) - || (SPHO_POS_INVALID == spho->activeEndPos) - || (PICODATA_ITEM_BOUND == spho->headx[spho->activeEndPos].head.type))) { - PICODBG_INFO(("PARSE found new activeEndPos: %i,%i -> %i,%i", - spho->penultima,spho->activeEndPos,spho->activeEndPos,spho->headxReadPos)); - spho->penultima = spho->activeEndPos; - spho->activeEndPos = spho->headxReadPos; - } - - } else if (PICO_EXC_BUF_OVERFLOW == rv) { - /* phoneme buffer cannot take this item anymore; - if the phoneme buffer has some contents, we are forced to transduce before reaching the sentence end - else we skip the (too long word) */ - PICODBG_INFO(("PARSE returned from phoneme extraction with overflow, number of phonemes in phonBuf: %i; forced to TRANSDUCE", spho->phonWritePos)); - if ((SPHO_POS_INVALID == spho->activeEndPos) || (spho->activeStartPos == spho->activeEndPos)) { - spho->activeEndPos = spho->headxReadPos; - } - spho->procState = SPHO_STEPSTATE_PROCESS_TRANSDUCE; - break; - } else { - PICODBG_ERROR(("PARSE returned from phoneme extraction with exception %i",rv)); - return (picodata_step_result_t)picoos_emRaiseException(this->common->em, - PICO_ERR_OTHER, NULL, NULL); - } - } else { - PICODBG_INFO(("PARSE found other item, passing over")); - /* it is "other" item, ignore */ - } - /* set pos at next item */ - PICODBG_INFO(("PARSE going to next item: %i -> %i",spho->headxReadPos, spho->headxReadPos + 1)); - spho->headxReadPos++; - break; - - case SPHO_STEPSTATE_PROCESS_TRANSDUCE: - - /* **********************************************************************/ - /* TRANSDUCE: transduction input pos/phon pairs to output pos/phon pairs */ - /* **********************************************************************/ - PICODBG_DEBUG(("TRANSDUCE (%i-th of %i fsts",spho->curFst+1, spho->numFsts)); - - /* termination condition first */ - if (spho->curFst >= spho->numFsts) { - -#if defined(PICO_DEBUG) - { - PICODBG_INFO_CTX(); - PICODBG_INFO_MSG(("result of all transductions: ")); - PICOTRNS_PRINTSYMSEQ(this->voice->kbArray[PICOKNOW_KBID_DBG], spho->phonBufOut, spho->phonWritePos); - PICODBG_INFO_MSG(("\n")); - } -#endif - - /* reset for next transduction */ - spho->curFst = 0; - /* prepare BOUNDS */ - spho->outReadPos = 0; - spho->phonReadPos = 0; - - spho->procState = SPHO_STEPSTATE_PROCESS_BOUNDS; - break; - } - - /* transduce from phonBufIn to PhonBufOut */ - { - - picoos_uint32 nrSteps; -#if defined(PICO_DEBUG) - { - PICODBG_INFO_CTX(); - PICODBG_INFO_MSG(("spho trying to transduce: ")); - PICOTRNS_PRINTSYMSEQ(this->voice->kbArray[PICOKNOW_KBID_DBG], spho->phonBuf, spho->phonWritePos); - PICODBG_INFO_MSG(("\n")); - } -#endif - rv = picotrns_transduce(spho->fst[spho->curFst], FALSE, - picotrns_printSolution, spho->phonBuf, spho->phonWritePos, spho->phonBufOut, - &spho->phonWritePos, - 4*PICOTRNS_MAX_NUM_POSSYM, spho->altDescBuf, - spho->maxAltDescLen, &nrSteps); - if (PICO_OK == rv) { -#if defined(PICO_DEBUG) - { - PICODBG_INFO_CTX(); - PICODBG_INFO_MSG(("result of transduction: (output symbols: %i)", spho->phonWritePos)); - PICOTRNS_PRINTSYMSEQ(this->voice->kbArray[PICOKNOW_KBID_DBG], spho->phonBufOut, spho->phonWritePos); - PICODBG_INFO_MSG(("\n")); - } -#endif - PICODBG_TRACE(("number of steps done in tranduction: %i", nrSteps)); - } else { - picoos_emRaiseWarning(this->common->em, PICO_WARN_FALLBACK,NULL,(picoos_char *)"phon buffer full"); - } - } - /* eliminate deep epsilons */ - picotrns_eliminate_epsilons(spho->phonBufOut, spho->phonWritePos, spho->phonBuf, - &spho->phonWritePos,4*PICOTRNS_MAX_NUM_POSSYM); - - spho->curFst++; - - /* return PICODATA_PU_ATOMIC */ - break; - - - case SPHO_STEPSTATE_PROCESS_BOUNDS: - /* ************************************************************************/ - /* BOUNDS: combine input item with pos/phon pairs to insert/modify bounds */ - /* ************************************************************************/ - - PICODBG_INFO(("BOUNDS")); - - /* get the suppressRecombWordBound in the left context */ - spho->suppressRecombWordBound = FALSE; - while (spho->outReadPos < spho->activeStartPos) { - /* look at the current item */ - ihead = spho->headx[spho->outReadPos].head; - /* icontent = spho->cbuf + spho->headx[spho->outReadPos].cind; */ - PICODBG_INFO(("in position %i, looking at item %s",spho->outReadPos,picodata_head_to_string(&ihead,msgstr,SPHO_MSGSTR_SIZE))); - if (PICODATA_ITEM_BOUND == ihead.type) { - spho->suppressRecombWordBound = TRUE; - } else if (PICODATA_ITEM_WORDPHON == ihead.type) { - spho->suppressRecombWordBound = FALSE; - } - spho->outReadPos++; - } - /* spho->outReadPos point now to the active region */ - - /* advance the phone reading pos to the active range */ - spho->phonReadPos = 0; - while (SPHO_POSSYM_OK == (rv = getNextPosSym(spho, &pos, &sym, - spho->activeStartPos))) { - /* ignore */ - } - PICODBG_INFO(("skipping left context phones results in %s", (SPHO_POSSYM_OUT_OF_RANGE==rv) ? "OUT_OF_RANGE" : (SPHO_POSSYM_END ==rv) ? "END" : "OTHER")); - - /* - * Align input items with transduced phones and note bound stregth changes and break commands - */ - - while (spho->outReadPos < spho->activeEndPos) { - - /* look at the current item */ - ihead = spho->headx[spho->outReadPos].head; - icontent = spho->cbuf + spho->headx[spho->outReadPos].cind; - nextInPos = spho->outReadPos + 1; - /* */ - PICODBG_INFO(("in position %i, looking at item %s",spho->outReadPos,picodata_head_to_string(&ihead,msgstr,SPHO_MSGSTR_SIZE))); - - if ((PICODATA_ITEM_BOUND == ihead.type) - || ((PICODATA_ITEM_WORDPHON == ihead.type) - && (!spho->suppressRecombWordBound))) { - /* there was a boundary originally */ - picoos_uint8 orig_strength, orig_type; - if (PICODATA_ITEM_BOUND == ihead.type) { - orig_strength = ihead.info1; - orig_type = ihead.info2; - spho->suppressRecombWordBound = TRUE; - } else { - orig_strength = PICODATA_ITEMINFO1_BOUND_PHR0; - orig_type = PICODATA_ITEMINFO2_NA; - } - /* i expect a boundary phone here */ - /* consume FST bound phones, consider pending break and set the side-bound */ - PICODBG_INFO(("got BOUND or WORDPHON item and expects corresponding phone")); - rv = getNextPosSym(spho, &pos, &sym, nextInPos); - if (SPHO_POSSYM_OK != rv) { - PICODBG_ERROR(("unexpected symbol or unexpected end of phoneme list (%s)", (SPHO_POSSYM_OUT_OF_RANGE==rv) ? "OUT_OF_RANGE" : (SPHO_POSSYM_END ==rv) ? "END" :"OTHER")); - return (picodata_step_result_t)picoos_emRaiseException(this->common->em, - PICO_ERR_OTHER, NULL, NULL); - } - sym = picotrns_unplane(sym, &plane); - /* */ - PICODBG_ASSERT((PICOKFST_PLANE_PB_STRENGTHS == plane)); - - /* insert modified bound according to transduction and possibly pending break */ - setSideBound(spho, orig_strength, orig_type, - (picoos_uint8) sym); - } else if ((PICODATA_ITEM_CMD == ihead.type) - && (PICODATA_ITEMINFO1_CMD_SIL == ihead.info1)) { - /* it's a SIL (break) command */ - picoos_uint16 time; - picoos_uint32 pos = 0; - picoos_read_mem_pi_uint16(icontent, &pos, &time); - if (spho->breakPending) { - spho->breakTime += time; - } else { - spho->breakTime = time; - spho->breakPending = TRUE; - } - } else if ((PICODATA_ITEM_CMD == ihead.type) && (PICODATA_ITEMINFO1_CMD_PLAY == ihead.info1)) { - /* insert break of at least one ms */ - if (!spho->breakPending || (spho->breakTime <= 0)) { - spho->breakTime = SPHO_SMALLEST_SIL_DUR; - spho->breakPending = TRUE; - } - setSideBound(spho, PICODATA_ITEMINFO1_NA, - PICODATA_ITEMINFO2_NA, PICODATA_ITEMINFO1_NA); - /* force following break to be at least one ms */ - spho->breakTime = SPHO_SMALLEST_SIL_DUR; - spho->breakPending = TRUE; - } else if (breakStateInterrupting(&ihead, &breakBefore, &breakAfter)) { - - if (breakBefore &&(!spho->breakPending || (spho->breakTime <= 0))) { - spho->breakTime = SPHO_SMALLEST_SIL_DUR; - spho->breakPending = TRUE; - } - setSideBound(spho, PICODATA_ITEMINFO1_NA, - PICODATA_ITEMINFO2_NA, PICODATA_ITEMINFO1_NA); - - if (breakAfter) { - spho->breakTime = SPHO_SMALLEST_SIL_DUR; - spho->breakPending = TRUE; - } - if (PICODATA_ITEM_WORDPHON == ihead.type) { - spho->suppressRecombWordBound = FALSE; - } - } - - /* skip phones of that item */ - while (SPHO_POSSYM_OK == (rv = getNextPosSym(spho, &pos, - &sym, nextInPos))) { - /* ignore */ - } - spho->outReadPos++; - } - - /* reset for RECOMB */ - spho->outReadPos = 0; - spho->phonReadPos = 0; - spho->suppressRecombWordBound = FALSE; - - spho->procState = SPHO_STEPSTATE_PROCESS_RECOMB; - return PICODATA_PU_ATOMIC; - - break; - - case SPHO_STEPSTATE_PROCESS_RECOMB: - /* **********************************************************************/ - /* RECOMB: combine input item with pos/phon pairs to output item */ - /* **********************************************************************/ - - PICODBG_TRACE(("RECOMB")); - - /* default place to come after feed: here */ - spho->feedFollowState = SPHO_STEPSTATE_PROCESS_RECOMB; - - /* check termination condition first */ - if (spho->outReadPos >= spho->activeEndPos) { - PICODBG_DEBUG(("RECOMB reached active region's end at %i",spho->outReadPos)); - spho->procState = SPHO_STEPSTATE_SHIFT; - break; - } - - /* look at the current item */ - ihead = spho->headx[spho->outReadPos].head; - icontent = spho->cbuf + spho->headx[spho->outReadPos].cind; - - PICODBG_DEBUG(("RECOMB looking at item %s",picodata_head_to_string(&ihead,msgstr,SPHO_MSGSTR_SIZE))); - - nextInPos = spho->outReadPos + 1; - - PICODBG_DEBUG(("RECOMB treating item in headx at pos %i",spho->outReadPos)); - if (nextInPos <= spho->activeStartPos) { /* we're in the (passive) left context. Just skip it */ - PICODBG_DEBUG(("RECOMB skipping item in the left context (%i <= %i)",nextInPos, spho->activeStartPos)); - if (PICODATA_ITEM_BOUND == ihead.type) { - spho->suppressRecombWordBound = 1; - } else if (PICODATA_ITEM_WORDPHON == ihead.type) { - spho->suppressRecombWordBound = 0; - } - - /* consume possyms */ - while (SPHO_POSSYM_OK == (rv = getNextPosSym(spho,&pos,&sym,nextInPos))) { - /* ignore */ - } - if (rv == SPHO_POSSYM_INVALID) { - return (picodata_step_result_t)picoos_emRaiseException(this->common->em, - PICO_ERR_OTHER, NULL, NULL); - } - spho->outReadPos = nextInPos; - } else { /* active region */ - if (spho->headx[spho->outReadPos].boundstrength) { -/* ***************** "side-bound" *********************/ - /* copy to outbuf */ - putSideBoundToOutput(spho); - /* mark as processed */ - spho->headx[spho->outReadPos].boundstrength = 0; - /* output it */ - spho->procState = SPHO_STEPSTATE_FEED; - } else if (PICODATA_ITEM_BOUND == ihead.type) { -/* ***************** BOUND *********************/ - /* expect a boundary phone here */ - PICODBG_DEBUG(("RECOMB got BOUND item and expects corresponding phone")); - rv = getNextPosSym(spho, &pos, &sym, nextInPos); - if (SPHO_POSSYM_OK != rv) { - PICODBG_ERROR(("unexpected symbol or unexpected end of phoneme list")); - return (picodata_step_result_t)picoos_emRaiseException( - this->common->em, PICO_ERR_OTHER, NULL, - NULL); - } - sym = picotrns_unplane(sym, &plane); - /* */ - PICODBG_ASSERT((PICOKFST_PLANE_PB_STRENGTHS == plane)); - - spho->suppressRecombWordBound = TRUE; /* if word following, don't need word boundary */ - /* just consume item and come back here*/ - spho->outReadPos = nextInPos; - - } else if (PICODATA_ITEM_WORDPHON == ihead.type) { -/* ***************** WORDPHON *********************/ - spho->wordStarted = TRUE; - /* i expect a word boundary symbol in this range unless a phrase boundary was encountered before */ - if (spho->suppressRecombWordBound) { - PICODBG_DEBUG(("RECOMB got WORDPHON item but skips expecting BOUND")); - spho->suppressRecombWordBound = FALSE; - } else { - PICODBG_DEBUG(("RECOMB got WORDPHON item and expects corresponding bound phone")); - rv = getNextPosSym(spho, &pos, &sym, nextInPos); - if (SPHO_POSSYM_OK != rv) { - PICODBG_ERROR(("unexpected symbol or unexpected end of phoneme list")); - return (picodata_step_result_t)picoos_emRaiseException(this->common->em, - PICO_ERR_OTHER, NULL, NULL); - } - } - spho->procState = SPHO_STEPSTATE_PROCESS_SYL; - } else if ((PICODATA_ITEM_CMD == ihead.type) && (PICODATA_ITEMINFO1_CMD_SIL == ihead.info1)) { -/* ***************** BREAK COMMAND *********************/ - /* just consume and come back here */ - PICODBG_DEBUG(("RECOMB consuming item from inBuf %i -> %i",spho->outReadPos, nextInPos)); - spho->outReadPos = nextInPos; - } else { -/* ***************** OTHER *********************/ - /* just copy item */ - PICODBG_DEBUG(("RECOMB found other item, just copying")); - picodata_put_itemparts(&ihead, icontent, ihead.len, - spho->outBuf, spho->outBufSize, &clen); - PICODBG_DEBUG(("RECOMB consuming item from inBuf %i -> %i",spho->outReadPos, nextInPos)); - spho->outReadPos = nextInPos; - /* and output it */ - spho->procState = SPHO_STEPSTATE_FEED; - } /* if (ihead.type) */ - - } - - /* return PICODATA_PU_BUSY; */ - break; - - case SPHO_STEPSTATE_PROCESS_SYL: - /* **********************************************************************/ - /* SYL: combine input word item with pos/phon pairs to syl output item */ - /* **********************************************************************/ - - /* consume all transduced phonemes with pos in in the range [spho->outReadPos,nextInPos[ */ - PICODBG_DEBUG(("SYL")); - - spho->feedFollowState = SPHO_STEPSTATE_PROCESS_SYL; - - /* look at the current item */ - ihead = spho->headx[spho->outReadPos].head; - icontent = spho->cbuf + spho->headx[spho->outReadPos].cind; - nextInPos = spho->outReadPos + 1; - PICODBG_DEBUG(("SYL (1) treating item in headx at pos %i",spho->outReadPos)); - /* create syllable item in ohead (head) and sylBuf (contents) */ - ohead.type = PICODATA_ITEM_SYLLPHON; - - PICODBG_TRACE(("SYL expects accent at phonBuf[%i] = (%i,%i) (outReadPos=%i)", spho->phonReadPos, spho->phonBuf[spho->phonReadPos].pos, spho->phonBuf[spho->phonReadPos].sym,spho->outReadPos)); - rv = getNextPosSym(spho,&pos,&sym,nextInPos); - if (SPHO_POSSYM_OK != rv) { - PICODBG_ERROR(("unexpected symbol or unexpected end of phoneme list (%i)",rv)); - return (picodata_step_result_t)picoos_emRaiseException(this->common->em, PICO_ERR_OTHER, NULL, NULL); - } - ohead.info2 = picotrns_unplane(sym, &plane); - PICODBG_ASSERT((PICOKFST_PLANE_ACCENTS == plane)); - PICODBG_DEBUG(("SYL sets accent to %c", sym)); - - /* for the time being, we force to use POS so we can transduce all fsts in a row without reconsulting the items */ - PICODBG_TRACE(("SYL expects POS")); - PICODBG_DEBUG(("SYL (2) treating item in inBuf range [%i,%i[",spho->outReadPos,nextInPos)); - rv = getNextPosSym(spho,&pos,&sym,nextInPos); - if (SPHO_POSSYM_OK != rv) { - PICODBG_ERROR(("unexpected symbol or unexpected end of phoneme list")); - return (picodata_step_result_t)picoos_emRaiseException(this->common->em, PICO_ERR_OTHER, NULL, NULL); - } - if (spho->wordStarted) { - spho->wordStarted = FALSE; - ohead.info1 = picotrns_unplane(sym, &plane); - /* */ - PICODBG_ASSERT(PICOKFST_PLANE_POS == plane); - /* */ - PICODBG_DEBUG(("SYL setting POS to %c", ohead.info1)); - } else { - ohead.info1 = PICODATA_ITEMINFO1_NA; - } - - PICODBG_DEBUG(("SYL (3) treating item in inBuf range [%i,%i[",spho->outReadPos,nextInPos)); - /* get phonemes of that syllable; stop if syllable boundary or outside word */ - sylsym = (PICOKFST_PLANE_PHONEMES << 8) - + spho->syllSepId; - PICODBG_DEBUG(("collecting syllable phonemes before headx position %i",nextInPos)); - spho->sylWritePos = 0; - while (SPHO_POSSYM_OK == (rv = getNextPosSym(spho,&pos,&sym,nextInPos)) && (sym != sylsym)) { - spho->sylBuf[spho->sylWritePos++] = picotrns_unplane(sym, &plane); - /* */ - PICODBG_TRACE(("SYL adding phoneme to syllable: (pos %i,sym %i)[plane %i,sym %c]",pos,sym,plane,sym & 0xFF)); - PICODBG_ASSERT((PICOKFST_PLANE_PHONEMES == plane)); - } - PICODBG_DEBUG(("SYL (4) treating item in inBuf range [%i,%i[",spho->outReadPos,nextInPos)); - ohead.len = spho->sylWritePos; - if (SPHO_POS_INVALID == rv) { - PICODBG_ERROR(("unexpected symbol or unexpected end of phoneme list")); - return (picodata_step_result_t)picoos_emRaiseException(this->common->em, PICO_WARN_INCOMPLETE, NULL, NULL); - } else if ((SPHO_POSSYM_OUT_OF_RANGE == rv) || (SPHO_POSSYM_END == rv)) { - PICODBG_DEBUG(("SYL arrived at end of word and/or end of phon buffer, go to next word")); - spho->outReadPos = nextInPos; /* advance to next item */ - spho->feedFollowState = SPHO_STEPSTATE_PROCESS_RECOMB; /* go to RECOMB after feed */ - } else { - PICODBG_ASSERT((sym == sylsym)); - } - PICODBG_DEBUG(("SYL (5) treating item in inBuf range [%i,%i[",spho->outReadPos,nextInPos)); - - if (ohead.len > 0) { - /* prepare syllable output */ - picodata_put_itemparts(&ohead, spho->sylBuf, - PICODATA_BUFSIZE_DEFAULT, spho->outBuf, - spho->outBufSize, &clen); - - spho->procState = SPHO_STEPSTATE_FEED; - } else { /* skip feeding output of empty syllable */ - spho->procState = spho->feedFollowState; - } - break; - - case SPHO_STEPSTATE_FEED: - /* **********************************************************************/ - /* FEED: output output item and proceed to feedFollowState */ - /* **********************************************************************/ - - PICODBG_DEBUG(("FEED")); - - PICODBG_DEBUG(("FEED putting outBuf item into cb")); - - /*feeding items to PU output buffer*/ - rv = picodata_cbPutItem(this->cbOut, spho->outBuf, - spho->outBufSize, &clen); - - PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], - (picoos_uint8 *)"spho: ", - spho->outBuf, spho->outBufSize); - - if (PICO_EXC_BUF_OVERFLOW == rv) { - /* we have to redo this item */ - PICODBG_DEBUG(("FEED got overflow, returning ICODATA_PU_OUT_FULL")); - return PICODATA_PU_OUT_FULL; - } else if (PICO_OK == rv) { - *numBytesOutput += clen; - spho->procState = spho->feedFollowState; - PICODBG_DEBUG(("FEED ok, going back to procState %i", spho->procState)); - return PICODATA_PU_BUSY; - } else { - PICODBG_DEBUG(("FEED got exception %i when trying to output item",rv)); - spho->procState = spho->feedFollowState; - return (picodata_step_result_t)rv; - } - break; - - case SPHO_STEPSTATE_SHIFT: - /* **********************************************************************/ - /* SHIFT */ - /* **********************************************************************/ - /* If there exists a valid penultima, it should replace any left context (from 0 to activeStartPos) - * else discard the current active range (from activeStartPos to activeEndPos), leaving the current - * left context intact. Often, PARSE would move activeStartPos to 0, so that there is no left context - * after the shift. - */ - - PICODBG_DEBUG(("SHIFT")); - - if (spho->penultima != SPHO_POS_INVALID) { - picoos_int16 shift; - /* set penultima as new left context and set activeStartPos to the shifted activeEndPos */ - PICODBG_DEBUG(( - "SHIFT shifting penultima from %i to 0", - spho->penultima)); - shift = shift_range_left_1(spho, &spho->penultima, 0); - if (shift < 0) { - picoos_emRaiseException(this->common->em,PICO_ERR_OTHER,NULL,NULL); - return PICODATA_PU_ERROR; - } - spho->activeStartPos = spho->activeEndPos - - shift; - spho->lastPhraseBoundPos -= shift; - spho->suppressParseWordBound = FALSE; - spho->suppressRecombWordBound = FALSE; - - } else { - picoos_int16 shift; - picoos_bool lastPhraseBoundActive; - if (spho->activeStartPos == spho->activeEndPos) { - /* no items consumed; we have to abandon left context */ - spho->activeStartPos = 0; - } - lastPhraseBoundActive = (spho->lastPhraseBoundPos >= spho->activeStartPos); - /* dummy comment */ - PICODBG_DEBUG(("SHIFT shift active end from %i to %i", - spho->activeEndPos, spho->activeStartPos)); - shift = shift_range_left_1(spho, &spho->activeEndPos, spho->activeStartPos); - if (shift < 0) { - picoos_emRaiseException(this->common->em,PICO_ERR_OTHER,NULL,NULL); - return PICODATA_PU_ERROR; - } - if (lastPhraseBoundActive) { - spho->lastPhraseBoundPos -= shift; - } - } - - spho->procState = SPHO_STEPSTATE_INIT; - break; - - default: - picoos_emRaiseException(this->common->em, PICO_ERR_OTHER, NULL, NULL); - return PICODATA_PU_ERROR; - break; - - } /* switch (spho->procState) */ - - } /* while (1) */ - - /* should be never reached */ - picoos_emRaiseException(this->common->em, PICO_ERR_OTHER, NULL, NULL); - return PICODATA_PU_ERROR; -} - -#ifdef __cplusplus -} -#endif - -/* end picospho.c */ diff --git a/lib/picospho.h b/lib/picospho.h deleted file mode 100644 index 0c4a0d8..0000000 --- a/lib/picospho.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * 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 picospho.h - * - * sentence phonemic/phonetic FSTs PU - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -/** @addtogroup picospho -itemtype, iteminfo1, iteminfo2, content -> TYPE(INFO1,INFO2)content -in the following - -items input -=========== - -processed: - -- WORDPHON(POS,WACC)phon - -- BOUND(BOUNDstrength,BOUNDtype) - - -unprocessed: -- all other item types are forwared through the PU without modification - - - -- POS - a the single, unambiguous POS - -cf. picodata.h for -- WACC (sentence-level accent (aka prominence)) - PICODATA_ACC0 - PICODATA_ACC1 - PICODATA_ACC2 (<- maybe mapped to ACC1, ie. no ACC2 in output) - PICODATA_ACC3 - - -- BOUNDstrength - PICODATA_ITEMINFO1_BOUND_SBEG (sentence start) - PICODATA_ITEMINFO1_BOUND_SEND (at sentence end) - PICODATA_ITEMINFO1_BOUND_TERM (replaces a flush) - PICODATA_ITEMINFO1_BOUND_PHR0 (no break) - PICODATA_ITEMINFO1_BOUND_PHR1 (primary boundary) - PICODATA_ITEMINFO1_BOUND_PHR2 (short break) - PICODATA_ITEMINFO1_BOUND_PHR3 (secondary phrase boundary, no break) - -- BOUNDtype (actually phrase type of the following phrase) - PICODATA_ITEMINFO2_BOUNDTYPE_P (non-terminal phrase) - PICODATA_ITEMINFO2_BOUNDTYPE_T (terminal phrase) - PICODATA_ITEMINFO2_BOUNDTYPE_Q (question terminal phrase) - PICODATA_ITEMINFO2_BOUNDTYPE_E (exclamation terminal phrase) - - -output sequence (without CMDs): - - = { BOUND(BOUND_SBEG,PHRASEtype) BOUND(BOUND_SEND,..)} BOUND(BOUND_TERM,..) - - = { BOUND(BOUND_PHR1|2|3,PHRASEtype) } - - = WORDPHON(POS,ACC)phon { WORDPHON(POS,ACC)phon } - - - -mapping ACC & word-level stress to syllable accent value - - ACC0 prim -> 0 - ACC1 prim -> 1 - ACC2 prim -> 2 - ACC3 prim -> 3 - - ACC0 sec -> 0 - ACC1 sec -> 4 - ACC2 sec -> 4 - ACC3 sec -> 4 - -Mapping of values to FST symbol id (has to identical to the symbol table used when compiling the FST) - -Value FST symbol id -phoneme_id -> phoneme_id + 256 * PICOKFST_PLANE_PHONEMES -POS_id -> POS_id + 256 * PICOKFST_PLANE_POS -phrasetype_id -> phrasetype_id + 256 * PICOKFST_PLANE_PHRASETYPES -accentlevel_id -> accentlevel_id + 256 * PICOKFST_PLANE_ACCENTS - - - - - - - -minimal input size (before processing starts) -================== - -processing (ie. sequencially applying spho transducers to phoneme sequence composed of - - phonemes inside WORDPHON items and - - pseudo-phonemes derived from boundaries and POS) is possible with - -- one phrase, consisting of a sequence of maximal 30 non-PUNC items - terminated by a PUNC item. A PUNC is artificially enforced if - needed to start processing. - -- as long as the internal buffer is empty, non-processed item types - can be processed immediately - - - -items output -============ -- BOUND(BOUNDstrength,BOUNDtype) - - bound strength may be changed by the fsts - - in addition, BOUNDs of BOUNDstrength = PHR0 are inserted to mark word boundaries - -- SYLLPHON(POS,ACC)phon - where POS is only set for the first syllable of a word, otherwise NA - - - - - - -other limitations -================= - - - */ -#ifndef PICOSPHO_H_ -#define PICOSPHO_H_ - -#include "picoos.h" -#include "picodata.h" -#include "picorsrc.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -picodata_ProcessingUnit picospho_newSentPhoUnit( - picoos_MemoryManager mm, - picoos_Common common, - picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, - picorsrc_Voice voice); - -#ifdef __cplusplus -} -#endif - - -#endif /*PICOSPHO_H_*/ diff --git a/lib/picotok.c b/lib/picotok.c deleted file mode 100644 index 4488609..0000000 --- a/lib/picotok.c +++ /dev/null @@ -1,1563 +0,0 @@ -/* - * 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 picotok.c - * - * tokenizer - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - - -/* ************************************************************/ -/* tokenisation and markup handling */ -/* ************************************************************/ - -/** @addtogroup picotok - @b tokenisation_overview - - markup handling overview: - - The following markups are recognized - - ignore - - speed - - pitch - - volume - - voice - - preproccontext - - mark - - play - - usesig - - genfile - - sentence - - s - - paragraph - - p - - break - - spell (pauses between letter) - - phoneme - - All markups which are recognized but are not yet implemented in pico - system have the mark. -*/ - - -#include "picodefs.h" -#include "picoos.h" -#include "picobase.h" -#include "picodbg.h" -#include "picodata.h" -#include "picotok.h" -#include "picoktab.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -/* *****************************************************************************/ - -#define IN_BUF_SIZE 255 -#define OUT_BUF_SIZE IN_BUF_SIZE + 3 * PICODATA_ITEM_HEADSIZE + 3 - -#define MARKUP_STRING_BUF_SIZE (IN_BUF_SIZE*5) -#define MAX_NR_MARKUP_PARAMS 6 -#define MARKUP_HANDLING_DISABLED 0 -#define MARKUP_HANDLING_ENABLED 1 -#define EOL '\n' - - -typedef picoos_int8 pico_tokenSubType; -typedef picoos_uint8 pico_tokenType; - -/** @todo : consider adding these specialized exception codes: */ - -#define PICO_ERR_MARKUP_VALUE_OUT_OF_RANGE PICO_ERR_OTHER -#define PICO_ERR_INVALID_MARKUP_TAG PICO_ERR_OTHER -#define PICO_ERR_INTERNAL_LIMIT PICO_ERR_OTHER - -typedef enum {MIDummyStart, MIIgnore, - MIPitch, MISpeed, MIVolume, - MIVoice, MIPreprocContext, MIMarker, - MIPlay, MIUseSig, MIGenFile, MIParagraph, - MISentence, MIBreak, MISpell, MIPhoneme, MIItem, MISpeaker, MIDummyEnd - } MarkupId; -typedef enum {MSNotInMarkup, MSGotStart, MSExpectingmarkupTagName, MSInmarkupTagName, - MSGotmarkupTagName, MSInAttrName, MSGotAttrName, MSGotEqual, MSInAttrValue, - MSInAttrValueEscaped, MSGotAttrValue, MSGotEndSlash, MSGotEnd, - MSError, MSErrorTooLong, MSErrorSyntax - } MarkupState; -typedef enum {MENone, MEMissingStart, MEUnknownTag, MEIdent, MEMissingEqual, - MEMissingQuote, MEMissingEnd, MEUnexpectedChar, MEInterprete - } MarkupParseError; - -typedef enum {MTNone, MTStart, MTEnd, MTEmpty} MarkupTagType; - -#define UTF_CHAR_COMPLETE 2 -#define UTF_CHAR_INCOMPLETE 1 -#define UTF_CHAR_MALFORMED 0 - -#define TOK_MARKUP_KW_IGNORE (picoos_uchar*)"ignore" -#define TOK_MARKUP_KW_SPEED (picoos_uchar*)"speed" -#define TOK_MARKUP_KW_PITCH (picoos_uchar*)"pitch" -#define TOK_MARKUP_KW_VOLUME (picoos_uchar*)"volume" -#define TOK_MARKUP_KW_VOICE (picoos_uchar*)"voice" -#define TOK_MARKUP_KW_CONTEXT (picoos_uchar*)"preproccontext" -#define TOK_MARKUP_KW_MARK (picoos_uchar*)"mark" -#define TOK_MARKUP_KW_PLAY (picoos_uchar*)"play" -#define TOK_MARKUP_KW_USESIG (picoos_uchar*)"usesig" -#define TOK_MARKUP_KW_GENFILE (picoos_uchar*)"genfile" -#define TOK_MARKUP_KW_SENTENCE (picoos_uchar*)"sentence" -#define TOK_MARKUP_KW_S (picoos_uchar*)"s" -#define TOK_MARKUP_KW_PARAGRAPH (picoos_uchar*)"paragraph" -#define TOK_MARKUP_KW_P (picoos_uchar*)"p" -#define TOK_MARKUP_KW_BREAK (picoos_uchar*)"break" -#define TOK_MARKUP_KW_SPELL (picoos_uchar*)"spell" -#define TOK_MARKUP_KW_PHONEME (picoos_uchar*)"phoneme" -#define TOK_MARKUP_KW_ITEM (picoos_uchar*)"item" -#define TOK_MARKUP_KW_SPEAKER (picoos_uchar*)"speaker" - -#define KWLevel (picoos_uchar *)"level" -#define KWName (picoos_uchar *)"name" -#define KWProsDomain (picoos_uchar *)"prosodydomain" -#define KWTime (picoos_uchar *)"time" -#define KWMode (picoos_uchar *)"mode" -#define KWSB (picoos_uchar *)"sb" -#define KWPB (picoos_uchar *)"pb" -#define KWFile (picoos_uchar *)"file" -#define KWType (picoos_uchar *)"type" -#define KWF0Beg (picoos_uchar *)"f0beg" -#define KWF0End (picoos_uchar *)"f0end" -#define KWXFadeBeg (picoos_uchar *)"xfadebeg" -#define KWXFadeEnd (picoos_uchar *)"xfadeend" -#define KWAlphabet (picoos_uchar *)"alphabet" -#define KWPH (picoos_uchar *)"ph" -#define KWOrthMode (picoos_uchar *)"orthmode" -#define KWIgnorePunct (picoos_uchar *)"ignorepunct" -#define KWInfo1 (picoos_uchar *)"info1" -#define KWInfo2 (picoos_uchar *)"info2" -#define KWDATA (picoos_uchar *)"data" - -#define PICO_SPEED_MIN 20 -#define PICO_SPEED_MAX 500 -#define PICO_SPEED_DEFAULT 100 -#define PICO_SPEED_FACTOR_MIN 500 -#define PICO_SPEED_FACTOR_MAX 2000 - -#define PICO_PITCH_MIN 50 -#define PICO_PITCH_MAX 200 -#define PICO_PITCH_DEFAULT 100 -#define PICO_PITCH_FACTOR_MIN 500 -#define PICO_PITCH_FACTOR_MAX 2000 -#define PICO_PITCH_ADD_MIN -100 -#define PICO_PITCH_ADD_MAX 100 -#define PICO_PITCH_ADD_DEFAULT 0 - -#define PICO_VOLUME_MIN 0 -#define PICO_VOLUME_MAX 500 -#define PICO_VOLUME_DEFAULT 100 -#define PICO_VOLUME_FACTOR_MIN 500 -#define PICO_VOLUME_FACTOR_MAX 2000 - -#define PICO_SPEAKER_MIN 20 -#define PICO_SPEAKER_MAX 180 -#define PICO_SPEAKER_DEFAULT 100 -#define PICO_SPEAKER_FACTOR_MIN 500 -#define PICO_SPEAKER_FACTOR_MAX 2000 - -#define PICO_CONTEXT_DEFAULT (picoos_uchar*)"DEFAULT" - -#define PARAGRAPH_PAUSE_DUR 500 -#define SPELL_WITH_PHRASE_BREAK 1 -#define SPELL_WITH_SENTENCE_BREAK 2 - -/* *****************************************************************************/ - -#define TOK_PUNC_FLUSH (picoos_char) '\0' - -typedef picoos_uchar Word[MARKUP_STRING_BUF_SIZE]; - - -struct MarkupParam { - Word paramId; - Word paramVal; -}; - -typedef struct MarkupParam MarkupParams[MAX_NR_MARKUP_PARAMS]; - - -/** subobject : TokenizeUnit - * shortcut : tok - */ -typedef struct tok_subobj -{ - picoos_int32 ignLevel; - - picoos_uchar utf[5]; - picoos_int32 utfpos; - picoos_int32 utflen; - - MarkupParams markupParams; - picoos_int32 nrMarkupParams; - MarkupState markupState; - picoos_uchar markupStr[MARKUP_STRING_BUF_SIZE]; - picoos_int32 markupPos; - picoos_int32 markupLevel[MIDummyEnd+1]; - picoos_uchar markupTagName[IN_BUF_SIZE]; - MarkupTagType markupTagType; - MarkupParseError markupTagErr; - - picoos_int32 strPos; - picoos_uchar strDelim; - picoos_bool isFileAttr; - - pico_tokenType tokenType; - pico_tokenSubType tokenSubType; - - picoos_int32 tokenPos; - picoos_uchar tokenStr[IN_BUF_SIZE]; - - picoos_int32 nrEOL; - - picoos_bool markupHandlingMode; /* to be moved ??? */ - picoos_bool aborted; /* to be moved ??? */ - - picoos_bool start; - - picoos_uint8 outBuf[OUT_BUF_SIZE]; /* internal output buffer */ - picoos_uint16 outReadPos; /* next pos to read from outBuf */ - picoos_uint16 outWritePos; /* next pos to write to outBuf */ - - picoos_uchar saveFile[IN_BUF_SIZE]; - Word phonemes; - - picotrns_SimpleTransducer transducer; - - /* kbs */ - - picoktab_Graphs graphTab; - picokfst_FST xsampa_parser; - picokfst_FST svoxpa_parser; - picokfst_FST xsampa2svoxpa_mapper; - - - -} tok_subobj_t; - -/* *****************************************************************************/ - -static void tok_treatMarkupAsSimpleToken (picodata_ProcessingUnit this, tok_subobj_t * tok); -static void tok_treatChar (picodata_ProcessingUnit this, tok_subobj_t * tok, picoos_uchar ch, picoos_bool markupHandling); -static void tok_treatMarkup (picodata_ProcessingUnit this, tok_subobj_t * tok); -static void tok_putToMarkup (picodata_ProcessingUnit this, tok_subobj_t * tok, picoos_uchar str[]); -static void tok_treatSimpleToken (picodata_ProcessingUnit this, tok_subobj_t * tok); -static MarkupId tok_markupTagId (picoos_uchar tagId[]); - -/* *****************************************************************************/ - -static picoos_bool tok_strEqual(picoos_uchar * str1, picoos_uchar * str2) -{ - return (picoos_strcmp((picoos_char*)str1, (picoos_char*)str2) == 0); -} - -static void tok_reduceBlanks(picoos_uchar * str) - /* Remove leading and trailing blanks of 'str' and reduce - groups of blanks within string to exactly one blank. */ - -{ - int i = 0; - int j = 0; - - while (str[j] != 0) { - if (str[j] == (picoos_uchar)' ') { - /* note one blank except at the beginning of string */ - if (i > 0) { - str[i] = (picoos_uchar)' '; - i++; - } - j++; - while (str[j] == (picoos_uchar)' ') { - j++; - } - } else { - str[i] = str[j]; - j++; - i++; - } - } - - /* remove blanks at end of string */ - if ((i > 0) && (str[i - 1] == ' ')) { - i--; - } - str[i] = 0; -} - - -static void tok_startIgnore (tok_subobj_t * tok) -{ - tok->ignLevel++; -} - - -static void tok_endIgnore (tok_subobj_t * tok) -{ - if (tok->ignLevel > 0) { - tok->ignLevel--; - } -} - - -static void tok_getParamIntVal (MarkupParams params, picoos_uchar paramId[], picoos_int32 * paramVal, picoos_bool * paramFound) -{ - int i=0; - - while ((i < MAX_NR_MARKUP_PARAMS) && !tok_strEqual(paramId,params[i].paramId)) { - i++; - } - if ((i < MAX_NR_MARKUP_PARAMS)) { - (*paramVal) = picoos_atoi((picoos_char*)params[i].paramVal); - (*paramFound) = TRUE; - } else { - (*paramVal) = -1; - (*paramFound) = FALSE; - } -} - - - -static void tok_getParamStrVal (MarkupParams params, picoos_uchar paramId[], picoos_uchar paramStrVal[], picoos_bool * paramFound) -{ - int i=0; - - while ((i < MAX_NR_MARKUP_PARAMS) && !tok_strEqual(paramId,params[i].paramId)) { - i++; - } - if (i < MAX_NR_MARKUP_PARAMS) { - picoos_strcpy((picoos_char*)paramStrVal, (picoos_char*)params[i].paramVal); - (*paramFound) = TRUE; - } else { - paramStrVal[0] = 0; - (*paramFound) = FALSE; - } -} - - -static void tok_getParamPhonesStr (MarkupParams params, picoos_uchar paramId[], picoos_uchar alphabet[], picoos_uchar phones[], picoos_int32 phoneslen, picoos_bool * paramFound) -{ - - int i; - picoos_bool done; - - i = 0; - while ((i < MAX_NR_MARKUP_PARAMS) && !tok_strEqual(paramId, params[i].paramId)) { - i++; - } - if (i < MAX_NR_MARKUP_PARAMS) { - if (tok_strEqual(alphabet, PICODATA_XSAMPA) || tok_strEqual(alphabet, (picoos_uchar*)"")) { - picoos_strlcpy((picoos_char*)phones, (picoos_char*)params[i].paramVal, phoneslen); - done = TRUE; - } else { - done = FALSE; - } - (*paramFound) = TRUE; - } else { - done = FALSE; - (*paramFound) = FALSE; - } - if (!done) { - phones[0] = 0; - } -} - - -static void tok_clearMarkupParams (MarkupParams params) -{ - int i; - - for (i = 0; i= '0') && (durStr[i] <= '9')) { - num = 10 * num + (int)durStr[i] - (int)'0'; - tmpWord[i] = ' '; - i++; - } - tok_reduceBlanks(tmpWord); - if (tok_strEqual(tmpWord, (picoos_uchar*)"s")) { - (*dur) = (1000 * num); - (*done) = TRUE; - } else if (tok_strEqual(tmpWord,(picoos_uchar*)"ms")) { - (*dur) = num; - (*done) = TRUE; - } else { - (*dur) = 0; - (*done) = FALSE; - } -} - - -static picoos_int32 tok_putToUtf (tok_subobj_t * tok, picoos_uchar ch) -{ - if (tok->utfpos < PICOBASE_UTF8_MAXLEN) { - tok->utf[tok->utfpos] = ch; - if (tok->utfpos == 0) { - tok->utflen = picobase_det_utf8_length(ch); - } else if (((ch < (picoos_uchar)'\200') || (ch >= (picoos_uchar)'\300'))) { - tok->utflen = 0; - } - (tok->utfpos)++; - if ((tok->utfpos == tok->utflen)) { - if ((tok->utfpos < PICOBASE_UTF8_MAXLEN)) { - tok->utf[tok->utfpos] = 0; - } - return UTF_CHAR_COMPLETE; - } else if (tok->utfpos < tok->utflen) { - return UTF_CHAR_INCOMPLETE; - } else { - return UTF_CHAR_MALFORMED; - } - } else { - return UTF_CHAR_MALFORMED; - } -} - - -static picoos_bool tok_isRelative (picoos_uchar strval[], picoos_uint32 * val) -{ - picoos_int32 len; - picoos_bool rel; - - rel = FALSE; - len = picoos_strlen((picoos_char*)strval); - if (len > 0) { - if (strval[len - 1] == '%') { - strval[len - 1] = 0; - if ((strval[0] == '+') || (strval[0] == '-')) { - (*val) = 1000 + (picoos_atoi((picoos_char*)strval) * 10); - } else { - (*val) = picoos_atoi((picoos_char*)strval) * 10; - } - rel = TRUE; - } - } - return rel; -} - - -static void tok_putItem (picodata_ProcessingUnit this, tok_subobj_t * tok, - picoos_uint8 itemType, picoos_uint8 info1, picoos_uint8 info2, - picoos_uint16 val, - picoos_uchar str[]) -{ - picoos_int32 len, i; - - if ((itemType == PICODATA_ITEM_CMD) && (info1 == PICODATA_ITEMINFO1_CMD_FLUSH)) { - tok->outBuf[tok->outWritePos++] = itemType; - tok->outBuf[tok->outWritePos++] = info1; - tok->outBuf[tok->outWritePos++] = info2; - tok->outBuf[tok->outWritePos++] = 0; - } - else if (tok->ignLevel <= 0) { - switch (itemType) { - case PICODATA_ITEM_CMD: - switch (info1) { - case PICODATA_ITEMINFO1_CMD_CONTEXT: - case PICODATA_ITEMINFO1_CMD_VOICE: - case PICODATA_ITEMINFO1_CMD_MARKER: - case PICODATA_ITEMINFO1_CMD_PLAY: - case PICODATA_ITEMINFO1_CMD_SAVE: - case PICODATA_ITEMINFO1_CMD_UNSAVE: - case PICODATA_ITEMINFO1_CMD_PROSDOMAIN: - case PICODATA_ITEMINFO1_CMD_PHONEME: - len = picoos_strlen((picoos_char*)str); - if (tok->outWritePos + 4 + len < OUT_BUF_SIZE) { - tok->outBuf[tok->outWritePos++] = itemType; - tok->outBuf[tok->outWritePos++] = info1; - tok->outBuf[tok->outWritePos++] = info2; - tok->outBuf[tok->outWritePos++] = len; - for (i=0; ioutBuf[tok->outWritePos++] = str[i]; - } - } - else { - PICODBG_WARN(("tok_putItem: output buffer too small")); - } - break; - case PICODATA_ITEMINFO1_CMD_IGNSIG: - case PICODATA_ITEMINFO1_CMD_IGNORE: - if (tok->outWritePos + 4 < OUT_BUF_SIZE) { - tok->outBuf[tok->outWritePos++] = itemType; - tok->outBuf[tok->outWritePos++] = info1; - tok->outBuf[tok->outWritePos++] = info2; - tok->outBuf[tok->outWritePos++] = 0; - } - else { - PICODBG_WARN(("tok_putItem: output buffer too small")); - } - break; - case PICODATA_ITEMINFO1_CMD_SPEED: - case PICODATA_ITEMINFO1_CMD_PITCH: - case PICODATA_ITEMINFO1_CMD_VOLUME: - case PICODATA_ITEMINFO1_CMD_SPELL: - case PICODATA_ITEMINFO1_CMD_SIL: - case PICODATA_ITEMINFO1_CMD_SPEAKER: - if (tok->outWritePos + 4 + 2 < OUT_BUF_SIZE) { - tok->outBuf[tok->outWritePos++] = itemType; - tok->outBuf[tok->outWritePos++] = info1; - tok->outBuf[tok->outWritePos++] = info2; - tok->outBuf[tok->outWritePos++] = 2; - tok->outBuf[tok->outWritePos++] = val % 256; - tok->outBuf[tok->outWritePos++] = val / 256; - } - else { - PICODBG_WARN(("tok_putItem: output buffer too small")); - } - break; - default: - PICODBG_WARN(("tok_putItem: unknown command type")); - } - break; - case PICODATA_ITEM_TOKEN: - len = picoos_strlen((picoos_char*)str); - if (tok->outWritePos + 4 + len < OUT_BUF_SIZE) { - tok->outBuf[tok->outWritePos++] = itemType; - tok->outBuf[tok->outWritePos++] = info1; - tok->outBuf[tok->outWritePos++] = info2; - tok->outBuf[tok->outWritePos++] = len; - for (i=0; ioutBuf[tok->outWritePos++] = str[i]; - } - } - else { - PICODBG_WARN(("tok_putItem: output buffer too small")); - } - break; - default: - PICODBG_WARN(("tok_putItem: unknown item type")); - } - } -} - - -static void tok_putItem2 (picodata_ProcessingUnit this, tok_subobj_t * tok, - picoos_uint8 type, - picoos_uint8 info1, picoos_uint8 info2, - picoos_uint8 len, - picoos_uint8 data[]) -{ - picoos_int32 i; - - if (is_valid_itemtype(type)) { - tok->outBuf[tok->outWritePos++] = type; - tok->outBuf[tok->outWritePos++] = info1; - tok->outBuf[tok->outWritePos++] = info2; - tok->outBuf[tok->outWritePos++] = len; - for (i=0; ioutBuf[tok->outWritePos++] = data[i]; - } - } -} - - -static MarkupId tok_markupTagId (picoos_uchar tagId[]) -{ - if (picoos_strstr(tagId,(picoos_char *)"svox:") == (picoos_char *)tagId) { - tagId+=5; - } - if (tok_strEqual(tagId, TOK_MARKUP_KW_IGNORE)) { - return MIIgnore; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_SPEED)) { - return MISpeed; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_PITCH)) { - return MIPitch; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_VOLUME)) { - return MIVolume; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_SPEAKER)) { - return MISpeaker; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_VOICE)) { - return MIVoice; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_CONTEXT)) { - return MIPreprocContext; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_MARK)) { - return MIMarker; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_PLAY)) { - return MIPlay; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_USESIG)) { - return MIUseSig; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_GENFILE)) { - return MIGenFile; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_SENTENCE) || tok_strEqual(tagId, TOK_MARKUP_KW_S)) { - return MISentence; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_PARAGRAPH) || tok_strEqual(tagId, TOK_MARKUP_KW_P)) { - return MIParagraph; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_BREAK)) { - return MIBreak; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_SPELL)) { - return MISpell; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_PHONEME)) { - return MIPhoneme; - } else if (tok_strEqual(tagId, TOK_MARKUP_KW_ITEM)) { - return MIItem; - } else { - return MIDummyEnd; - } -} - - -extern void tok_checkLimits (picodata_ProcessingUnit this, picoos_uint32 * value, picoos_uint32 min, picoos_uint32 max, picoos_uchar valueType[]) -{ - if ((((*value) < min) || ((*value) > max))) { - picoos_emRaiseWarning(this->common->em, PICO_ERR_MARKUP_VALUE_OUT_OF_RANGE, (picoos_char*)"", (picoos_char*)"attempt to set illegal value %i for %s", *value, valueType); - if (((*value) < min)) { - (*value) = min; - } else if (((*value) > max)) { - (*value) = max; - } - } -} - - - -extern void tok_checkRealLimits (picodata_ProcessingUnit this, picoos_single * value, picoos_single min, picoos_single max, picoos_uchar valueType[]) -{ - if ((((*value) < min) || ((*value) > max))) { - picoos_emRaiseWarning(this->common->em, PICO_ERR_MARKUP_VALUE_OUT_OF_RANGE, (picoos_char*)"", (picoos_char*)"attempt to set illegal value %f for %s", *value, valueType); - if (((*value) < min)) { - (*value) = min; - } else if (((*value) > max)) { - (*value) = max; - } - } -} - - -#define VAL_STR_LEN 21 - -static void tok_interpretMarkup (picodata_ProcessingUnit this, tok_subobj_t * tok, picoos_bool isStartTag, MarkupId mId) -{ - picoos_bool done; - picoos_int32 ival; - picoos_uint32 uval; - picoos_int32 ival2; - picoos_uchar valStr[VAL_STR_LEN]; - picoos_uchar valStr2[VAL_STR_LEN]; - picoos_uchar valStr3[VAL_STR_LEN]; - picoos_int32 i2; - picoos_uint32 dur; - picoos_bool done1; - picoos_bool paramFound; - picoos_uint8 type, info1, info2; - picoos_uint8 data[256]; - picoos_int32 pos, n, len; - picoos_uchar part[10]; - - done = FALSE; - switch (mId) { - case MIIgnore: - if (isStartTag && tok_strEqual(tok->markupParams[0].paramId,(picoos_uchar*)"")) { - tok_startIgnore(tok); - done = TRUE; - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { - tok_endIgnore(tok); - done = TRUE; - } - break; - case MISpeed: - if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWLevel)) { - if (tok_isRelative(tok->markupParams[0].paramVal, & uval)) { - tok_checkLimits(this, & uval, PICO_SPEED_FACTOR_MIN, PICO_SPEED_FACTOR_MAX,(picoos_uchar*)"relative speed factor"); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPEED, PICODATA_ITEMINFO2_CMD_RELATIVE, uval, (picoos_uchar*)""); - } else { - uval = picoos_atoi((picoos_char*)tok->markupParams[0].paramVal); - tok_checkLimits(this, & uval, PICO_SPEED_MIN, PICO_SPEED_MAX,(picoos_uchar*)"speed"); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPEED, PICODATA_ITEMINFO2_CMD_ABSOLUTE, uval, (picoos_uchar*)""); - } - done = TRUE; - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPEED, PICODATA_ITEMINFO2_CMD_ABSOLUTE, PICO_SPEED_DEFAULT, (picoos_uchar*)""); - done = TRUE; - } - break; - case MIPitch: - if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWLevel)) { - if (tok_isRelative(tok->markupParams[0].paramVal, & uval)) { - tok_checkLimits(this, & uval,PICO_PITCH_FACTOR_MIN,PICO_PITCH_FACTOR_MAX, (picoos_uchar*)"relative pitch factor"); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PITCH, PICODATA_ITEMINFO2_CMD_RELATIVE, uval, (picoos_uchar*)""); - } else { - uval = picoos_atoi((picoos_char*)tok->markupParams[0].paramVal); - tok_checkLimits(this, & uval,PICO_PITCH_MIN,PICO_PITCH_MAX, (picoos_uchar*)"pitch"); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PITCH,PICODATA_ITEMINFO2_CMD_ABSOLUTE, uval, (picoos_uchar*)""); - } - done = TRUE; - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PITCH,PICODATA_ITEMINFO2_CMD_ABSOLUTE, PICO_PITCH_DEFAULT, (picoos_uchar*)""); - done = TRUE; - } - break; - case MIVolume: - if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWLevel)) { - if (tok_isRelative(tok->markupParams[0].paramVal, & uval)) { - tok_checkLimits(this, & uval, PICO_VOLUME_FACTOR_MIN, PICO_VOLUME_FACTOR_MAX, (picoos_uchar*)"relative volume factor"); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_VOLUME, PICODATA_ITEMINFO2_CMD_RELATIVE, uval, (picoos_uchar*)""); - } else { - uval = picoos_atoi((picoos_char*)tok->markupParams[0].paramVal); - tok_checkLimits(this, & uval, PICO_VOLUME_MIN, PICO_VOLUME_MAX, (picoos_uchar*)"volume"); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_VOLUME, PICODATA_ITEMINFO2_CMD_ABSOLUTE, uval, (picoos_uchar*)""); - } - done = TRUE; - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_VOLUME, PICODATA_ITEMINFO2_CMD_ABSOLUTE, PICO_VOLUME_DEFAULT, (picoos_uchar*)""); - done = TRUE; - } - break; - case MISpeaker: - if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWLevel)) { - if (tok_isRelative(tok->markupParams[0].paramVal, & uval)) { - tok_checkLimits(this, & uval, PICO_SPEAKER_FACTOR_MIN, PICO_SPEAKER_FACTOR_MAX, (picoos_uchar*)"relative speaker factor"); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPEAKER, PICODATA_ITEMINFO2_CMD_RELATIVE, uval, (picoos_uchar*)""); - } else { - uval = picoos_atoi((picoos_char*)tok->markupParams[0].paramVal); - tok_checkLimits(this, & uval, PICO_SPEAKER_MIN, PICO_SPEAKER_MAX, (picoos_uchar*)"volume"); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPEAKER, PICODATA_ITEMINFO2_CMD_ABSOLUTE, uval, (picoos_uchar*)""); - } - done = TRUE; - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPEAKER, PICODATA_ITEMINFO2_CMD_ABSOLUTE, PICO_SPEAKER_DEFAULT, (picoos_uchar*)""); - done = TRUE; - } - break; - - case MIVoice: - if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWName)) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_VOICE, PICODATA_ITEMINFO2_NA, 0, tok->markupParams[0].paramVal); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PROSDOMAIN, 0, 0, (picoos_uchar*)""); - done = TRUE; - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId,(picoos_uchar*)"")) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_VOICE, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PROSDOMAIN, 0, 0, (picoos_uchar*)""); - done = TRUE; - } - break; - case MIPreprocContext: - if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWName)) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_CONTEXT, PICODATA_ITEMINFO2_NA, 0, tok->markupParams[0].paramVal); - done = TRUE; - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId,(picoos_uchar*)"")) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_CONTEXT, PICODATA_ITEMINFO2_NA, 0, PICO_CONTEXT_DEFAULT); - done = TRUE; - } - break; - case MIMarker: - if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWName)) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_MARKER, PICODATA_ITEMINFO2_NA, 0, tok->markupParams[0].paramVal); - done = TRUE; - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId,(picoos_uchar*)"")) { - done = TRUE; - } - break; - case MISentence: - if (isStartTag) { - tok_getParamStrVal(tok->markupParams, KWProsDomain, (picoos_uchar*)valStr, & paramFound); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PROSDOMAIN, 2, 0, valStr); - done = TRUE; - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PROSDOMAIN, 2, 0, (picoos_uchar*)""); - done = TRUE; - } - break; - case MIParagraph: - if (isStartTag) { - tok_getParamStrVal(tok->markupParams, KWProsDomain, (picoos_uchar*)valStr, & paramFound); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PROSDOMAIN, 1, 0, valStr); - done = TRUE; - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SIL, PICODATA_ITEMINFO2_NA, PARAGRAPH_PAUSE_DUR, (picoos_uchar*)""); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PROSDOMAIN, 1, 0, (picoos_uchar*)""); - done = TRUE; - } - break; - case MIBreak: - if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWTime)) { - tok_getDur(tok->markupParams[0].paramVal, & dur, & done1); - tok_checkLimits (this, &dur, 0, 65535, (picoos_uchar*)"time"); - if (done1) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SIL, PICODATA_ITEMINFO2_NA, dur, (picoos_uchar*)""); - done = TRUE; - } - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { - done = TRUE; - } - break; - case MISpell: - if (isStartTag) { - if (tok_strEqual(tok->markupParams[0].paramId, KWMode)) { - if (tok_strEqual(tok->markupParams[0].paramVal, KWPB)) { - uval = SPELL_WITH_PHRASE_BREAK; - } else if (tok_strEqual(tok->markupParams[0].paramVal, KWSB)) { - uval = SPELL_WITH_SENTENCE_BREAK; - } else { - tok_getDur(tok->markupParams[0].paramVal, & uval, & done1); - tok_checkLimits (this, & uval, 0, 65535, (picoos_uchar*)"time"); - if (done1) { - done = TRUE; - } - } - } else { - uval = SPELL_WITH_PHRASE_BREAK; - } - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPELL, PICODATA_ITEMINFO2_CMD_START, uval, (picoos_uchar*)""); - done = TRUE; - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPELL, PICODATA_ITEMINFO2_CMD_END, 0, (picoos_uchar*)""); - done = TRUE; - } - break; - case MIGenFile: - if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWFile)) { - if (tok->saveFile[0] != 0) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_UNSAVE, - picodata_getPuTypeFromExtension(tok->saveFile, /*input*/FALSE), 0, tok->saveFile); - tok->saveFile[0] = 0; - } - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SAVE, - picodata_getPuTypeFromExtension(tok->markupParams[0].paramVal, /*input*/FALSE), 0, tok->markupParams[0].paramVal); - picoos_strcpy((picoos_char*)tok->saveFile, (picoos_char*)tok->markupParams[0].paramVal); - done = TRUE; - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { - if (tok->saveFile[0] != 0) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_UNSAVE, - picodata_getPuTypeFromExtension(tok->saveFile, /*input*/FALSE), 0, (picoos_uchar*)""); - tok->saveFile[0] = 0; - } - done = TRUE; - } - break; - case MIPlay: - if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWFile)) { - if (picoos_FileExists(this->common, (picoos_char*)tok->markupParams[0].paramVal)) { - tok_getParamIntVal(tok->markupParams,KWF0Beg,& ival,& paramFound); - tok_getParamIntVal(tok->markupParams,KWF0End,& ival2,& paramFound); - tok_getParamStrVal(tok->markupParams,KWAlphabet,valStr3,& paramFound); - tok_getParamPhonesStr(tok->markupParams,KWXFadeBeg,valStr3,valStr,VAL_STR_LEN,& paramFound); - tok_getParamPhonesStr(tok->markupParams,KWXFadeEnd,valStr3,valStr2,VAL_STR_LEN,& paramFound); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PLAY, - picodata_getPuTypeFromExtension(tok->markupParams[0].paramVal, /*input*/TRUE), 0, tok->markupParams[0].paramVal); - tok_startIgnore(tok); - } else { - if (tok->ignLevel > 0) { - tok_startIgnore(tok); - } else { - picoos_emRaiseWarning(this->common->em, PICO_EXC_CANT_OPEN_FILE, (picoos_char*)"", (picoos_char*)"file '%s' not found; synthesizing enclosed text instead\n", tok->markupParams[0].paramVal); - } - } - done = TRUE; - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { - tok_endIgnore(tok); - done = TRUE; - } - break; - case MIUseSig: - if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWFile)) { - if (picoos_FileExists(this->common, (picoos_char*)tok->markupParams[0].paramVal)) { - tok_getParamIntVal(tok->markupParams,KWF0Beg,& ival,& paramFound); - tok_getParamIntVal(tok->markupParams,KWF0End,& ival2,& paramFound); - tok_getParamStrVal(tok->markupParams,KWAlphabet,valStr3, & paramFound); - tok_getParamPhonesStr(tok->markupParams,KWXFadeBeg,valStr3,valStr,VAL_STR_LEN,& paramFound); - tok_getParamPhonesStr(tok->markupParams,KWXFadeEnd,valStr3,valStr2,VAL_STR_LEN,& paramFound); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PLAY, - picodata_getPuTypeFromExtension(tok->markupParams[0].paramVal, /*input*/TRUE), 0, tok->markupParams[0].paramVal); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_IGNSIG, PICODATA_ITEMINFO2_CMD_START, 0, (picoos_uchar*)""); - } else { - if (tok->ignLevel <= 0) { - picoos_emRaiseWarning(this->common->em, PICO_EXC_CANT_OPEN_FILE, (picoos_char*)"", (picoos_char*)"file '%s' not found; synthesizing enclosed text instead", tok->markupParams[0].paramVal); - } - } - done = TRUE; - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_IGNSIG, PICODATA_ITEMINFO2_CMD_END, 0, (picoos_uchar*)""); - done = TRUE; - } - break; - case MIPhoneme: - i2 = 0; - if (isStartTag) { - if (tok_strEqual(tok->markupParams[0].paramId, KWAlphabet) && tok_strEqual(tok->markupParams[1].paramId, KWPH)) { - if (tok_strEqual(tok->markupParams[2].paramId, KWOrthMode) - && tok_strEqual(tok->markupParams[2].paramVal, KWIgnorePunct)) { - i2 = 1; - } - if (picodata_mapPAStrToPAIds(tok->transducer, this->common, tok->xsampa_parser, tok->svoxpa_parser, tok->xsampa2svoxpa_mapper, tok->markupParams[1].paramVal, tok->markupParams[0].paramVal, tok->phonemes, sizeof(tok->phonemes)-1) == PICO_OK) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PHONEME, - PICODATA_ITEMINFO2_CMD_START, i2, tok->phonemes); - done = TRUE; - } else { - PICODBG_WARN(("cannot map phonetic string '%s'; synthesizeing text instead", tok->markupParams[1].paramVal)); - picoos_emRaiseWarning(this->common->em, PICO_ERR_MARKUP_VALUE_OUT_OF_RANGE,(picoos_char*)"", (picoos_char*)"cannot map phonetic string '%s'; synthesizeing text instead", tok->markupParams[1].paramVal); - done = TRUE; - } - } else if (tok_strEqual(tok->markupParams[0].paramId, KWPH)) { - if (tok_strEqual(tok->markupParams[1].paramId, KWOrthMode) - && tok_strEqual(tok->markupParams[1].paramVal, KWIgnorePunct)) { - i2 = 1; - } - if (picodata_mapPAStrToPAIds(tok->transducer, this->common, tok->xsampa_parser, tok->svoxpa_parser, tok->xsampa2svoxpa_mapper, tok->markupParams[0].paramVal, PICODATA_XSAMPA, tok->phonemes, sizeof(tok->phonemes)) == PICO_OK) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PHONEME, - PICODATA_ITEMINFO2_CMD_START, i2, tok->phonemes); - done = TRUE; - } - else { - PICODBG_WARN(("cannot map phonetic string '%s'; synthesizeing text instead", tok->markupParams[1].paramVal)); - picoos_emRaiseWarning(this->common->em, PICO_ERR_MARKUP_VALUE_OUT_OF_RANGE,(picoos_char*)"", (picoos_char*)"cannot map phonetic string '%s'; synthesizing text instead", tok->markupParams[0].paramVal); - done = TRUE; - } - } - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PHONEME, - PICODATA_ITEMINFO2_CMD_END, i2, (picoos_uchar*)""); - done = TRUE; - } - break; - case MIItem: - if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWType) && - tok_strEqual(tok->markupParams[1].paramId, KWInfo1)&& - tok_strEqual(tok->markupParams[2].paramId, KWInfo2)&& - tok_strEqual(tok->markupParams[3].paramId, KWDATA)) { - picoos_int32 len2, n2; - type = picoos_atoi(tok->markupParams[0].paramVal); - info1 = picoos_atoi(tok->markupParams[1].paramVal); - info2 = picoos_atoi(tok->markupParams[2].paramVal); - n = 0; n2 = 0; - len2 = (picoos_int32)picoos_strlen(tok->markupParams[3].paramVal); - while (nmarkupParams[3].paramVal[n] != 0) && (tok->markupParams[3].paramVal[n] <= 32)) { - n++; - } - tok->markupParams[3].paramVal[n2] = tok->markupParams[3].paramVal[n]; - n++; - n2++; - } - if (is_valid_itemtype(type)) { - done = TRUE; - len = 0; - pos = 0; - picoos_get_sep_part_str(tok->markupParams[3].paramVal, picoos_strlen(tok->markupParams[3].paramVal), - &pos, ',', part, 10, &done1); - while (done && done1) { - n = picoos_atoi(part); - if ((n>=0) && (n<256) && (len<256)) { - data[len++] = n; - } - else { - done = FALSE; - } - picoos_get_sep_part_str(tok->markupParams[3].paramVal, picoos_strlen(tok->markupParams[3].paramVal), - &pos, ',', part, 10, &done1); - } - if (done) { - tok_putItem2(this, tok, type, info1, info2, len, data); - } - } - else { - done = FALSE; - } - } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId,(picoos_uchar*)"")) { - done = TRUE; - } - break; - default: - break; - } - if (!done) { - tok->markupTagErr = MEInterprete; - } - if (isStartTag) { - tok->markupLevel[mId]++; - } else if ((tok->markupLevel[mId] > 0)) { - tok->markupLevel[mId]--; - } -} - - -static picoos_bool tok_attrChar (picoos_uchar ch, picoos_bool first) -{ - return ((((ch >= (picoos_uchar)'A') && (ch <= (picoos_uchar)'Z')) || - ((ch >= (picoos_uchar)'a') && (ch <= (picoos_uchar)'z'))) || - ( !(first) && ((ch >= (picoos_uchar)'0') && (ch <= (picoos_uchar)'9')))); -} - - - -static picoos_bool tok_idChar (picoos_uchar ch, picoos_bool first) -{ - return tok_attrChar(ch, first) || ( !(first) && (ch == (picoos_uchar)':')); -} - - -static void tok_setIsFileAttr (picoos_uchar name[], picoos_bool * isFile) -{ - (*isFile) = tok_strEqual(name, KWFile); -} - -/* *****************************************************************************/ - -static void tok_putToSimpleToken (picodata_ProcessingUnit this, tok_subobj_t * tok, picoos_uchar str[], pico_tokenType type, pico_tokenSubType subtype) -{ - int i, len; - - if (str[0] != 0) { - len = picoos_strlen((picoos_char*)str); - for (i = 0; i < len; i++) { - if (tok->tokenPos >= IN_BUF_SIZE) { - picoos_emRaiseWarning(this->common->em, PICO_ERR_INTERNAL_LIMIT, (picoos_char*)"", (picoos_char*)"simple token too long; forced treatment"); - tok_treatSimpleToken(this, tok); - } - tok->tokenStr[tok->tokenPos] = str[i]; - tok->tokenPos++; - } - } - tok->tokenType = type; - tok->tokenSubType = subtype; -} - - -static void tok_putToMarkup (picodata_ProcessingUnit this, tok_subobj_t * tok, picoos_uchar str[]) -{ - picoos_int32 i, len; - picoos_uint8 ok; - - tok->markupTagErr = MENone; - len = picoos_strlen((picoos_char*)str); - for (i = 0; i< len; i++) { - if (tok->markupPos >= (MARKUP_STRING_BUF_SIZE - 1)) { - if ((tok->markupPos == (MARKUP_STRING_BUF_SIZE - 1)) && (tok_markupTagId(tok->markupTagName) != MIDummyEnd)) { - picoos_emRaiseWarning(this->common->em, PICO_ERR_INTERNAL_LIMIT ,(picoos_char*)"", (picoos_char*)"markup tag too long"); - } - tok->markupState = MSErrorTooLong; - } else if ((str[i] == (picoos_uchar)' ') && ((tok->markupState == MSExpectingmarkupTagName) || (tok->markupState == MSGotmarkupTagName) || (tok->markupState == MSGotAttrName) || (tok->markupState == MSGotEqual) || (tok->markupState == MSGotAttrValue))) { - } else if ((str[i] == (picoos_uchar)'>') && ((tok->markupState == MSGotmarkupTagName) || (tok->markupState == MSInmarkupTagName) || (tok->markupState == MSGotAttrValue))) { - tok->markupState = MSGotEnd; - } else if ((str[i] == (picoos_uchar)'/') && ((tok->markupState == MSGotmarkupTagName) || (tok->markupState == MSInmarkupTagName) || (tok->markupState == MSGotAttrValue))) { - if (tok->markupTagType == MTEnd) { - tok->markupTagErr = MEUnexpectedChar; - tok->markupState = MSError; - } else { - tok->markupTagType = MTEmpty; - tok->markupState = MSGotEndSlash; - } - } else { - switch (tok->markupState) { - case MSNotInMarkup: - if (str[i] == (picoos_uchar)'<') { - tok_clearMarkupParams(tok->markupParams); - tok->nrMarkupParams = 0; - tok->strPos = 0; - tok->markupTagType = MTStart; - tok->markupState = MSGotStart; - } else { - tok->markupTagErr = MEMissingStart; - tok->markupState = MSError; - } - break; - case MSGotStart: - if (str[i] == (picoos_uchar)'/') { - tok->markupTagType = MTEnd; - tok->markupState = MSExpectingmarkupTagName; - } else if (str[i] == (picoos_uchar)' ') { - tok->markupState = MSExpectingmarkupTagName; - } else if (tok_idChar(str[i],TRUE)) { - tok->markupTagType = MTStart; - tok->markupTagName[tok->strPos] = str[i]; - tok->strPos++; - tok->markupTagName[tok->strPos] = 0; - tok->markupState = MSInmarkupTagName; - } else { - tok->markupTagErr = MEUnexpectedChar; - tok->markupState = MSError; - } - break; - case MSInmarkupTagName: case MSExpectingmarkupTagName: - if (tok_idChar(str[i],tok->markupState == MSExpectingmarkupTagName)) { - tok->markupTagName[tok->strPos] = str[i]; - tok->strPos++; - tok->markupTagName[(tok->strPos)] = 0; - tok->markupState = MSInmarkupTagName; - } else if ((tok->markupState == MSInmarkupTagName) && (str[i] == (picoos_uchar)' ')) { - tok->markupState = MSGotmarkupTagName; - picobase_lowercase_utf8_str(tok->markupTagName, (picoos_char*)tok->markupTagName, IN_BUF_SIZE, &ok); - tok->strPos = 0; - } else { - tok->markupTagErr = MEIdent; - tok->markupState = MSError; - } - break; - case MSGotmarkupTagName: case MSGotAttrValue: - if (tok_attrChar(str[i], TRUE)) { - if (tok->markupTagType == MTEnd) { - tok->markupTagErr = MEUnexpectedChar; - tok->markupState = MSError; - } else { - if (tok->nrMarkupParams < MAX_NR_MARKUP_PARAMS) { - tok->markupParams[tok->nrMarkupParams].paramId[tok->strPos] = str[i]; - tok->strPos++; - tok->markupParams[tok->nrMarkupParams].paramId[tok->strPos] = 0; - } else { - picoos_emRaiseWarning(this->common->em, PICO_ERR_INTERNAL_LIMIT ,(picoos_char*)"", (picoos_char*)"too many attributes in markup; ignoring"); - } - tok->markupState = MSInAttrName; - } - } else { - tok->markupTagErr = MEUnexpectedChar; - tok->markupState = MSError; - } - break; - case MSInAttrName: - if (tok_attrChar(str[i], FALSE)) { - if (tok->nrMarkupParams < MAX_NR_MARKUP_PARAMS) { - tok->markupParams[tok->nrMarkupParams].paramId[tok->strPos] = str[i]; - tok->strPos++; - tok->markupParams[tok->nrMarkupParams].paramId[tok->strPos] = 0; - } - tok->markupState = MSInAttrName; - } else if (str[i] == (picoos_uchar)' ') { - picobase_lowercase_utf8_str(tok->markupParams[tok->nrMarkupParams].paramId, (picoos_char*)tok->markupParams[tok->nrMarkupParams].paramId, IN_BUF_SIZE, &ok); - tok_setIsFileAttr(tok->markupParams[tok->nrMarkupParams].paramId, & tok->isFileAttr); - tok->markupState = MSGotAttrName; - } else if (str[i] == (picoos_uchar)'=') { - picobase_lowercase_utf8_str(tok->markupParams[tok->nrMarkupParams].paramId, (picoos_char*)tok->markupParams[tok->nrMarkupParams].paramId, IN_BUF_SIZE, &ok); - tok_setIsFileAttr(tok->markupParams[tok->nrMarkupParams].paramId, & tok->isFileAttr); - tok->markupState = MSGotEqual; - } else { - tok->markupTagErr = MEMissingEqual; - tok->markupState = MSError; - } - break; - case MSGotAttrName: - if (str[i] == (picoos_uchar)'=') { - tok->markupState = MSGotEqual; - } else { - tok->markupTagErr = MEMissingEqual; - tok->markupState = MSError; - } - break; - case MSGotEqual: - if ((str[i] == (picoos_uchar)'"') || (str[i] == (picoos_uchar)'\'')) { - tok->strDelim = str[i]; - tok->strPos = 0; - tok->markupState = MSInAttrValue; - } else { - tok->markupTagErr = MEMissingQuote; - tok->markupState = MSError; - } - break; - case MSInAttrValue: - if (!(tok->isFileAttr) && (str[i] == (picoos_uchar)'\\')) { - tok->markupState = MSInAttrValueEscaped; - } else if (str[i] == tok->strDelim) { - if (tok->nrMarkupParams < MAX_NR_MARKUP_PARAMS) { - tok->nrMarkupParams++; - } - tok->strPos = 0; - tok->markupState = MSGotAttrValue; - } else { - if (tok->nrMarkupParams < MAX_NR_MARKUP_PARAMS) { - tok->markupParams[tok->nrMarkupParams].paramVal[tok->strPos] = str[i]; - tok->strPos++; - tok->markupParams[tok->nrMarkupParams].paramVal[tok->strPos] = 0; - } - tok->markupState = MSInAttrValue; - } - break; - case MSInAttrValueEscaped: - if (tok->nrMarkupParams < MAX_NR_MARKUP_PARAMS) { - tok->markupParams[tok->nrMarkupParams].paramVal[tok->strPos] = str[i]; - tok->strPos++; - tok->markupParams[tok->nrMarkupParams].paramVal[tok->strPos] = 0; - } - tok->markupState = MSInAttrValue; - break; - case MSGotEndSlash: - if (str[i] == (picoos_uchar)'>') { - tok->markupState = MSGotEnd; - } else { - tok->markupTagErr = MEUnexpectedChar; - tok->markupState = MSError; - } - break; - default: - tok->markupTagErr = MEUnexpectedChar; - tok->markupState = MSError; - break; - } - } - tok->markupStr[tok->markupPos] = str[i]; - tok->markupPos++; - tok->markupStr[tok->markupPos] = 0; - } - /* - PICODBG_DEBUG(("putToMarkup %s", tok->markupStr)); - */ -} - -/* *****************************************************************************/ - -static void tok_treatMarkupAsSimpleToken (picodata_ProcessingUnit this, tok_subobj_t * tok) -{ - picoos_int32 i; - - tok->utfpos = 0; - tok->utflen = 0; - tok->markupState = MSNotInMarkup; - for (i = 0; i < tok->markupPos; i++) { - tok_treatChar(this, tok, tok->markupStr[i], FALSE); - } - tok->markupPos = 0; - tok->strPos = 0; -} - - -static void tok_treatMarkup (picodata_ProcessingUnit this, tok_subobj_t * tok) -{ - MarkupId mId; - - if (tok_markupTagId(tok->markupTagName) != MIDummyEnd) { - if (tok->markupTagErr == MENone) { - tok->markupState = MSNotInMarkup; - if ((tok->tokenType != PICODATA_ITEMINFO1_TOKTYPE_SPACE) && (tok->tokenType != PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED)) { - tok_treatSimpleToken(this, tok); - } - tok_putToSimpleToken(this, tok, (picoos_uchar*)" ", PICODATA_ITEMINFO1_TOKTYPE_SPACE, -1); - mId = tok_markupTagId(tok->markupTagName); - if ((tok->markupTagType == MTStart) || (tok->markupTagType == MTEmpty)) { - tok_interpretMarkup(this, tok, TRUE, mId); - } - if (((tok->markupTagType == MTEnd) || (tok->markupTagType == MTEmpty))) { - tok_clearMarkupParams(tok->markupParams); - tok->nrMarkupParams = 0; - tok_interpretMarkup(this, tok, FALSE,mId); - } - } - if (tok->markupTagErr != MENone) { - if (!tok->aborted) { - picoos_emRaiseWarning(this->common->em, PICO_ERR_INVALID_MARKUP_TAG, (picoos_char*)"", (picoos_char*)"syntax error in markup token '%s'",tok->markupStr); - } - tok_treatMarkupAsSimpleToken(this, tok); - } - } else { - tok_treatMarkupAsSimpleToken(this, tok); - } - tok->markupState = MSNotInMarkup; - tok->markupPos = 0; - tok->strPos = 0; -} - - - -static void tok_treatChar (picodata_ProcessingUnit this, tok_subobj_t * tok, picoos_uchar ch, picoos_bool markupHandling) -{ - picoos_int32 id; - picoos_uint8 uval8; - pico_tokenType type = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; - pico_tokenSubType subtype = -1; - picoos_bool dummy; - - if (ch == NULLC) { - tok_treatSimpleToken(this, tok); - tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); - } - else { - switch (tok_putToUtf(tok, ch)) { - case UTF_CHAR_MALFORMED: - tok->utfpos = 0; - tok->utflen = 0; - break; - case UTF_CHAR_INCOMPLETE: - break; - case UTF_CHAR_COMPLETE: - markupHandling = (markupHandling && (tok->markupHandlingMode == MARKUP_HANDLING_ENABLED)); - id = picoktab_graphOffset(tok->graphTab, tok->utf); - if (id > 0) { - if (picoktab_getIntPropTokenType(tok->graphTab, id, &uval8)) { - type = (pico_tokenType)uval8; - if (type == PICODATA_ITEMINFO1_TOKTYPE_LETTERV) { - type = PICODATA_ITEMINFO1_TOKTYPE_LETTER; - } - } - dummy = picoktab_getIntPropTokenSubType(tok->graphTab, id, &subtype); - } else if (ch <= (picoos_uchar)' ') { - type = PICODATA_ITEMINFO1_TOKTYPE_SPACE; - subtype = -1; - } else { - type = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; - subtype = -1; - } - if ((ch > (picoos_uchar)' ')) { - tok->nrEOL = 0; - } else if ((ch == EOL)) { - tok->nrEOL++; - } - if (markupHandling && (tok->markupState != MSNotInMarkup)) { - tok_putToMarkup(this, tok, tok->utf); - if (tok->markupState >= MSError) { - tok_treatMarkupAsSimpleToken(this, tok); - } else if (tok->markupState == MSGotEnd) { - tok_treatMarkup(this, tok); - } - } else if ((markupHandling && (ch == (picoos_uchar)'<'))) { - tok_putToMarkup(this, tok, tok->utf); - } else if (type != PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED) { - if ((type != tok->tokenType) || (type == PICODATA_ITEMINFO1_TOKTYPE_CHAR) || (subtype != tok->tokenSubType)) { - tok_treatSimpleToken(this, tok); - } else if ((ch == EOL) && (tok->nrEOL == 2)) { - tok_treatSimpleToken(this, tok); - tok_putToSimpleToken(this, tok, (picoos_uchar*)".", PICODATA_ITEMINFO1_TOKTYPE_CHAR, -1); - tok_treatSimpleToken(this, tok); - } - tok_putToSimpleToken(this, tok, tok->utf, type, subtype); - } else { - tok_treatSimpleToken(this, tok); - } - tok->utfpos = 0; - tok->utflen = 0; - break; - } - } -} - - -static void tok_treatSimpleToken (picodata_ProcessingUnit this, tok_subobj_t * tok) -{ - if (tok->tokenPos < IN_BUF_SIZE) { - tok->tokenStr[tok->tokenPos] = 0; - } - if (tok->markupState != MSNotInMarkup) { - if (!(tok->aborted) && (tok->markupState >= MSGotmarkupTagName) && (tok_markupTagId(tok->markupTagName) != MIDummyEnd)) { - picoos_emRaiseWarning(this->common->em, PICO_ERR_INVALID_MARKUP_TAG, (picoos_char*)"", (picoos_char*)"unfinished markup tag '%s'",tok->markupStr); - } - tok_treatMarkupAsSimpleToken(this, tok); - tok_treatSimpleToken(this, tok); - } else if ((tok->tokenPos > 0) && ((tok->ignLevel <= 0) || (tok->tokenType == PICODATA_ITEMINFO1_TOKTYPE_SPACE))) { - tok_putItem(this, tok, PICODATA_ITEM_TOKEN, tok->tokenType, (picoos_uint8)tok->tokenSubType, 0, tok->tokenStr); - } - tok->tokenPos = 0; - tok->tokenType = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; - tok->tokenSubType = -1; -} - -/* *****************************************************************************/ - -static pico_status_t tokReset(register picodata_ProcessingUnit this) -{ - tok_subobj_t * tok; - MarkupId mId; - - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - tok = (tok_subobj_t *) this->subObj; - - tok->ignLevel = 0; - - tok->utfpos = 0; - tok->utflen = 0; - - tok_clearMarkupParams(tok->markupParams); - tok->nrMarkupParams = 0; - tok->markupState = MSNotInMarkup; - tok->markupPos = 0; - for (mId = MIDummyStart; mId <= MIDummyEnd; mId++) { - tok->markupLevel[mId] = 0; - } - tok->markupTagName[0] = 0; - tok->markupTagType = MTNone; - tok->markupTagErr = MENone; - - tok->strPos = 0; - tok->strDelim = 0; - tok->isFileAttr = FALSE; - - tok->tokenType = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; - tok->tokenSubType = -1; - tok->tokenPos = 0; - - tok->nrEOL = 0; - - - tok->markupHandlingMode = TRUE; - tok->aborted = FALSE; - - tok->start = TRUE; - - tok->outReadPos = 0; - tok->outWritePos = 0; - - tok->saveFile[0] = 0; - - - tok->graphTab = picoktab_getGraphs(this->voice->kbArray[PICOKNOW_KBID_TAB_GRAPHS]); - - tok->xsampa_parser = picokfst_getFST(this->voice->kbArray[PICOKNOW_KBID_FST_XSAMPA_PARSE]); - PICODBG_TRACE(("got xsampa_parser @ %i",tok->xsampa_parser)); - - tok->svoxpa_parser = picokfst_getFST(this->voice->kbArray[PICOKNOW_KBID_FST_SVOXPA_PARSE]); - PICODBG_TRACE(("got svoxpa_parser @ %i",tok->svoxpa_parser)); - - tok->xsampa2svoxpa_mapper = picokfst_getFST(this->voice->kbArray[PICOKNOW_KBID_FST_XSAMPA2SVOXPA]); - PICODBG_TRACE(("got xsampa2svoxpa_mapper @ %i",tok->xsampa2svoxpa_mapper)); - - - - return PICO_OK; -} - -static pico_status_t tokInitialize(register picodata_ProcessingUnit this) -{ -/* - - tok_subobj_t * tok; - - if (NULL == this || NULL == this->subObj) { - return PICO_ERR_OTHER; - } - tok = (tok_subobj_t *) this->subObj; -*/ - return tokReset(this); -} - - -static pico_status_t tokTerminate(register picodata_ProcessingUnit this) -{ - return PICO_OK; -} - -static picodata_step_result_t tokStep(register picodata_ProcessingUnit this, picoos_int16 mode, picoos_uint16 * numBytesOutput); - -static pico_status_t tokSubObjDeallocate(register picodata_ProcessingUnit this, - picoos_MemoryManager mm) -{ - - if (NULL != this) { - picoos_deallocate(this->common->mm, (void *) &this->subObj); - } - mm = mm; /* avoid warning "var not used in this function"*/ - return PICO_OK; -} - -picodata_ProcessingUnit picotok_newTokenizeUnit(picoos_MemoryManager mm, picoos_Common common, - picodata_CharBuffer cbIn, picodata_CharBuffer cbOut, - picorsrc_Voice voice) -{ - tok_subobj_t * tok; - picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, cbOut, voice); - if (this == NULL) { - return NULL; - } - this->initialize = tokInitialize; - PICODBG_DEBUG(("set this->step to tokStep")); - this->step = tokStep; - this->terminate = tokTerminate; - this->subDeallocate = tokSubObjDeallocate; - this->subObj = picoos_allocate(mm, sizeof(tok_subobj_t)); - if (this->subObj == NULL) { - picoos_deallocate(mm, (void *)&this); - return NULL; - } - tok = (tok_subobj_t *) this->subObj; - tok->transducer = picotrns_newSimpleTransducer(mm, common, 10*(PICOTRNS_MAX_NUM_POSSYM+2)); - if (NULL == tok->transducer) { - tokSubObjDeallocate(this,mm); - picoos_deallocate(mm, (void *)&this); - return NULL; - } - tokInitialize(this); - return this; -} - -/** - * fill up internal buffer, try to locate token, write token to output - */ -picodata_step_result_t tokStep(register picodata_ProcessingUnit this, - picoos_int16 mode, picoos_uint16 * numBytesOutput) -{ - register tok_subobj_t * tok; - - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - tok = (tok_subobj_t *) this->subObj; - - mode = mode; /* avoid warning "var not used in this function"*/ - - *numBytesOutput = 0; - while (1) { /* exit via return */ - picoos_int16 ch; - - if ((tok->outWritePos - tok->outReadPos) > 0) { - if (picodata_cbPutItem(this->cbOut, &tok->outBuf[tok->outReadPos], tok->outWritePos - tok->outReadPos, numBytesOutput) == PICO_OK) { - PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], - (picoos_uint8 *)"tok:", &tok->outBuf[tok->outReadPos], tok->outWritePos - tok->outReadPos); - tok->outReadPos += *numBytesOutput; - if (tok->outWritePos == tok->outReadPos) { - tok->outWritePos = 0; - tok->outReadPos = 0; - } - } - else { - return PICODATA_PU_OUT_FULL; - } - - } - else if (PICO_EOF != (ch = picodata_cbGetCh(this->cbIn))) { - PICODBG_DEBUG(("read in %c", (picoos_char) ch)); - tok_treatChar(this, tok, (picoos_uchar) ch, /*markupHandling*/TRUE); - } - else { - return PICODATA_PU_IDLE; - } - } -} - -#ifdef __cplusplus -} -#endif - -/* end */ diff --git a/lib/picotok.h b/lib/picotok.h deleted file mode 100644 index b602408..0000000 --- a/lib/picotok.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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 picotok.h - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - - -/** @addtogroup picotok -itemtype, iteminfo1, iteminfo2, content -> TYPE(INFO1,INFO2)content -in the following - -input -===== - -- UTF8 text - -limitations: currently only german umlauts in addition to ASCII - - -minimal input size (before processing starts) -================== - -processing (ie. tokenization) starts when -- 'PICO_EOF' char received (which happens whenever the cbIn buffer is empty) -- tok-internal buffer is full - - -items output -============ - -processing the character stream can result in one of the -following items: --> WORDGRAPH(NA,NA)graph <- mapped to lower case; incl. 1-2 digit nrs (0-99) --> OTHER(NA,NA)string <- skip or spell --> PUNC(PUNCtype,PUNCsubtype) --> CMD(CMDtype,CMDsubtype)args - -with -- PUNCtype %d - PICODATA_ITEMINFO1_PUNC_SENTEND - PICODATA_ITEMINFO1_PUNC_PHRASEEND -- PUNCsubtype %d - PICODATA_ITEMINFO2_PUNC_SENT_T - PICODATA_ITEMINFO2_PUNC_SENT_Q - PICODATA_ITEMINFO2_PUNC_SENT_E - PICODATA_ITEMINFO2_PUNC_PHRASE - (used later: PICODATA_ITEMINFO2_PUNC_PHRASE_FORCED) -- CMDtype %d - PICODATA_ITEMINFO1_CMD_FLUSH (no args) - ? PICODATA_ITEMINFO1_CMD_PLAY ? (not yet) -- CMDsubtype %d - PICODATA_ITEMINFO2_NA - ? PICODATA_ITEMINFO2_CMD_PLAY_G2P ? (not yet) -- graph, len>0, utf8 graphemes, %s -- string, len>0, can be any string with printable ascii characters, %s - - -other limitations -================= - -- item size: header plus len=256 (valid for Pico in general) - */ - - -#ifndef PICOTOK_H_ -#define PICOTOK_H_ - -#include "picoos.h" -#include "picodata.h" -#include "picorsrc.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - - -picodata_ProcessingUnit picotok_newTokenizeUnit( - picoos_MemoryManager mm, - picoos_Common common, - picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, - picorsrc_Voice voice); - -#define PICOTOK_OUTBUF_SIZE 256 - -#ifdef __cplusplus -} -#endif - - -#endif /*PICOTOK_H_*/ diff --git a/lib/picotrns.c b/lib/picotrns.c deleted file mode 100644 index 2d16340..0000000 --- a/lib/picotrns.c +++ /dev/null @@ -1,745 +0,0 @@ -/* - * 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 picotrns.c - * - * fst processing - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#include "picoos.h" -#include "picodbg.h" -/* #include "picodata.h" */ -/* #include "picoknow.h" */ -#include "picoktab.h" -#include "picokfst.h" -#include "picotrns.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - - -picoos_uint8 picotrns_unplane(picoos_int16 symIn, picoos_uint8 * plane) { - if (symIn < 0) { - (*plane) = 0; - return (picoos_uint8) symIn; - } else { - (*plane) = symIn >> 8; - return (picoos_uint8) (symIn & 0xFF); - } -} - -#if defined(PICO_DEBUG) - -void PICOTRNS_PRINTSYM1(picoknow_KnowledgeBase kbdbg, picoos_int16 insym, picoos_uint8 phonemic) -{ -#include "picokdbg.h" - picoos_int16 sym; - picoos_uint8 plane; - picokdbg_Dbg dbg = (NULL == kbdbg) ? NULL : picokdbg_getDbg(kbdbg); - sym = picotrns_unplane(insym, &plane); - switch (plane) { - case PICOKFST_PLANE_PHONEMES: /* phones */ - if ((NULL == dbg) || !phonemic) { - PICODBG_INFO_MSG((" %c", sym)); - } else { - PICODBG_INFO_MSG((" %s", picokdbg_getPhoneSym(dbg, (picoos_uint8) sym))); - } - break; - case PICOKFST_PLANE_ACCENTS: /* accents */ - PICODBG_INFO_MSG((" {A%c}", sym)); - break; - case PICOKFST_PLANE_XSAMPA: /* xsampa symbols */ - PICODBG_INFO_MSG((" {XS:(%i)}", sym)); - break; - case PICOKFST_PLANE_POS: /* part of speech */ - PICODBG_INFO_MSG((" {P:%d}", sym)); - break; - case PICOKFST_PLANE_PB_STRENGTHS: /* phrases */ - if (sym == 48) { - PICODBG_INFO_MSG((" {WB}", sym)); - } else if (sym == 115) { - PICODBG_INFO_MSG((" {P0}", sym)); - } else { - PICODBG_INFO_MSG((" {P%c}", sym)); - } - break; - case PICOKFST_PLANE_INTERN: /* intern */ - PICODBG_INFO_MSG((" [%c]", sym)); - break; - } -} - -void PICOTRNS_PRINTSYM(picoknow_KnowledgeBase kbdbg, picoos_int16 insym) -{ - PICOTRNS_PRINTSYM1(kbdbg,insym,1); -} - -void PICOTRNS_PRINTSYMSEQ1(picoknow_KnowledgeBase kbdbg, const picotrns_possym_t seq[], const picoos_uint16 seqLen, - picoos_uint8 phonemic) { - picoos_uint16 i; - for (i=0; i= maxOutSeqLen) { - return PICO_EXC_BUF_OVERFLOW; - } - /* let j skip consonant cluster */ - accent = 0; - accentpos = 0; - while ((j < inSeqLen) && !picoktab_isSyllCarrier(phones,(picoos_uint8)inSeq[j].sym)) { - if ((inSeq[j].sym == picoktab_getPrimstressID(phones)) - || (inSeq[j].sym == picoktab_getPrimstressID(phones))) { - PICODBG_TRACE(("j skipping stress symbol inSeq[%i].sym = %c", j, inSeq[j].sym)); - accent = inSeq[j].sym; - accentpos = j; - } else { - PICODBG_TRACE(("j skipping consonant inSeq[%i].sym = %c", j, inSeq[j].sym)); - } - j++; - } - if (j < inSeqLen) { /* j is at the start of a new vowel */ - /* copy consonant cluster (moving i) to output, insert syll separator if between vowels */ - while (i < j-1) { - if ((accent > 0) && (i == accentpos)) { - PICODBG_TRACE(("skipping inSeq[%i].sym = %c (stress)", i, inSeq[i].sym)); - i++; - } else { - PICODBG_TRACE(("copying inSeq[%i].sym = %c (consonant) into output buffer", i, inSeq[i].sym)); - outSeq[out++] = inSeq[i++]; - } - } - if (vowelFound) { /* we're between vowels */ - PICODBG_TRACE(("inserting syllable separator into output buffer")); - insertSym(outSeq,out++,picoktab_getSyllboundID(phones)); - if (accent > 0) { - insertSym(outSeq,out++,accent); - } - numInserted++; - } - if ((accent > 0) && (i == accentpos)) { - PICODBG_TRACE(("skipping inSeq[%i].sym = %c (stress)", i, inSeq[i].sym)); - i++; - } else { - PICODBG_TRACE(("copying inSeq[%i].sym = %c (consonant) into output buffer", i, inSeq[i].sym)); - outSeq[out++] = inSeq[i++]; - } - vowelFound = TRUE; - /* now copy vowel cluster */ - while ((i < inSeqLen) && picoktab_isSyllCarrier(phones,(picoos_uint8)inSeq[i].sym)) { - PICODBG_TRACE(("copying inSeq[%i].sym = %c (vowel) into output buffer", i, inSeq[i].sym)); - outSeq[out++] = inSeq[i++]; - } - j = i; - } else { /* j is at end of word or end of input */ - while (i < j) { - PICODBG_TRACE(("copying inSeq[%i].sym = %c (consonant or stress) into output buffer", i, inSeq[i].sym)); - outSeq[out++] = inSeq[i++]; - } - } - *outSeqLen = out; - } - PICODBG_ASSERT((out == inSeqLen + numInserted)); - - return PICO_OK; -} - - -/* ******** +CT+: full transduction procedure **********/ - - -/* Gets next acceptable alternative for output symbol '*outSym' at current recursion position - starting from previous alternative in 'altDesc'; possibly uses input symbol - given by 'inSeq'/'inSeq'; returns whether alterative was found in '*found'; - if '*found', the other output values ('*outRefPos', '*endFSTstate', '*nextInPos'*) - return the characteristics for next recursion step; - if '*found' is false, the output values are undefined. */ - -static void GetNextAlternative (picokfst_FST fst, picotrns_AltDesc altDesc, - const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen, - picokfst_symid_t * outSym, picoos_int32 * outRefPos, - picokfst_state_t * endFSTState, picoos_int32 * nextInPos, picoos_bool * found) -{ - - picoos_bool inSymFound; - picoos_bool pairFound; - picokfst_class_t pairClass; - picoos_bool inEpsTransFound; - picokfst_symid_t inSym; - - (*found) = 0; - do { - switch (altDesc->altState) { - case 0: /* before pair search */ - if (altDesc->inPos < inSeqLen) { - inSym = inSeq[altDesc->inPos].sym; - if (inSym == PICOKFST_SYMID_EPS) { - /* very special case: input epsilon simply produces eps in output - without fst state change */ - (*found) = 1; - (*outSym) = PICOKFST_SYMID_EPS; - (*outRefPos) = inSeq[altDesc->inPos].pos; - (*endFSTState) = altDesc->startFSTState; - (*nextInPos) = altDesc->inPos + 1; - altDesc->altState = 2; - } else { - /* start search for alternatives using input symbol */ - picokfst_kfstStartPairSearch(fst,inSeq[altDesc->inPos].sym,& inSymFound,& altDesc->searchState); - if (!inSymFound) { - altDesc->altState = 2; - PICODBG_INFO_CTX(); - PICODBG_INFO_MSG((" didnt find symbol ")); - PICOTRNS_PRINTSYM(NULL, inSeq[altDesc->inPos].sym); - PICODBG_INFO_MSG(("\n")); - - } else { - altDesc->altState = 1; - } - } - } else { - altDesc->altState = 2; - } - break; - case 1: /* within pair search */ - picokfst_kfstGetNextPair(fst,& altDesc->searchState,& pairFound,& (*outSym),& pairClass); - if (pairFound) { - picokfst_kfstGetTrans(fst,altDesc->startFSTState,pairClass,& (*endFSTState)); - if ((*endFSTState) > 0) { - (*found) = 1; - (*outRefPos) = inSeq[altDesc->inPos].pos; - (*nextInPos) = altDesc->inPos + 1; - } - } else { - /* no more pair found */ - altDesc->altState = 2; - } - break; - case 2: /* before inEps trans search */ - picokfst_kfstStartInEpsTransSearch(fst,altDesc->startFSTState,& inEpsTransFound,& altDesc->searchState); - if (inEpsTransFound) { - altDesc->altState = 3; - } else { - altDesc->altState = 4; - } - break; - case 3: /* within inEps trans search */ - picokfst_kfstGetNextInEpsTrans(fst,& altDesc->searchState,& inEpsTransFound,& (*outSym),& (*endFSTState)); - if (inEpsTransFound) { - (*found) = 1; - (*outRefPos) = PICOTRNS_POS_INSERT; - (*nextInPos) = altDesc->inPos; - } else { - altDesc->altState = 4; - } - break; - case 4: /* no more alternatives */ - break; - } - } while (! ((*found) || (altDesc->altState == 4)) ); /* i.e., until (*found) || (altState == 4) */ -} - - - -/* Transfers current alternatives path stored in 'altDesc' with current path length 'pathLen' - into 'outSeq'/'outSeqLen'. The number of solutions is incremented. */ - -static void NoteSolution (picoos_uint32 * nrSol, picotrns_printSolutionFct printSolution, - picotrns_altDesc_t altDesc[], picoos_uint16 pathLen, - picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen) -{ - register picotrns_AltDesc ap; - picoos_uint32 i; - - (*nrSol)++; - (*outSeqLen) = 0; - for (i = 0; i < pathLen; i++) { - if (i < maxOutSeqLen) { - ap = &altDesc[i]; - outSeq[i].sym = ap->altOutSym; - outSeq[i].pos = ap->altOutRefPos; - (*outSeqLen)++; - } - } - if (pathLen > maxOutSeqLen) { - PICODBG_WARN(("**** output symbol array too small to hold full solution\n")); - } - if (printSolution != NULL) { - printSolution(outSeq,(*outSeqLen)); - } -} - - - -/* * - general scheme to get all solutions ("position" refers to abstract backtracking recursion depth, - which in the current solution is equal to the output symbol position): - - "set position to first position"; - "initialize alternatives in first position"; - REPEAT - IF "current state in current position is a solution" THEN - "note solution"; - END; - "get first or next acceptable alternative in current position"; - IF "acceptable alternative found" THEN - "note alternative"; - "go to next position"; - "initialize alternatives in that position"; - ELSE - "step back to previous position"; - END; - UNTIL "current position is before first position" -***/ - - -/* Initializes transduction state for further use in repeated application - of 'TransductionStep'. */ - -static void StartTransduction (struct picotrns_transductionState * transductionState) -{ - (*transductionState).phase = 0; -} - - - -/* Performs one step in the transduction of 'inSeqLen' input symbols with corresponding - reference positions in 'inSeq'. '*transductionState' must have been - initialized by 'StartTransduction'. Repeat calls to this procedure until '*finished' returns true. - The output is returned in 'outSeqLen' symbols and reference positions in 'outSeq'. - The output reference positions refer to the corresponding input reference positions. - Inserted output symbols receive the reference position -1. If several solutions are possible, - only the last found solution is returned. - 'altDesc' is a temporary workspace which should be at least one cell longer than 'outSeq'. - 'firstSolOnly' determines whether only the first solution should be found or if - the search should go on to find all solutions (mainly for testing purposes). - - NOTE: current version written for use in single repetitive steps; - could be simplified if full transduction can be done as an atomic operation */ - -static void TransductionStep (picokfst_FST fst, struct picotrns_transductionState * transductionState, - picotrns_altDesc_t altDesc[], picoos_uint16 maxAltDescLen, - picoos_bool firstSolOnly, picotrns_printSolutionFct printSolution, - const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen, - picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen, - picoos_bool * finished) -{ - register picotrns_AltDesc ap; - picoos_int32 i; - picokfst_state_t endFSTState; - picoos_int32 nextInPos; - picoos_bool found; - picokfst_symid_t outSym; - picoos_int32 outRefPos; - picoos_int32 tmpRecPos; - - (*finished) = 0; - tmpRecPos = (*transductionState).recPos; - switch ((*transductionState).phase) { - case 0: /* before initialization */ - (*transductionState).nrSol = 0; - - /* check for initial solution (empty strings are always accepted) */ - if (inSeqLen == 0) { - NoteSolution(& (*transductionState).nrSol,printSolution,altDesc,0,outSeq,outSeqLen,maxOutSeqLen); - } - - /* initialize first recursion position */ - tmpRecPos = 0; - ap = & altDesc[0]; - ap->startFSTState = 1; - ap->inPos = 0; - ap->altState = 0; - (*transductionState).phase = 1; - break; - - case 1: /* before regular recursion step */ - if ((tmpRecPos < 0) || (firstSolOnly && ((*transductionState).nrSol > 0))) { - /* end reached */ - (*transductionState).phase = 2; - } else { - /* not finished; do regular step */ - - /* get first or next acceptable alternative in current position */ - GetNextAlternative(fst,& altDesc[tmpRecPos],inSeq,inSeqLen,& outSym,& outRefPos,& endFSTState,& nextInPos,& found); - if (found) { - /* note alternative in current position */ - ap = & altDesc[tmpRecPos]; - ap->altOutSym = outSym; - ap->altOutRefPos = outRefPos; - - /* check for solution after found alternative */ - if ((nextInPos == inSeqLen) && picokfst_kfstIsAcceptingState(fst,endFSTState)) { - NoteSolution(& (*transductionState).nrSol,printSolution,altDesc,tmpRecPos+1, - outSeq,outSeqLen,maxOutSeqLen); - } - - /* go to next position if possible, start search for follower alternative symbols */ - if (tmpRecPos < maxAltDescLen-1) { - /* got to next position */ - tmpRecPos = tmpRecPos + 1; - - /* initialize alternatives in new position */ - ap = & altDesc[tmpRecPos]; - ap->startFSTState = endFSTState; - ap->inPos = nextInPos; - ap->altState = 0; - - } else { - /* do not go on due to limited path but still treat alternatives in current position */ - PICODBG_WARN(("--- transduction path too long; may fail to find solution\n")); - } - } else { /* no more acceptable alternative found in current position */ - /* backtrack to previous recursion */ - tmpRecPos = tmpRecPos - 1; - } - } - break; - - case 2: /* before finish */ - if ((*transductionState).nrSol == 0) { - PICODBG_WARN(("--- no transduction solution found, using input as output\n")); - i = 0; - while ((i < inSeqLen) && (i < maxOutSeqLen)) { - outSeq[i].sym = inSeq[i].sym; - outSeq[i].pos = inSeq[i].pos; - i++; - } - (*outSeqLen) = i; - } else if ((*transductionState).nrSol > 1) { - PICODBG_WARN(("--- more than one transducer solutions found\n")); - } - (*transductionState).phase = 3; - break; - - case 3: /* after finish */ - (*finished) = 1; - break; - } - (*transductionState).recPos = tmpRecPos; -} - - - -/* see description in header */ -pico_status_t picotrns_transduce (picokfst_FST fst, picoos_bool firstSolOnly, - picotrns_printSolutionFct printSolution, - const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen, - picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen, - picotrns_AltDesc altDescBuf, picoos_uint16 maxAltDescLen, - picoos_uint32 *nrSteps) -{ - struct picotrns_transductionState transductionState; - picoos_bool finished; - -#if defined(PICO_DEBUG) - { - picoos_uint16 i; - - PICODBG_INFO_CTX(); - PICODBG_INFO_MSG(("got input: ")); - for (i=0; ipossymBuf = transducer->possymBufA; - transducer->possymBufTmp = transducer->possymBufB; - transducer->possymReadPos = 0; - transducer->possymWritePos = 0; - return PICO_OK; -} -/** creates a SimpleTranducer with a working buffer of given size - * - * @param mm MemoryManager handle - * @param common Common handle - * @param maxAltDescLen maximal size for working buffer (in bytes) - * @return handle to new SimpleTransducer or NULL if error - */ -picotrns_SimpleTransducer picotrns_newSimpleTransducer(picoos_MemoryManager mm, - picoos_Common common, - picoos_uint16 maxAltDescLen) -{ - picotrns_SimpleTransducer this; - this = picoos_allocate(mm, sizeof(picotrns_simple_transducer_t)); - if (this == NULL) { - picoos_deallocate(mm, (void *)&this); - picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); - return NULL; - } - - /* allocate working buffer */ - this->altDescBuf = picotrns_allocate_alt_desc_buf(mm, maxAltDescLen, &this->maxAltDescLen); - if (this->altDescBuf == NULL) { - picoos_deallocate(mm, (void *)&this); - picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); - return NULL; - } - this->common = common; - picotrns_stInitialize(this); - return this; -} -/** disposes a SimpleTransducer - * - * @param this - * @param mm - * @return PICO_OK - */ -pico_status_t picotrns_disposeSimpleTransducer(picotrns_SimpleTransducer * this, - picoos_MemoryManager mm) -{ - if (NULL != (*this)) { - picotrns_deallocate_alt_desc_buf(mm,&(*this)->altDescBuf); - picoos_deallocate(mm, (void *) this); - (*this) = NULL; - } - return PICO_OK; -} - -/** transduces the contents previously inserted via @ref picotrns_newSimpleTransducer and @ref - * picotrns_disposeSimpleTransducer. - * - * @param this - * @param fst - * @return - */ -pico_status_t picotrns_stTransduce(picotrns_SimpleTransducer this, picokfst_FST fst) -{ - picoos_uint16 outSeqLen; - picoos_uint32 nrSteps; - pico_status_t status; - - status = picotrns_transduce(fst,TRUE,NULL, - this->possymBuf, this->possymWritePos, - this->possymBufTmp,&outSeqLen, PICOTRNS_MAX_NUM_POSSYM, - this->altDescBuf,this->maxAltDescLen,&nrSteps); - if (PICO_OK != status) { - return status; - } - return picotrns_eliminate_epsilons(this->possymBufTmp,outSeqLen,this->possymBuf,&this->possymWritePos,PICOTRNS_MAX_NUM_POSSYM); -} - -/** - * Add chars from NULLC-terminated string \c inStr, shifted to plane \c plane, to internal input buffer of - * \c transducer. - * - * @param this is an initialized picotrns_SimpleTransducer - * @param inStr NULLC-terminated byte sequence - * @param plane - * @return PICO_OK, if all bytes fit into buffer, or PICO_EXC_BUF_OVERFLOW otherwise - */ -pico_status_t picotrns_stAddWithPlane(picotrns_SimpleTransducer this, picoos_char * inStr, picoos_uint8 plane) -{ - while ((*inStr) && (this->possymWritePos < PICOTRNS_MAX_NUM_POSSYM)) { - this->possymBuf[this->possymWritePos].pos = PICOTRNS_POS_INSERT; - this->possymBuf[this->possymWritePos].sym = (plane << 8) + (*inStr); - PICODBG_DEBUG(("inserting pos/sym = %i/'%c' at pos %i", - this->possymBuf[this->possymWritePos].pos, - this->possymBuf[this->possymWritePos].sym, - this->possymWritePos)); - this->possymWritePos++; - inStr++; - } - if (!(*inStr)) { - return PICO_OK; - } else { - return PICO_EXC_BUF_OVERFLOW; - } -} - -pico_status_t picotrns_stGetSymSequence( - picotrns_SimpleTransducer this, - picoos_uint8 * outputSymIds, - picoos_uint32 maxOutputSymIds) -{ - picoos_uint8 plane; - picoos_uint32 outputCount = 0; - while ((this->possymReadPos < this->possymWritePos) && (outputCount < maxOutputSymIds)) { - *outputSymIds++ = picotrns_unplane(this->possymBuf[this->possymReadPos++].sym, &plane); - outputCount++; - } - *outputSymIds = NULLC; - if (outputCount <= maxOutputSymIds) { - return PICO_OK; - } else { - return PICO_EXC_BUF_OVERFLOW; - } -} - -#ifdef __cplusplus -} -#endif - -/* end picotrns.c */ diff --git a/lib/picotrns.h b/lib/picotrns.h deleted file mode 100644 index f535ce0..0000000 --- a/lib/picotrns.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * 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 picotrns.h - * - * fst processing - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -/** @addtogroup picotrns - * - * Conventions: - * - * - The input to the transducer is a list of pos/sym pairs, where pos are arbitrary position markers - * - All positions are allowed on input (in particular all those coming as an output of a previous transduction) - * - A phone sequence to be transduced has to begin with PICOKNOW_PHON_START_ID and end with PICOKNOW_PHON_TERM_ID - * These special symbols are kept in the transduction output (as first and last symbol) - * - Symbols inserted by the transduction process allways get their position marker pos=PICOTRNS_POS_INSERT - * - The order of positions on output must be the same as that on input, i.e. apart from inserted pairs, the - * output position sequence must be a sub-sequence of the input position sequence. - * - Inserted symbols are allways preceded by a positioned pos/sym pair, e.g. - * if the sequence pos1/sym1, pos2/sym2 should be tranduced to x/sym3, y/sym4, z/sym5, then x must be pos1 or pos2 - * and not PICOTRNS_POS_INSERT - * - * For lingware developers: Insertions are always interpreted "to the right" - * - E.g.: The original sequence is phon1 , command , phon2 - * - The input to the transducer is then pos1/phon1 , pos2/phon2 - * - The output is pos1/phon1' -1/phon_ins pos2/phon2' [assuming -1 is the special insertion pos] - * - Then the new sequence will be recomposed as phon1' , phon_ins , command , phon2' [note position of command!] - * - To overwrite this behaviour, rules must be formulated such that the transduction output is - * pos1/phon1' pos2/phon_ins -1/phon2' - */ -#ifndef PICOTRNS_H_ -#define PICOTRNS_H_ - -#include "picoos.h" -#include "picokfst.h" -#include "picoktab.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -#define PICOTRNS_MAX_NUM_POSSYM 255 - -#define PICOTRNS_POS_INSERT (picoos_int16) -1 /* position returned by transducer to mark symbols inserted by the transducer */ -#define PICOTRNS_POS_INVALID (picoos_int16) -2 /* value to mark an invalid (e.g. uninitiated) position */ -#define PICOTRNS_POS_IGNORE (picoos_int16) -3 /* value to mark a pos/sym pair to be ignored (e.g. start/term symbols only used by the transducer) */ - - -typedef struct picotrns_possym { - picoos_int16 pos; - picoos_int16 sym; -} picotrns_possym_t; - -picoos_uint8 picotrns_unplane(picoos_int16 symIn, picoos_uint8 * plane); - - -#if defined(PICO_DEBUG) - -void PICOTRNS_PRINTSYM(picoknow_KnowledgeBase kbdbg, picoos_int16 insym); - -void PICOTRNS_PRINTSYMSEQ(picoknow_KnowledgeBase kbdbg, const picotrns_possym_t seq[], const picoos_uint16 seqLen); - -void picotrns_printSolution(const picotrns_possym_t outSeq[], const picoos_uint16 outSeqLen); - -#else -#define PICOTRNS_PRINTSYM(x,y) -#define PICOTRNS_PRINTSYMSEQ(x,y,z) -#define picotrns_printSolution NULL -#endif - - -typedef struct picotrns_altDesc * picotrns_AltDesc; - - -picotrns_AltDesc picotrns_allocate_alt_desc_buf(picoos_MemoryManager mm, picoos_uint32 maxByteSize, picoos_uint16 * numAltDescs); - -void picotrns_deallocate_alt_desc_buf(picoos_MemoryManager mm, picotrns_AltDesc * altDescBuf); - - -/* type of function for printing transduction solutions; - only for testing purposes in transduction mode where all solutions - are produced */ -typedef void picotrns_printSolutionFct(const picotrns_possym_t outSeq[], const picoos_uint16 outSeqLen); - - - -/** overall transduction; transduces 'inSeq' with 'inSeqLen' elements - to '*outSeqLen' elements in 'outSeq'; - * - * @param fst the finite-state transducer used for transduction - * @param firstSolOnly determines whether only the first solution (usually) - or all solutions should be produced (for testing); only the last found - solution is returned in 'outSeq'; - * @param printSolution if not NULL, every found solution is displayed using - the given function - * @param inSeq the input sequence - * @param inSeqLen the input sequence length - * @retval outSeq the output sequence - * @retval outSeqLen the output sequence length - * @param maxOutSeqLen must provide the maximum length of 'outSeq' - * @param altDescBuf must provide a working array of length 'maxAltDescLen' - * @param maxAltDescLen should be chosen at least 'maxOutSeqLen' + 1 - * @retval nrSteps returns the overall internal number of iterative steps done - * @return status of the transduction: PICO_OK, if transduction successful - @note if 'outSeq' or 'altDesc' are too small to hold a solution, - an error occurs and the input is simply transfered to the output - (up to maximum possible length) - */ -extern pico_status_t picotrns_transduce (picokfst_FST fst, picoos_bool firstSolOnly, - picotrns_printSolutionFct printSolution, - const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen, - picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen, - picotrns_AltDesc altDescBuf, picoos_uint16 maxAltDescLen, - picoos_uint32 *nrSteps); - - - -/* transduce 'inSeq' into 'outSeq' 'inSeq' has to be terminated with the id for symbol '#'. 'outSeq' is terminated in the same way. */ -/* -pico_status_t picotrns_transduce_sequence(picokfst_FST fst, const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen, - picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen); -*/ - -/* copy elements from inSeq to outSeq, ignoring elements with epsilon symbol */ -pico_status_t picotrns_eliminate_epsilons(const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen, - picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen); - -/* copy elements from inSeq to outSeq, inserting syllable separators in some trivial way. - * inSeq is assumed to be at most, outSeq at least of size PICOTRNS_MAX_NUM_POSSYM */ -pico_status_t picotrns_trivial_syllabify(picoktab_Phones phones, - const picotrns_possym_t inSeq[], const picoos_uint16 inSeqLen, - picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen); - - -/** object : SimpleTransducer - * shortcut : st - * - */ -typedef struct picotrns_simple_transducer * picotrns_SimpleTransducer; - -picotrns_SimpleTransducer picotrns_newSimpleTransducer(picoos_MemoryManager mm, - picoos_Common common, - picoos_uint16 maxAltDescLen); - -pico_status_t picotrns_disposeSimpleTransducer(picotrns_SimpleTransducer * this, - picoos_MemoryManager mm); - -pico_status_t picotrns_stInitialize(picotrns_SimpleTransducer transducer); - -pico_status_t picotrns_stAddWithPlane(picotrns_SimpleTransducer this, picoos_char * inStr, picoos_uint8 plane); - -pico_status_t picotrns_stTransduce(picotrns_SimpleTransducer this, picokfst_FST fst); - -pico_status_t picotrns_stGetSymSequence( - picotrns_SimpleTransducer this, - picoos_uint8 * outputSymIds, - picoos_uint32 maxOutputSymIds); - - - - - -#ifdef __cplusplus -} -#endif - -#endif /*PICOTRNS_H_*/ diff --git a/lib/picowa.c b/lib/picowa.c deleted file mode 100644 index 3e793c9..0000000 --- a/lib/picowa.c +++ /dev/null @@ -1,578 +0,0 @@ -/* - * 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 picowa.c - * - * word analysis PU - lexicon lookup and POS prediction - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - -#include "picoos.h" -#include "picodbg.h" -#include "picodata.h" -#include "picowa.h" -#include "picoklex.h" -#include "picokdt.h" -#include "picoktab.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - -/* PU waStep states */ -#define WA_STEPSTATE_COLLECT 0 -#define WA_STEPSTATE_PROCESS 1 -#define WA_STEPSTATE_FEED 2 - - -/* subobject : WordAnaUnit - * shortcut : wa - * context size : one item - */ -typedef struct wa_subobj { - picoos_uint8 procState; /* for next processing step decision */ - - /* one item only */ - picoos_uint8 inBuf[PICOWA_MAXITEMSIZE]; /* internal input buffer */ - picoos_uint16 inBufSize; /* actually allocated size */ - picoos_uint16 inLen; /* length of item in inBuf, 0 for empty buf */ - - picoos_uint8 outBuf[PICOWA_MAXITEMSIZE]; /* internal output buffer */ - picoos_uint16 outBufSize; /* actually allocated size */ - picoos_uint16 outLen; /* length of item in outBuf, 0 for empty buf */ - - /* lex knowledge base */ - picoklex_Lex lex; - - /* ulex knowledge bases */ - picoos_uint8 numUlex; - picoklex_Lex ulex[PICOKNOW_MAX_NUM_ULEX]; - - /* tab knowledge base */ - picoktab_Pos tabpos; - - /* dtposp knowledge base */ - picokdt_DtPosP dtposp; -} wa_subobj_t; - - -static pico_status_t waInitialize(register picodata_ProcessingUnit this) { - picoos_uint8 i; - picoklex_Lex ulex; - wa_subobj_t * wa; - - picoknow_kb_id_t ulexKbIds[PICOKNOW_MAX_NUM_ULEX] = PICOKNOW_KBID_ULEX_ARRAY; - - PICODBG_DEBUG(("calling")); - - if (NULL == this || NULL == this->subObj) { - return (picodata_step_result_t) picoos_emRaiseException(this->common->em, - PICO_ERR_NULLPTR_ACCESS, NULL, NULL); - } - wa = (wa_subobj_t *) this->subObj; - wa->procState = WA_STEPSTATE_COLLECT; - wa->inBufSize = PICOWA_MAXITEMSIZE; - wa->inLen = 0; - wa->outBufSize = PICOWA_MAXITEMSIZE; - wa->outLen = 0; - - /* kb lex */ - wa->lex = picoklex_getLex(this->voice->kbArray[PICOKNOW_KBID_LEX_MAIN]); - if (wa->lex == NULL) { - return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - PICODBG_DEBUG(("got lex")); - - /* kb ulex[] */ - wa->numUlex = 0; - for (i = 0; ivoice->kbArray[ulexKbIds[i]]); - if (NULL != ulex) { - wa->ulex[wa->numUlex++] = ulex; - } - } - PICODBG_DEBUG(("got %i user lexica", wa->numUlex)); - - /* kb tabpos */ - wa->tabpos = - picoktab_getPos(this->voice->kbArray[PICOKNOW_KBID_TAB_POS]); - if (wa->tabpos == NULL) { - return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - PICODBG_DEBUG(("got tabpos")); - - /* kb dtposp */ - wa->dtposp = picokdt_getDtPosP(this->voice->kbArray[PICOKNOW_KBID_DT_POSP]); - if (wa->dtposp == NULL) { - return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, - NULL, NULL); - } - PICODBG_DEBUG(("got dtposp")); - return PICO_OK; -} - -static picodata_step_result_t waStep(register picodata_ProcessingUnit this, - picoos_int16 mode, - picoos_uint16 *numBytesOutput); - -static pico_status_t waTerminate(register picodata_ProcessingUnit this) { - return PICO_OK; -} - -static pico_status_t waSubObjDeallocate(register picodata_ProcessingUnit this, - picoos_MemoryManager mm) { - if (NULL != this) { - picoos_deallocate(this->common->mm, (void *) &this->subObj); - } - mm = mm; /* avoid warning "var not used in this function"*/ - return PICO_OK; -} - - -picodata_ProcessingUnit picowa_newWordAnaUnit(picoos_MemoryManager mm, - picoos_Common common, - picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, - picorsrc_Voice voice) { - picodata_ProcessingUnit this; - - this = picodata_newProcessingUnit(mm, common, cbIn, cbOut, voice); - if (this == NULL) { - return NULL; - } - - this->initialize = waInitialize; - PICODBG_DEBUG(("set this->step to waStep")); - this->step = waStep; - this->terminate = waTerminate; - this->subDeallocate = waSubObjDeallocate; - this->subObj = picoos_allocate(mm, sizeof(wa_subobj_t)); - if (this->subObj == NULL) { - picoos_deallocate(mm, (void *)&this); - picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); - return NULL; - } - - waInitialize(this); - return this; -} - -/* ***********************************************************************/ -/* WORDGRAPH proc functions */ -/* ***********************************************************************/ - -static picoos_uint8 waClassifyPos(register picodata_ProcessingUnit this, - register wa_subobj_t *wa, - const picoos_uint8 *graph, - const picoos_uint16 graphlen) { - picokdt_classify_result_t dtres; - picoos_uint8 specchar; - picoos_uint16 i; - - PICODBG_DEBUG(("graphlen %d", graphlen)); - - /* check existence of special char (e.g. hyphen) in graph: - for now, check existence of hard-coded ascii hyphen, - ie. preproc needs to match all UTF8 hyphens to the ascii - hyphen. */ - /* @todo : consider specifying special char(s) in lingware. */ - specchar = FALSE; - i = 0; - while ((i < graphlen) && (!specchar)) { - if (graph[i++] == '-') { - specchar = TRUE; - } - } - - /* construct input vector, which is set in dtposp */ - if (!picokdt_dtPosPconstructInVec(wa->dtposp, graph, graphlen, specchar)) { - /* error constructing invec */ - PICODBG_WARN(("problem with invec")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, NULL, NULL); - return PICODATA_ITEMINFO1_ERR; - } - - /* classify */ - if (!picokdt_dtPosPclassify(wa->dtposp)) { - /* error doing classification */ - PICODBG_WARN(("problem classifying")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, - NULL, NULL); - return PICODATA_ITEMINFO1_ERR; - } - - /* decompose */ - if (!picokdt_dtPosPdecomposeOutClass(wa->dtposp, &dtres)) { - /* error decomposing */ - PICODBG_WARN(("problem decomposing")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_OUTVECTOR, - NULL, NULL); - return PICODATA_ITEMINFO1_ERR; - } - - if (dtres.set) { - PICODBG_DEBUG(("class %d", dtres.class)); - return (picoos_uint8)dtres.class; - } else { - PICODBG_WARN(("result not set")); - picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, - NULL, NULL); - return PICODATA_ITEMINFO1_ERR; - } -} - - -static pico_status_t waProcessWordgraph(register picodata_ProcessingUnit this, - register wa_subobj_t *wa /*inout*/, - picodata_itemhead_t *head /*inout*/, - const picoos_uint8 *content) { - pico_status_t status; - picoklex_lexl_result_t lexres; - picoos_uint8 posbuf[PICOKTAB_MAXNRPOS_IN_COMB]; - picoos_uint8 i; - picoos_uint8 foundIndex; - picoos_bool found; - - - PICODBG_DEBUG(("type %c, len %d", head->type, head->len)); - - /* do lookup - if no entry found: - do POS prediction: -> WORDGRAPH(POSes,NA)graph - else: - if incl-phone: - N entries possible -> WORDINDEX(POSes,NA)POS1|ind1...POSN|indN - (N in {1,...,PICOKLEX_MAX_NRRES}, now up to 4) - else: - no phone, one entry -> WORDGRAPH(POS,NA)graph - */ - - found = FALSE; - i = 0; - while (!found && (i < wa->numUlex)) { - found = picoklex_lexLookup(wa->ulex[i], content, head->len, &lexres); - i++; - } - /* note that if found, i will be incremented nevertheless, so i >= 1 */ - if (found) { - foundIndex = i; - } else { - foundIndex = 0; - } - if (!found && !picoklex_lexLookup(wa->lex, content, head->len, &lexres)) { - /* no lex entry found, WORDGRAPH(POS,NA)graph */ - if (PICO_OK == picodata_copy_item(wa->inBuf, wa->inLen, - wa->outBuf, wa->outBufSize, - &wa->outLen)) { - wa->inLen = 0; - /* predict and modify pos in info1 */ - if (PICO_OK != picodata_set_iteminfo1(wa->outBuf, wa->outLen, - waClassifyPos(this, wa, content, head->len))) { - return picoos_emRaiseException(this->common->em, - PICO_EXC_BUF_OVERFLOW,NULL,NULL); - } - } - - } else { /* at least one entry found */ - PICODBG_DEBUG(("at least one entry found in lexicon %i",foundIndex)); - if (lexres.phonfound) { /* incl. ind-phone and possibly multi-ent. */ - if (lexres.nrres > PICOKLEX_MAX_NRRES) { - /* not possible with system lexicon, needs to be - ensured for user lex too */ - picoos_emRaiseWarning(this->common->em, PICO_WARN_FALLBACK,NULL, - (picoos_char *)"using %d lexicon lookup results", - PICOKLEX_MAX_NRRES); - lexres.nrres = PICOKLEX_MAX_NRRES; - } - head->type = PICODATA_ITEM_WORDINDEX; - if (lexres.nrres == 1) { - head->info1 = lexres.posind[0]; - } else { - /* more than one result, POSgroup info needs to be - determined for later POS disambiguation */ - for (i = 0; i < lexres.nrres; i++) { - posbuf[i] = lexres.posind[i * PICOKLEX_POSIND_SIZE]; - } - head->info1 = picoktab_getPosGroup(wa->tabpos, posbuf, - lexres.nrres); - } - head->info2 = foundIndex; - head->len = lexres.posindlen; - if ((status = picodata_put_itemparts(head, lexres.posind, - lexres.posindlen, - wa->outBuf, wa->outBufSize, - &wa->outLen)) == PICO_OK) { - wa->inLen = 0; - } else { - return picoos_emRaiseException(this->common->em, status, - NULL, NULL); - } - - } else { /* no phone, :G2P, one entry: WORDGRAPH(POS,NA)graph */ - if (PICO_OK == picodata_copy_item(wa->inBuf, wa->inLen, - wa->outBuf, wa->outBufSize, - &wa->outLen)) { - wa->inLen = 0; - /* set lex pos in info1 */ - if (PICO_OK != picodata_set_iteminfo1(wa->outBuf, wa->outLen, - lexres.posind[0])) { - return picoos_emRaiseException(this->common->em, - PICO_EXC_BUF_OVERFLOW, - NULL, NULL); - } - } - } - } - return PICO_OK; -} - - -/* ***********************************************************************/ -/* waStep function */ -/* ***********************************************************************/ - -/* - collect into internal buffer, process, and then feed to output buffer - - init state: COLLECT ext ext - state transitions: in IN OUTout - COLLECT | getOneItem ->-1 +1 0 0 | (ATOMIC) -> PROCESS (got item) - COLLECT | getOneItem -> 0 0 0 0 | IDLE (got no item) - - PROCESS | procOneItem -> 0 -1 +1 0 | (ATOMIC) -> FEED (proc'ed item) - PROCESS | procOneItem -> 0 -1 0 0 | BUSY -> COLLECT (item skipped) - - FEED | putOneItem -> 0 0 -1 +1 | BUSY -> COLLECT (put item) - FEED | putOneItem -> 0 0 1 0 | OUT_FULL (put no item) -*/ - -static picodata_step_result_t waStep(register picodata_ProcessingUnit this, - picoos_int16 mode, - picoos_uint16 * numBytesOutput) { - register wa_subobj_t *wa; - pico_status_t rv = PICO_OK; - - if (NULL == this || NULL == this->subObj) { - return PICODATA_PU_ERROR; - } - wa = (wa_subobj_t *) this->subObj; - mode = mode; /* avoid warning "var not used in this function"*/ - *numBytesOutput = 0; - while (1) { /* exit via return */ - PICODBG_DEBUG(("doing state %i, inLen: %d, outLen: %d", - wa->procState, wa->inLen, wa->outLen)); - - switch (wa->procState) { - /* collect state: get item from charBuf and store in - * internal inBuf - */ - case WA_STEPSTATE_COLLECT: - if (wa->inLen == 0) { /* is input buffer empty? */ - picoos_uint16 blen; - /* try to get one item */ - rv = picodata_cbGetItem(this->cbIn, wa->inBuf, - wa->inBufSize, &blen); - PICODBG_DEBUG(("after getting item, status: %d", rv)); - if (PICO_OK == rv) { - /* we now have one item */ - wa->inLen = blen; - wa->procState = WA_STEPSTATE_PROCESS; - /* uncomment next line to split into two steps */ - /* return PICODATA_PU_ATOMIC; */ - } else if (PICO_EOF == rv) { - /* there was no item in the char buffer */ - return PICODATA_PU_IDLE; - } else if ((PICO_EXC_BUF_UNDERFLOW == rv) - || (PICO_EXC_BUF_OVERFLOW == rv)) { - PICODBG_ERROR(("problem getting item")); - picoos_emRaiseException(this->common->em, rv, - NULL, NULL); - return PICODATA_PU_ERROR; - } else { - PICODBG_ERROR(("problem getting item, unhandled")); - picoos_emRaiseException(this->common->em, rv, - NULL, NULL); - return PICODATA_PU_ERROR; - } - } else { /* there already is an item in the input buffer */ - PICODBG_WARN(("item already in input buffer")); - picoos_emRaiseWarning(this->common->em, - PICO_WARN_PU_IRREG_ITEM, NULL, NULL); - wa->procState = WA_STEPSTATE_PROCESS; - /* uncomment next to split into two steps */ - /* return PICODATA_PU_ATOMIC; */ - } - break; - - - /* process state: process item in internal inBuf and put - * result in internal outBuf - */ - case WA_STEPSTATE_PROCESS: - - /* ensure there is an item in inBuf and it is valid */ - if ((wa->inLen > 0) && picodata_is_valid_item(wa->inBuf, - wa->inLen)) { - picodata_itemhead_t ihead; - picoos_uint8 *icontent; - pico_status_t rvP = PICO_OK; - - rv = picodata_get_iteminfo(wa->inBuf, wa->inLen, &ihead, - &icontent); - if (PICO_OK == rv) { - - switch (ihead.type) { - case PICODATA_ITEM_WORDGRAPH: - - if (0 < ihead.len) { - rvP = waProcessWordgraph(this, wa, &ihead, - icontent); - } else { - /* else ignore empty WORDGRAPH */ - wa->inLen = 0; - wa->procState = WA_STEPSTATE_COLLECT; - return PICODATA_PU_BUSY; - } - break; - case PICODATA_ITEM_OTHER: - /* skip item */ - rvP = PICO_WARN_PU_DISCARD_BUF; - break; - default: - /* copy item unmodified */ - rvP = picodata_copy_item(wa->inBuf, - wa->inLen, wa->outBuf, - wa->outBufSize, &wa->outLen); - break; - } - - if (PICO_OK == rvP) { - wa->inLen = 0; - wa->procState = WA_STEPSTATE_FEED; - /* uncomment next to split into two steps */ - /* return PICODATA_PU_ATOMIC; */ - } else if (PICO_WARN_PU_DISCARD_BUF == rvP) { - /* discard input buffer and get a new item */ - PICODBG_INFO(("skipping OTHER item")); -/* picoos_emRaiseWarning(this->common->em, - PICO_WARN_PU_DISCARD_BUF, NULL, NULL); -*/ - wa->inLen = 0; - wa->procState = WA_STEPSTATE_COLLECT; - return PICODATA_PU_BUSY; - } else { - /* PICO_EXC_BUF_OVERFLOW <- overflow in outbuf - PICO_ERR_OTHER <- no valid item in inbuf - or return from processWordgraph - */ - PICODBG_ERROR(("problem processing item", rvP)); - picoos_emRaiseException(this->common->em, rvP, - NULL, NULL); - return PICODATA_PU_ERROR; - } - - } else { /* could not get iteminfo */ - /* PICO_EXC_BUF_OVERFLOW <- overflow in outbuf - PICO_ERR_OTHER <- no valid item in inbuf - */ - PICODBG_ERROR(("problem getting item info, " - "discard buffer content")); - wa->inLen = 0; - wa->procState = WA_STEPSTATE_COLLECT; - picoos_emRaiseException(this->common->em, rv, - NULL, NULL); - return PICODATA_PU_ERROR; - } - - } else if (wa->inLen == 0) { /* no item in inBuf */ - PICODBG_INFO(("no item in inBuf")); - /* wa->inLen = 0;*/ - wa->procState = WA_STEPSTATE_COLLECT; - return PICODATA_PU_BUSY; - - } else { /* no valid item in inBuf */ - /* bad state/item, discard buffer content */ - PICODBG_WARN(("no valid item, discard buffer content")); - picoos_emRaiseWarning(this->common->em, - PICO_WARN_PU_IRREG_ITEM, NULL, NULL); - picoos_emRaiseWarning(this->common->em, - PICO_WARN_PU_DISCARD_BUF, NULL, NULL); - wa->inLen = 0; - wa->procState = WA_STEPSTATE_COLLECT; - return PICODATA_PU_BUSY; - } - break; - - - /* feed state: copy item in internal outBuf to output charBuf */ - case WA_STEPSTATE_FEED: - - /* check that item fits in cb should not be needed */ - rv = picodata_cbPutItem(this->cbOut, wa->outBuf, - wa->outLen, numBytesOutput); - - PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], - (picoos_uint8 *)"wana: ", wa->outBuf, - wa->outLen); - - PICODBG_DEBUG(("put item, status: %d", rv)); - if (PICO_OK == rv) { - wa->outLen = 0; - wa->procState = WA_STEPSTATE_COLLECT; - return PICODATA_PU_BUSY; - } else if (PICO_EXC_BUF_OVERFLOW == rv) { - PICODBG_INFO(("feeding, overflow, PICODATA_PU_OUT_FULL")); - return PICODATA_PU_OUT_FULL; - } else if ((PICO_EXC_BUF_UNDERFLOW == rv) - || (PICO_ERR_OTHER == rv)) { - PICODBG_WARN(("feeding problem, discarding item")); - wa->outLen = 0; - wa->procState = WA_STEPSTATE_COLLECT; - picoos_emRaiseWarning(this->common->em, rv, NULL,NULL); - return PICODATA_PU_BUSY; - } - break; - - default: - break; - - } /* switch */ - - } /* while */ - - /* should be never reached */ - PICODBG_ERROR(("reached end of function")); - picoos_emRaiseException(this->common->em, PICO_ERR_OTHER, NULL, NULL); - return PICODATA_PU_ERROR; -} - -#ifdef __cplusplus -} -#endif - - -/* end */ diff --git a/lib/picowa.h b/lib/picowa.h deleted file mode 100644 index d7fbcd3..0000000 --- a/lib/picowa.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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 picowa.h - * - * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland - * All rights reserved. - * - * History: - * - 2009-04-20 -- initial version - * - */ - - -/** - * @addtogroup picowa - * ---------------------------------------------------\n - * Pico Word Analysis \n - * ---------------------------------------------------\n -itemtype, iteminfo1, iteminfo2, content -> TYPE(INFO1,INFO2)content -in the following - -items input\n -=========== - -processed by wa: -- WORDGRAPH(NA,NA)graph -- OTHER(NA,NA)string - -unprocessed: -- all other item types are forwarded through the PU without modification: - - PUNC - - CMD - - -minimal input size (before processing starts)\n -================== - -processing (ie. lex lookup and POS prediction) is possible with -- one item - - -items processed and output\n -========================== - -processing an input WORDGRAPH results in one of the following items: -- WORDGRAPH(POSes,NA)graph - - graph not in lex, POSes determined with dtree, or - - graph in lex - single entry without phone (:G2P), POSes from lex -- WORDINDEX(POSes,NA)pos1|ind1...posN|indN - - graph in lex - {1,4} entries with phone, pos1...posN from lex, - {1,4} lexentries indices in content, POSes combined with map table - in klex - -processing an input OTHER results in the item being skipped (in the -future this can be extended to e.g. spelling) - -see picotok.h for PUNC and CMD - -- POSes %d - - is the superset of all single POS and POS combinations defined - in the lingware as unique symbol -- graph, len>0, utf8 graphemes, %s -- pos1|ind1, pos2|ind2, ..., posN|indN - - pos? are the single, unambiguous POS only, one byte %d - - ind? are the lexentry indices, three bytes %d %d %d - - -lexicon (system lexicon, but must also be ensured for user lexica)\n -======= - -- POS GRAPH PHON, all mandatory, but - - * PHON can be an empty string -> no pronunciation in the resulting TTS output - - * PHON can be :G2P -> use G2P later to add pronunciation -- (POS,GRAPH) is a uniq key (only one entry allowed) -- (GRAPH) is almost a uniq key (2-4 entries with the same GRAPH, and - differing POS and differing PHON possible) - - for one graph we can have 2-4 solutions from the lex which all - need to be passed on the the next PU - - in this case GRAPH, POS, and PHON all must be available in lex - - in this case for each entry only a non-ambiguous, unique POS ID - is possible) - -other limitations\n -================= - -- item size: header plus len=256 (valid for Pico in general) -- wa uses one item context only -> internal buffer set to 256+4 - */ - - -#ifndef PICOWA_H_ -#define PICOWA_H_ - -#include "picoos.h" -#include "picodata.h" -#include "picorsrc.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -} -#endif - - -/* maximum length of an item incl. head for input and output buffers */ -#define PICOWA_MAXITEMSIZE 260 - - -picodata_ProcessingUnit picowa_newWordAnaUnit( - picoos_MemoryManager mm, - picoos_Common common, - picodata_CharBuffer cbIn, - picodata_CharBuffer cbOut, - picorsrc_Voice voice); - -#ifdef __cplusplus -} -#endif - -#endif /*PICOWA_H_*/ diff --git a/pico/Android.mk b/pico/Android.mk new file mode 100755 index 0000000..485ca70 --- /dev/null +++ b/pico/Android.mk @@ -0,0 +1,92 @@ +# SVOX Pico TTS Engine +# This makefile builds both an activity and a shared library. + +ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean + +TOP_LOCAL_PATH:= $(call my-dir) + +# Build Pico activity + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := user + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_PACKAGE_NAME := PicoTts + +LOCAL_JNI_SHARED_LIBRARIES := libttspico + +include $(BUILD_PACKAGE) + +# Build Pico Shared Library + +LOCAL_PATH:= $(TOP_LOCAL_PATH)/tts +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= com_svox_picottsengine.cpp + +LOCAL_C_INCLUDES += \ + external/svox/pico/lib \ + frameworks + +LOCAL_STATIC_LIBRARIES:= libsvoxpico + +LOCAL_SHARED_LIBRARIES:= libcutils + +LOCAL_MODULE:= libttspico + +LOCAL_ARM_MODE:= arm + +LOCAL_PRELINK_MODULE:= false + +include $(BUILD_SHARED_LIBRARY) + + +# Build Base Generic SVOX Pico Library +LOCAL_PATH:= $(TOP_LOCAL_PATH)/lib +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + picoacph.c \ + picoapi.c \ + picobase.c \ + picocep.c \ + picoctrl.c \ + picodata.c \ + picodbg.c \ + picoextapi.c \ + picofftsg.c \ + picokdbg.c \ + picokdt.c \ + picokfst.c \ + picoklex.c \ + picoknow.c \ + picokpdf.c \ + picokpr.c \ + picoktab.c \ + picoos.c \ + picopal.c \ + picopam.c \ + picopr.c \ + picorsrc.c \ + picosa.c \ + picosig.c \ + picosig2.c \ + picospho.c \ + picotok.c \ + picotrns.c \ + picowa.c + +LOCAL_PRELINK_MODULE:= false + +LOCAL_MODULE:= libsvoxpico + +LOCAL_CFLAGS+= $(TOOL_CFLAGS) + +LOCAL_LDFLAGS+= $(TOOL_LDFLAGS) + +include $(BUILD_STATIC_LIBRARY) + +endif # TARGET_SIMULATOR diff --git a/pico/AndroidManifest.xml b/pico/AndroidManifest.xml new file mode 100755 index 0000000..7188e70 --- /dev/null +++ b/pico/AndroidManifest.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pico/lib/picoacph.c b/pico/lib/picoacph.c new file mode 100644 index 0000000..98feb6e --- /dev/null +++ b/pico/lib/picoacph.c @@ -0,0 +1,1430 @@ +/* + * 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 picoacph.c + * + * accentuation and phrasing + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#include "picoos.h" +#include "picodbg.h" +#include "picobase.h" +#include "picodata.h" +#include "picoacph.h" +#include "picokdt.h" +#include "picoklex.h" +#include "picoktab.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/* PU acphStep states */ +#define SA_STEPSTATE_COLLECT 0 +#define SA_STEPSTATE_PROCESS_PHR 12 +#define SA_STEPSTATE_PROCESS_ACC 13 +#define SA_STEPSTATE_FEED 2 + + +/* boundary strength state */ +#define SA_BOUNDSTRENGTH_SSEP 0 /* sentence separator */ +#define SA_BOUNDSTRENGTH_PPHR 1 /* primary phrase separator */ + + +/* subobject : AccPhrUnit + * shortcut : acph + * context size : one phrase, max. 30 non-PUNC items, for non-processed items + * one item if internal input empty + */ + +/** + * @addtogroup picoacph + * + * Pico Accentuation and Phrasing \n + * + internal buffers: + + - headx : array for extended item heads of fixed size (head plus + index for content, plus two fields for boundary strength/type) + - cbuf : buffer for item contents (referenced by index in + headx). + + 0. bottom up filling of items in headx and cbuf + + 1. phrasing (right-to-left): + + e.g. from WP WP WP WP WP PUNC WP WP PUNC WP WP WP PUNC FLUSH \n + e.g. to BSBEG WP WP WP BPHR3 WP WP BPHR1 WP WP BSEND BSBEG WP WP WP BSEND BTERM \n + |1 |2 |3 |4 \n + + 2-level bound state: The internal buffer contains one primary phrase (sometimes forced, if buffer + allmost full), with the trailing PUNCT item included (last item).\n + If the trailing PUNC is a a primary phrase separator, the + item is not output, but instead, the bound state is set to PPHR, so that the correct BOUND can + be output at the start of the next primary phrase.\n + Otherwise, + the item is converted to the corresponding BOUND and output. the bound state is set to SSEP, + so that a BOUND of type SBEG is output at the start of the next primary phrase. + + trailing PUNC item bound states \n + SSEP PPHR \n + PUNC(SENTEND, X) B(B,X)>SSEP B(P1,X)>SSEP (X = T | Q | E) \n + PUNC(FLUSH, T) B(B,T)>SSEP* B(P1,T)>SSEP \n + PUNC(PHRASEEND, P) B(B,P)>PPHR B(P1,P)>PPHR \n + PUNC(PHRASEEND, FORC) B(B,P)>PPHR B(P1,P)>PPHR \n + + If more than one sentence separators follow each other (e.g. SEND-FLUSH, SEND-SEND) then + all but the first will be treated as an (empty) phrase containing just this item. + If this (single) item is a flush, creation of SBEG is suppressed. + + + - dtphr phrasing tree ("subphrasing") + determines + - BOUND_PHR2 + - BOUND_PHR3 + - boundary strenghts are determined for every word (except the + first one) from right-to-left. The boundary types mark the phrase + type of the phrase following the boundary. + - number of items actually changed (new BOUND items added): because + of fixed size without content, two fields are contained in headx + to indicate if a BOUND needs to be added to the LEFT of the item. + -> headx further extended with boundary strength and type info to + indicate that to the left of the headx ele a BOUND needs to be + inserted when outputting. + + 2. accentuation: + - number of items unchanged, content unchanged, only head info changes + -> changed in place in headx +*/ + + +typedef struct { + picodata_itemhead_t head; + picoos_uint16 cind; + picoos_uint8 boundstrength; /* bstrength to the left, 0 if not set */ + picoos_uint8 boundtype; /* btype for following phrase, 0 if not set */ +} picoacph_headx_t; + + +typedef struct acph_subobj { + picoos_uint8 procState; /* for next processing step decision */ + picoos_uint8 boundStrengthState; /* boundary strength state */ + + picoos_uint8 inspaceok; /* flag: headx/cbuf has space for an item */ + picoos_uint8 needsmoreitems; /* flag: need more items */ + + picoos_uint8 tmpbuf[PICODATA_MAX_ITEMSIZE]; /* tmp. location for an item */ + + picoacph_headx_t headx[PICOACPH_MAXNR_HEADX]; + picoos_uint16 headxBottom; /* bottom */ + picoos_uint16 headxLen; /* length, 0 if empty */ + + picoos_uint8 cbuf[PICOACPH_MAXSIZE_CBUF]; + picoos_uint16 cbufBufSize; /* actually allocated size */ + picoos_uint16 cbufLen; /* length, 0 if empty */ + + /* tab knowledge base */ + picoktab_Phones tabphones; + + /* dtphr knowledge base */ + picokdt_DtPHR dtphr; + + /* dtacc knowledge base */ + picokdt_DtACC dtacc; +} acph_subobj_t; + + +static pico_status_t acphInitialize(register picodata_ProcessingUnit this) { + acph_subobj_t * acph; + picoos_uint16 i; + + PICODBG_DEBUG(("calling")); + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(this->common->em, + PICO_ERR_NULLPTR_ACCESS, NULL, NULL); + } + acph = (acph_subobj_t *) this->subObj; + acph->procState = SA_STEPSTATE_COLLECT; + acph->boundStrengthState = SA_BOUNDSTRENGTH_SSEP; + + acph->inspaceok = TRUE; + acph->needsmoreitems = TRUE; + + acph->headxBottom = 0; + acph->headxLen = 0; + acph->cbufBufSize = PICOACPH_MAXSIZE_CBUF; + acph->cbufLen = 0; + + /* init headx, cbuf */ + for (i = 0; i < PICOACPH_MAXNR_HEADX; i++){ + acph->headx[i].head.type = 0; + acph->headx[i].head.info1 = 0; + acph->headx[i].head.info2 = 0; + acph->headx[i].head.len = 0; + acph->headx[i].cind = 0; + acph->headx[i].boundstrength = 0; + acph->headx[i].boundtype = 0; + } + for (i = 0; i < PICOACPH_MAXSIZE_CBUF; i++) { + acph->cbuf[i] = 0; + } + + /* kb tabphones */ + acph->tabphones = + picoktab_getPhones(this->voice->kbArray[PICOKNOW_KBID_TAB_PHONES]); + if (acph->tabphones == NULL) { + return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + PICODBG_DEBUG(("got tabphones")); + +#ifdef PICO_DEBUG_1 + { + picoos_uint16 itmp; + for (itmp = 0; itmp < 256; itmp++) { + if (picoktab_hasVowelProp(acph->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones hasVowel: %d", itmp)); + } + if (picoktab_hasDiphthProp(acph->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones hasDiphth: %d", itmp)); + } + if (picoktab_hasGlottProp(acph->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones hasGlott: %d", itmp)); + } + if (picoktab_hasNonsyllvowelProp(acph->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones hasNonsyllvowel: %d", itmp)); + } + if (picoktab_hasSyllconsProp(acph->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones hasSyllcons: %d", itmp)); + } + + if (picoktab_isPrimstress(acph->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones isPrimstress: %d", itmp)); + } + if (picoktab_isSecstress(acph->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones isSecstress: %d", itmp)); + } + if (picoktab_isSyllbound(acph->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones isSyllbound: %d", itmp)); + } + if (picoktab_isPause(acph->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones isPause: %d", itmp)); + } + } + + PICODBG_DEBUG(("tabphones primstressID: %d", + picoktab_getPrimstressID(acph->tabphones))); + PICODBG_DEBUG(("tabphones secstressID: %d", + picoktab_getSecstressID(acph->tabphones))); + PICODBG_DEBUG(("tabphones syllboundID: %d", + picoktab_getSyllboundID(acph->tabphones))); + PICODBG_DEBUG(("tabphones pauseID: %d", + picoktab_getPauseID(acph->tabphones))); + } +#endif + + + /* kb dtphr */ + acph->dtphr = picokdt_getDtPHR(this->voice->kbArray[PICOKNOW_KBID_DT_PHR]); + if (acph->dtphr == NULL) { + return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + PICODBG_DEBUG(("got dtphr")); + + /* kb dtacc */ + acph->dtacc = picokdt_getDtACC(this->voice->kbArray[PICOKNOW_KBID_DT_ACC]); + if (acph->dtacc == NULL) { + return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + PICODBG_DEBUG(("got dtacc")); + + return PICO_OK; +} + +static picodata_step_result_t acphStep(register picodata_ProcessingUnit this, + picoos_int16 mode, + picoos_uint16 *numBytesOutput); + +static pico_status_t acphTerminate(register picodata_ProcessingUnit this) +{ + return PICO_OK; +} + +static pico_status_t acphSubObjDeallocate(register picodata_ProcessingUnit this, + picoos_MemoryManager mm) { + mm = mm; /* avoid warning "var not used in this function"*/ + if (NULL != this) { + picoos_deallocate(this->common->mm, (void *) &this->subObj); + } + return PICO_OK; +} + + +picodata_ProcessingUnit picoacph_newAccPhrUnit(picoos_MemoryManager mm, + picoos_Common common, + picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, + picorsrc_Voice voice) { + picodata_ProcessingUnit this; + + this = picodata_newProcessingUnit(mm, common, cbIn, cbOut, voice); + if (this == NULL) { + return NULL; + } + + this->initialize = acphInitialize; + PICODBG_DEBUG(("set this->step to acphStep")); + this->step = acphStep; + this->terminate = acphTerminate; + this->subDeallocate = acphSubObjDeallocate; + this->subObj = picoos_allocate(mm, sizeof(acph_subobj_t)); + if (this->subObj == NULL) { + picoos_deallocate(mm, (void *)&this); + picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); + return NULL; + } + + acphInitialize(this); + return this; +} + + +/* ***********************************************************************/ +/* PROCESS_PHR/ACC support functions */ +/* ***********************************************************************/ + + +static picoos_uint8 acphGetNrSylls(register picodata_ProcessingUnit this, + register acph_subobj_t *acph, + const picoos_uint16 ind) { + picoos_uint8 i; + picoos_uint8 ch; + picoos_uint8 count; + + count = 1; + for (i = 0; i < acph->headx[ind].head.len; i++) { + ch = acph->cbuf[acph->headx[ind].cind + i]; + if (picoktab_isSyllbound(acph->tabphones, ch)) { + count++; + } + } + return count; +} + + +/* ***********************************************************************/ +/* PROCESS_PHR functions */ +/* ***********************************************************************/ + + +/* find next POS to the left of 'ind' and return its POS and index */ +static picoos_uint8 acphPhrItemSeqGetPosLeft(register picodata_ProcessingUnit this, + register acph_subobj_t *acph, + const picoos_uint16 ind, + picoos_uint16 *leftind) { + picoos_uint8 val; + picoos_int32 i; + + val = PICOKDT_EPSILON; + for (i = ind - 1; ((val == PICOKDT_EPSILON) && (i >= 0)); i--) { + if ((acph->headx[i].head.type == PICODATA_ITEM_WORDPHON)) { + val = acph->headx[i].head.info1; + } + } + *leftind = i + 1; + return val; +} + + +/* right-to-left, for each WORDPHON do phr */ +static pico_status_t acphSubPhrasing(register picodata_ProcessingUnit this, + register acph_subobj_t *acph) { + picokdt_classify_result_t dtres; + picoos_uint8 valbuf[5]; + picoos_uint16 nrwordspre; + picoos_uint16 nrwordsfol; + picoos_uint16 nrsyllsfol; + picoos_uint16 lastprev2; /* last index of POS(es) found to the left */ + picoos_uint8 curpos; /* POS(es) of current word */ + picoos_uint16 upbound; /* index of last WORDPHON item (with POS) */ + picoos_uint8 okay; + picoos_uint8 nosubphrases; + picoos_int32 i; + + /* set initial values */ + okay = TRUE; + nosubphrases = TRUE; + curpos = PICOKDT_EPSILON; /* needs to be in 2^8 */ + + /* set upbound to last WORDPHON, don't worry about first one */ + upbound = acph->headxLen - 1; + while ((upbound > 0) && + (acph->headx[upbound].head.type != PICODATA_ITEM_WORDPHON)) { + upbound--; + } + + /* zero or one WORDPHON, no subphrasing needed, but handling of + BOUND strength state is needed */ + if (upbound <= 0) { + /* phrase not containing more than one WORDPHON */ + PICODBG_DEBUG(("less than two WORDPHON in phrase -> no subphrasing")); + } + + lastprev2 = upbound; + + /* set initial nr pre/fol words/sylls, upbound is ind of last WORDPHON */ + nrwordsfol = 0; + nrsyllsfol = 0; + nrwordspre = 0; + for (i = 0; i < upbound; i++) { + if (acph->headx[i].head.type == PICODATA_ITEM_WORDPHON) { + nrwordspre++; + } + } + + nrwordspre++; /* because we later have a decrement before being used */ + + + /* set POS of current word in valbuf[1], will be shifted right afterwards */ + valbuf[1] = acph->headx[upbound].head.info1; + /* find first POS to the left and set valbuf[0] */ + valbuf[0] = acphPhrItemSeqGetPosLeft(this, acph, lastprev2, &lastprev2); + for (i = 2; i < 5; i++) { + valbuf[i] = PICOKDT_EPSILON; + } + + PICODBG_TRACE(("headxLen: %d", acph->headxLen)); + + /* at least two WORDPHON items */ + /* process from right-to-left all items in headx, except for 1st WORDPHON */ + for (i = upbound; (i > 0) && (nrwordspre > 1); i--) { + okay = TRUE; + + PICODBG_TRACE(("iter: %d, type: %c", i, acph->headx[i].head.type)); + + /* if not (WORDPHON) */ + if ((acph->headx[i].head.type != PICODATA_ITEM_WORDPHON)) { + continue; + } + + PICODBG_TRACE(("iter: %d, curpos: %d", i, acph->headx[i].head.info1)); + + /* get and set POS of current item, must be WORDPHON */ + curpos = acph->headx[i].head.info1; + + /* no continue so far => at [i] we have a WORDPHON item */ + /* shift all POS elements one position to the right */ + valbuf[4] = valbuf[3]; + valbuf[3] = valbuf[2]; + valbuf[2] = valbuf[1]; + valbuf[1] = valbuf[0]; + /* find next POS to the left and set valbuf[0] */ + valbuf[0] = acphPhrItemSeqGetPosLeft(this, acph, lastprev2, &lastprev2); + + /* better check double than never */ + if (curpos != valbuf[2]) { + PICODBG_WARN(("syncing POS")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, + NULL, NULL); + valbuf[2] = curpos; + } + + nrwordsfol++; + nrsyllsfol += acphGetNrSylls(this, acph, i); + nrwordspre--; + + PICODBG_TRACE(("%d: [%d,%d|%d|%d,%d|%d,%d,%d]", + i, valbuf[0], valbuf[1], valbuf[2], valbuf[3], + valbuf[4], nrwordspre, nrwordsfol, nrsyllsfol)); + + /* no continue so far => subphrasing needed */ + /* construct input vector, which is set in dtphr */ + if (!picokdt_dtPHRconstructInVec(acph->dtphr, valbuf[0], valbuf[1], + valbuf[2], valbuf[3], valbuf[4], + nrwordspre, nrwordsfol, nrsyllsfol)) { + /* error constructing invec */ + PICODBG_WARN(("problem with invec")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, + NULL, NULL); + okay = FALSE; + } + /* classify */ + if (okay && (!picokdt_dtPHRclassify(acph->dtphr))) { + /* error doing classification */ + PICODBG_WARN(("problem classifying")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, + NULL, NULL); + okay = FALSE; + } + /* decompose */ + if (okay && (!picokdt_dtPHRdecomposeOutClass(acph->dtphr, &dtres))) { + /* error decomposing */ + PICODBG_WARN(("problem decomposing")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_OUTVECTOR, + NULL, NULL); + okay = FALSE; + } + + if (okay && dtres.set) { + PICODBG_DEBUG(("%d - inpos: %d, out: %d", i,valbuf[2],dtres.class)); + } else { + PICODBG_WARN(("problem determining subphrase boundary strength")); + dtres.class = PICODATA_ITEMINFO1_ERR; + } + + if (dtres.class > 255) { + PICODBG_WARN(("dt class outside valid range, setting to PHR0")); + dtres.class = PICODATA_ITEMINFO1_BOUND_PHR0; + } + acph->headx[i].boundstrength = (picoos_uint8)dtres.class; + if ((dtres.class == PICODATA_ITEMINFO1_BOUND_PHR2) || + (dtres.class == PICODATA_ITEMINFO1_BOUND_PHR3)) { + if (nosubphrases) { + /* it's the last secondary phrase in the primary phrase */ + /* add type info */ + switch (acph->headx[acph->headxLen - 1].head.info2) { + case PICODATA_ITEMINFO2_PUNC_SENT_T: + acph->headx[i].boundtype = + PICODATA_ITEMINFO2_BOUNDTYPE_T; + break; + case PICODATA_ITEMINFO2_PUNC_SENT_Q: + acph->headx[i].boundtype = + PICODATA_ITEMINFO2_BOUNDTYPE_Q; + break; + case PICODATA_ITEMINFO2_PUNC_SENT_E: + acph->headx[i].boundtype = + PICODATA_ITEMINFO2_BOUNDTYPE_E; + break; + case PICODATA_ITEMINFO2_PUNC_PHRASE: + case PICODATA_ITEMINFO2_PUNC_PHRASE_FORCED: + acph->headx[i].boundtype = + PICODATA_ITEMINFO2_BOUNDTYPE_P; + break; + default: + PICODBG_WARN(("invalid boundary type, not set")); + break; + } + nosubphrases = FALSE; + + } else { + acph->headx[i].boundtype = + PICODATA_ITEMINFO2_BOUNDTYPE_P; + } + /* reset nr following words and sylls counters */ + nrwordsfol = 0; + nrsyllsfol = 0; + } + } + + /* process first item, add bound-info */ + switch (acph->boundStrengthState) { + case SA_BOUNDSTRENGTH_SSEP: + acph->headx[0].boundstrength = + PICODATA_ITEMINFO1_BOUND_SBEG; + break; + case SA_BOUNDSTRENGTH_PPHR: + acph->headx[0].boundstrength = + PICODATA_ITEMINFO1_BOUND_PHR1; + break; + default: + PICODBG_WARN(("invalid boundary strength, not set")); + break; + } + + /* set boundary strength state */ + switch (acph->headx[acph->headxLen - 1].head.info1) { + case PICODATA_ITEMINFO1_PUNC_SENTEND: + case PICODATA_ITEMINFO1_PUNC_FLUSH: + acph->boundStrengthState = SA_BOUNDSTRENGTH_SSEP; + break; + case PICODATA_ITEMINFO1_PUNC_PHRASEEND: + acph->boundStrengthState = SA_BOUNDSTRENGTH_PPHR; + break; + default: + PICODBG_WARN(("invalid boundary strength state, not changed")); + break; + } + + if (nosubphrases) { + /* process first item, add type info */ + switch (acph->headx[acph->headxLen - 1].head.info2) { + case PICODATA_ITEMINFO2_PUNC_SENT_T: + acph->headx[0].boundtype = + PICODATA_ITEMINFO2_BOUNDTYPE_T; + break; + case PICODATA_ITEMINFO2_PUNC_SENT_Q: + acph->headx[0].boundtype = + PICODATA_ITEMINFO2_BOUNDTYPE_Q; + break; + case PICODATA_ITEMINFO2_PUNC_SENT_E: + acph->headx[0].boundtype = + PICODATA_ITEMINFO2_BOUNDTYPE_E; + break; + case PICODATA_ITEMINFO2_PUNC_PHRASE: + case PICODATA_ITEMINFO2_PUNC_PHRASE_FORCED: + acph->headx[0].boundtype = + PICODATA_ITEMINFO2_BOUNDTYPE_P; + break; + default: + PICODBG_WARN(("invalid boundary type, not set")); + break; + } + } else { + acph->headx[0].boundtype = + PICODATA_ITEMINFO2_BOUNDTYPE_P; + } + + return PICO_OK; +} + + +/* ***********************************************************************/ +/* PROCESS_ACC functions */ +/* ***********************************************************************/ + +/* find next POS to the left of 'ind' and return its POS and index */ +static picoos_uint8 acphAccItemSeqGetPosLeft(register picodata_ProcessingUnit this, + register acph_subobj_t *acph, + const picoos_uint16 ind, + picoos_uint16 *leftind) { + picoos_uint8 val; + picoos_int32 i; + + val = PICOKDT_EPSILON; + for (i = ind - 1; ((val == PICOKDT_EPSILON) && (i >= 0)); i--) { + if ((acph->headx[i].head.type == PICODATA_ITEM_WORDPHON)) { + val = acph->headx[i].head.info1; + } + } + *leftind = i + 1; + return val; +} + + +/* s1: nr sylls in word before the first primary stressed syll, + s2: nr sylls in word after (but excluding) the first primary stressed syll */ +static picoos_uint8 acphAccNrSyllParts(register picodata_ProcessingUnit this, + register acph_subobj_t *acph, + const picoos_uint16 ind, + picoos_uint8 *s1, + picoos_uint8 *s2) { + picoos_uint16 pind; + picoos_uint16 pend; /* phone string start+len */ + picoos_uint8 afterprim; + + /* check ind is in valid range */ + if (ind >= acph->headxLen) { + return FALSE; + } + + *s1 = 0; + *s2 = 0; + afterprim = FALSE; + pend = acph->headx[ind].cind + acph->headx[ind].head.len; + for (pind = acph->headx[ind].cind; pind < pend; pind++) { + if (picoktab_isPrimstress(acph->tabphones, acph->cbuf[pind])) { + afterprim = TRUE; + } else if (picoktab_isSyllbound(acph->tabphones, acph->cbuf[pind])) { + if (afterprim) { + (*s2)++; + } else { + (*s1)++; + } + } + } + if (afterprim) { + (*s2)++; + } else { + (*s1)++; + } + + /* exclude the stressed syllable */ + if ((*s2) > 0) { + (*s2)--; + } + /* handle the case when there is no primstress */ + if (!afterprim) { + (*s2) = (*s1); + } + return TRUE; +} + + +static picoos_uint8 acphAccGetNrsRight(register picodata_ProcessingUnit this, + register acph_subobj_t *acph, + const picoos_uint16 ind, + picoos_uint16 *nrwordsfol, + picoos_uint16 *nrsyllsfol, + picoos_uint16 *footwordsfol, + picoos_uint16 *footsyllsfol) { + picoos_uint16 i; + picoos_uint8 s1; + picoos_uint8 s2; + + if (!acphAccNrSyllParts(this, acph, ind, &s1, &s2)) { + return FALSE; + } + + *nrwordsfol = 0; + *nrsyllsfol = s2; + i = ind + 1; + while ((i < acph->headxLen) && + (acph->headx[i].boundstrength == PICODATA_ITEMINFO1_BOUND_PHR0)) { + if (acph->headx[i].head.type == PICODATA_ITEM_WORDPHON) { + (*nrwordsfol)++; + *nrsyllsfol += acphGetNrSylls(this, acph, i); + } + i++; + } + + *footwordsfol = 0; + *footsyllsfol = s2; + i = ind + 1; + while ((i < acph->headxLen) && + (acph->headx[i].head.info2 != PICODATA_ACC1)) { + if (acph->headx[i].head.type == PICODATA_ITEM_WORDPHON) { + (*footwordsfol)++; + *footsyllsfol += acphGetNrSylls(this, acph, i); + } + i++; + } + if ((i < acph->headxLen) && (acph->headx[i].head.info2 == PICODATA_ACC1)) { + if (!acphAccNrSyllParts(this, acph, i, &s1, &s2)) { + return FALSE; + } + *footsyllsfol += s1; + } + return TRUE; +} + + +static picoos_uint8 acphAccGetNrsLeft(register picodata_ProcessingUnit this, + register acph_subobj_t *acph, + const picoos_uint16 ind, + picoos_uint16 *nrwordspre, + picoos_uint16 *nrsyllspre) { + picoos_int32 i; + picoos_uint8 s1; + picoos_uint8 s2; + + if (!acphAccNrSyllParts(this, acph, ind, &s1, &s2)) { + return FALSE; + } + + *nrwordspre = 0; + *nrsyllspre = s1; + i = ind - 1; + while ((i >= 0) && + (acph->headx[i].boundstrength == PICODATA_ITEMINFO1_BOUND_PHR0)) { + if (acph->headx[i].head.type == PICODATA_ITEM_WORDPHON) { + (*nrwordspre)++; + *nrsyllspre += acphGetNrSylls(this, acph, i); + } + i--; + } + + if ((acph->headx[i].boundstrength != PICODATA_ITEMINFO1_BOUND_PHR0) && + (acph->headx[i].head.type == PICODATA_ITEM_WORDPHON)) { + (*nrwordspre)++; + *nrsyllspre += acphGetNrSylls(this, acph, i); + } + return TRUE; +} + + +/* return TRUE if wordphon contains no stress, FALSE otherwise */ +static picoos_uint8 acphIsWordWithoutStress(register picodata_ProcessingUnit this, + register acph_subobj_t *acph, + const picoos_uint16 ind) { + picoos_uint8 i; + picoos_uint16 pos; + + pos = acph->headx[ind].cind; + for (i = 0; i < acph->headx[ind].head.len; i++) { + if (picoktab_isPrimstress(acph->tabphones, acph->cbuf[pos + i]) || + picoktab_isSecstress(acph->tabphones, acph->cbuf[pos + i])) { + return FALSE; + } + } + return TRUE; +} + + +/* right-to-left, for each WORDPHON do acc */ +static pico_status_t acphAccentuation(register picodata_ProcessingUnit this, + register acph_subobj_t *acph) { + picokdt_classify_result_t dtres; + picoos_uint8 valbuf[5]; + picoos_uint16 hist1; + picoos_uint16 hist2; + picoos_uint16 nrwordspre; + picoos_uint16 nrsyllspre; + picoos_uint16 nrwordsfol; + picoos_uint16 nrsyllsfol; + picoos_uint16 footwordsfol; + picoos_uint16 footsyllsfol; + picoos_uint16 lastprev2; /* last index of POS(es) found to the left */ + picoos_uint8 curpos; /* POS(es) of current word */ + picoos_uint16 prevout; + picoos_uint8 okay; + picoos_int32 upbound; /* index of last WORDPHON item (with POS) */ + picoos_uint16 i; + + /* set initial values */ + okay = TRUE; + curpos = PICOKDT_EPSILON; /* needs to be < 2^8 */ + + /* set upbound to last WORDPHON */ + upbound = acph->headxLen - 1; + while ((upbound >= 0) && + (acph->headx[upbound].head.type != PICODATA_ITEM_WORDPHON)) { + upbound--; + } + + if (upbound < 0) { + /* phrase containing zero WORDPHON */ + PICODBG_DEBUG(("no WORDPHON in phrase -> no accentuation")); + return PICO_OK; + } + + lastprev2 = upbound; + + /* set initial history values */ + prevout = PICOKDT_HISTORY_ZERO; + hist1 = PICOKDT_HISTORY_ZERO; + hist2 = PICOKDT_HISTORY_ZERO; + + /* set initial nr pre/fol words/sylls, upbound is ind of last WORDPHON */ + nrwordsfol = 0; + nrsyllsfol = 0; + footwordsfol = 0; + footsyllsfol = 0; + nrwordspre = 0; + nrsyllspre = 0; + + /* set POS of current word in valbuf[1], will be shifted right afterwards */ + valbuf[1] = acph->headx[upbound].head.info1; + /* find first POS to the left and set valbuf[0] */ + valbuf[0] = acphAccItemSeqGetPosLeft(this, acph, lastprev2, &lastprev2); + for (i = 2; i < 5; i++) { + valbuf[i] = PICOKDT_EPSILON; + } + + PICODBG_TRACE(("headxLen: %d", acph->headxLen)); + + /* process from right-to-left all items in headx */ + for (i = upbound+1; i > 0; ) { + i--; + + okay = TRUE; + + PICODBG_TRACE(("iter: %d, type: %c", i, acph->headx[i].head.type)); + + /* if not (WORDPHON) */ + if ((acph->headx[i].head.type != PICODATA_ITEM_WORDPHON)) { + continue; + } + + PICODBG_TRACE(("iter: %d, curpos: %d", i, acph->headx[i].head.info1)); + + /* get and set POS of current item, must be WORDPHON */ + curpos = acph->headx[i].head.info1; + + /* no continue so far => at [i] we have a WORDPHON item */ + /* shift all POS elements one position to the right */ + valbuf[4] = valbuf[3]; + valbuf[3] = valbuf[2]; + valbuf[2] = valbuf[1]; + valbuf[1] = valbuf[0]; + /* find next POS to the left and set valbuf[0] */ + valbuf[0] = acphAccItemSeqGetPosLeft(this, acph, lastprev2, &lastprev2); + + /* better check double than never */ + if (curpos != valbuf[2]) { + PICODBG_WARN(("syncing POS")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, + NULL, NULL); + valbuf[2] = curpos; + } + + /* set history values */ + hist2 = hist1; + hist1 = prevout; + + /* ************************************************************ */ + /* many speedups possible by avoiding double calc of attribtues */ + /* ************************************************************ */ + + /* get distances */ + if ((!acphAccGetNrsRight(this, acph, i, &nrwordsfol, &nrsyllsfol, + &footwordsfol, &footsyllsfol)) || + (!acphAccGetNrsLeft(this, acph, i, &nrwordspre, &nrsyllspre))) { + PICODBG_WARN(("problem setting distances in invec")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, + NULL, NULL); + okay = FALSE; + } + + PICODBG_TRACE(("%d: [%d,%d,%d,%d,%d|%d,%d|%d,%d,%d,%d|%d,%d]", i, + valbuf[0], valbuf[1], valbuf[2], valbuf[3], valbuf[4], + hist1, hist2, nrwordspre, nrsyllspre, + nrwordsfol, nrsyllsfol, footwordsfol, footsyllsfol)); + + /* no continue so far => accentuation needed */ + /* construct input vector, which is set in dtacc */ + if (!picokdt_dtACCconstructInVec(acph->dtacc, valbuf[0], valbuf[1], + valbuf[2], valbuf[3], valbuf[4], + hist1, hist2, nrwordspre, nrsyllspre, + nrwordsfol, nrsyllsfol, footwordsfol, + footsyllsfol)) { + /* error constructing invec */ + PICODBG_WARN(("problem with invec")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, + NULL, NULL); + okay = FALSE; + } + /* classify */ + if (okay && (!picokdt_dtACCclassify(acph->dtacc, &prevout))) { + /* error doing classification */ + PICODBG_WARN(("problem classifying")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, + NULL, NULL); + okay = FALSE; + } + /* decompose */ + if (okay && (!picokdt_dtACCdecomposeOutClass(acph->dtacc, &dtres))) { + /* error decomposing */ + PICODBG_WARN(("problem decomposing")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_OUTVECTOR, + NULL, NULL); + okay = FALSE; + } + + if (dtres.class > 255) { + PICODBG_WARN(("dt class outside valid range, setting to ACC0")); + dtres.class = PICODATA_ACC0; + } + + if (okay && dtres.set) { + PICODBG_DEBUG(("%d - inpos: %d, out: %d", i,valbuf[2],dtres.class)); + if (acphIsWordWithoutStress(this, acph, i)) { + if (dtres.class != PICODATA_ACC0) { + acph->headx[i].head.info2 = PICODATA_ACC3; + } else { + acph->headx[i].head.info2 = (picoos_uint8)dtres.class; + } + } else { + acph->headx[i].head.info2 = (picoos_uint8)dtres.class; + } + PICODBG_DEBUG(("%d - after-nostress-corr: %d", + i, acph->headx[i].head.info2)); + } else { + PICODBG_WARN(("problem determining accentuation level")); + dtres.class = PICODATA_ITEMINFO1_ERR; + } + } + return PICO_OK; +} + + + +/* ***********************************************************************/ +/* acphStep support functions */ +/* ***********************************************************************/ + +static picoos_uint8 acphPutBoundItem(register picodata_ProcessingUnit this, + register acph_subobj_t *acph, + const picoos_uint8 strength, + const picoos_uint8 type, + picoos_uint8 *dopuoutfull, + picoos_uint16 *numBytesOutput) { + pico_status_t rv = PICO_OK; + picoos_uint16 blen = 0; + picodata_itemhead_t tmphead; + + *dopuoutfull = FALSE; + + /* construct BOUND item in tmpbuf and put item */ + tmphead.type = PICODATA_ITEM_BOUND; + tmphead.info1 = strength; + tmphead.info2 = type; + tmphead.len = 0; + rv = picodata_put_itemparts(&tmphead, NULL, 0, acph->tmpbuf, + PICODATA_MAX_ITEMSIZE, &blen); + if (rv != PICO_OK) { + PICODBG_ERROR(("problem creating BOUND item")); + picoos_emRaiseException(this->common->em, rv, NULL, NULL); + return FALSE; + } + /* put constructed item to ext. charbuf */ + rv = picodata_cbPutItem(this->cbOut, acph->tmpbuf, blen, &blen); + + *numBytesOutput += blen; + if (rv == PICO_EXC_BUF_OVERFLOW) { + PICODBG_DEBUG(("overflow in cb output buffer")); + *dopuoutfull = TRUE; /* ie. do PU_OUT_FULL later */ + return FALSE; + } else if (rv != PICO_OK) { + PICODBG_ERROR(("problem putting BOUND item")); + picoos_emRaiseException(this->common->em, rv, NULL, NULL); + return FALSE; + } + + PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], + (picoos_uint8 *)"acph: ", acph->tmpbuf, blen); + + return TRUE; +} + + + +/* ***********************************************************************/ +/* acphStep function */ +/* ***********************************************************************/ + +/* +complete phrase processed in one step, if not fast enough -> rework + +init, collect into internal buffer, process, and then feed to +output buffer + +init state: INIT ext ext +state trans: in hc1 hc2 out + +INIT | putItem = 0 0 +1 | BUSY -> COLL (put B-SBEG item, + set do-init to false) + + inspace-ok-hc1 + needs-more-items-(phrase-or-flush) +COLL1 |getItems -n +n 0 1 | ATOMIC -> PPOSD (got items, + if flush set do-init) +COLL2 |getItems -n +n 1 0 | ATOMIC -> PPOSD (got items, forced) +COLL3 |getItems -n +n 1 1 | IDLE (got items, need more) +COLL4 |getItems = = 1 1 | IDLE (got no items) + +PPOSD | posd = ~n~n | BUSY -> PWP (posd done) +PWP | lex/g2p = ~n-n 0+n | BUSY -> PPHR (lex/g2p done) +PPHR | phr = -n 0 +m=n | BUSY -> PACC (phr done, m>=n) +PACC | acc = 0 0 ~m=n | BUSY -> FEED (acc done) + + doinit-flag +FEED | putItems 0 0 0 -m-n +m 0 | BUSY -> COLL (put items) +FEED | putItems 0 0 0 -m-n +m 1 | BUSY -> INIT (put items) +FEED | putItems 0 0 0 -d-d +d | OUT_FULL (put some items) +*/ + +static picodata_step_result_t acphStep(register picodata_ProcessingUnit this, + picoos_int16 mode, + picoos_uint16 *numBytesOutput) { + register acph_subobj_t *acph; + pico_status_t rv = PICO_OK; + pico_status_t rvP = PICO_OK; + picoos_uint16 blen = 0; + picoos_uint16 clen = 0; + picoos_uint16 i; + + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + acph = (acph_subobj_t *) this->subObj; + mode = mode; /* avoid warning "var not used in this function"*/ + *numBytesOutput = 0; + while (1) { /* exit via return */ + PICODBG_DEBUG(("doing state %i, hLen|c1Len: %d|%d", + acph->procState, acph->headxLen, acph->cbufLen)); + + switch (acph->procState) { + + /* *********************************************************/ + /* collect state: get item(s) from charBuf and store in + * internal buffers, need a complete punctuation-phrase + */ + case SA_STEPSTATE_COLLECT: + + while (acph->inspaceok && acph->needsmoreitems && (PICO_OK == + (rv = picodata_cbGetItem(this->cbIn, acph->tmpbuf, + PICODATA_MAX_ITEMSIZE, &blen)))) { + rvP = picodata_get_itemparts(acph->tmpbuf, + PICODATA_MAX_ITEMSIZE, &(acph->headx[acph->headxLen].head), + &(acph->cbuf[acph->cbufLen]), acph->cbufBufSize + - acph->cbufLen, &clen); + if (rvP != PICO_OK) { + PICODBG_ERROR(("problem getting item parts")); + picoos_emRaiseException(this->common->em, rvP, + NULL, NULL); + return PICODATA_PU_ERROR; + } + + /* if CMD(...FLUSH...) -> PUNC(...FLUSH...), + construct PUNC-FLUSH item in headx */ + if ((acph->headx[acph->headxLen].head.type + == PICODATA_ITEM_CMD) + && (acph->headx[acph->headxLen].head.info1 + == PICODATA_ITEMINFO1_CMD_FLUSH)) { + acph->headx[acph->headxLen].head.type + = PICODATA_ITEM_PUNC; + acph->headx[acph->headxLen].head.info1 + = PICODATA_ITEMINFO1_PUNC_FLUSH; + acph->headx[acph->headxLen].head.info2 + = PICODATA_ITEMINFO2_PUNC_SENT_T; + acph->headx[acph->headxLen].head.len = 0; + } + + /* check/set needsmoreitems */ + if (acph->headx[acph->headxLen].head.type + == PICODATA_ITEM_PUNC) { + acph->needsmoreitems = FALSE; + } + + /* check/set inspaceok, keep spare slot for forcing */ + if ((acph->headxLen >= (PICOACPH_MAXNR_HEADX - 2)) + || ((acph->cbufBufSize - acph->cbufLen) + < PICODATA_MAX_ITEMSIZE)) { + acph->inspaceok = FALSE; + } + + if (clen > 0) { + acph->headx[acph->headxLen].cind = acph->cbufLen; + acph->cbufLen += clen; + } else { + acph->headx[acph->headxLen].cind = 0; + } + acph->headxLen++; + } + + if (!acph->needsmoreitems) { + /* 1, phrase buffered */ + acph->procState = SA_STEPSTATE_PROCESS_PHR; + return PICODATA_PU_ATOMIC; + } else if (!acph->inspaceok) { + /* 2, forced phrase end */ + /* at least one slot is still free, use it to + force a trailing PUNC item */ + acph->headx[acph->headxLen].head.type = PICODATA_ITEM_PUNC; + acph->headx[acph->headxLen].head.info1 = + PICODATA_ITEMINFO1_PUNC_PHRASEEND; + acph->headx[acph->headxLen].head.info2 = + PICODATA_ITEMINFO2_PUNC_PHRASE_FORCED; + acph->headx[acph->headxLen].head.len = 0; + acph->needsmoreitems = FALSE; /* not really needed for now */ + acph->headxLen++; + PICODBG_WARN(("forcing phrase end, added PUNC_PHRASEEND")); + picoos_emRaiseWarning(this->common->em, + PICO_WARN_FALLBACK, NULL, + (picoos_char *)"forced phrase end"); + acph->procState = SA_STEPSTATE_PROCESS_PHR; + return PICODATA_PU_ATOMIC; + } else if (rv == PICO_EOF) { + /* 3, 4 */ + return PICODATA_PU_IDLE; + } else if ((rv == PICO_EXC_BUF_UNDERFLOW) || + (rv == PICO_EXC_BUF_OVERFLOW)) { + /* error, no valid item in cb (UNDER) */ + /* or tmpbuf not large enough, not possible (OVER) */ + /* no exception raised, left for ctrl to handle */ + PICODBG_ERROR(("buffer under/overflow, rv: %d", rv)); + return PICODATA_PU_ERROR; + } else { + /* error, only possible if cbGetItem implementation + changes without this function being adapted*/ + PICODBG_ERROR(("untreated return value, rv: %d", rv)); + return PICODATA_PU_ERROR; + } + break; + + + + + /* *********************************************************/ + /* process phr state: process items in headx and modify + * headx in place + */ + case SA_STEPSTATE_PROCESS_PHR: + /* ensure there is an item in inBuf */ + if (acph->headxLen > 0) { + /* we have a phrase in headx, cbuf1 (can be + single PUNC item), do phrasing and modify headx */ + + if (PICO_OK != acphSubPhrasing(this, acph)) { + picoos_emRaiseException(this->common->em, + PICO_ERR_OTHER, NULL, NULL); + return PICODATA_PU_ERROR; + } + acph->procState = SA_STEPSTATE_PROCESS_ACC; + } else if (acph->headxLen == 0) { /* no items in inBuf */ + PICODBG_WARN(("no items in inBuf")); + acph->procState = SA_STEPSTATE_COLLECT; + return PICODATA_PU_BUSY; + } + +#if defined (PICO_DEBUG_NOTNEEDED) + if (1) { + picoos_uint8 i, j, ittype; + for (i = 0; i < acph->headxLen; i++) { + if ((acph->headx[i].boundstrength != 0) && + (acph->headx[i].boundstrength != + PICODATA_ITEMINFO1_BOUND_PHR0)) { + PICODBG_INFO(("acph-p: boundstrength '%c', " + "boundtype '%c'", + acph->headx[i].boundstrength, + acph->headx[i].boundtype)); + } + + ittype = acph->headx[i].head.type; + PICODBG_INFO_CTX(); + PICODBG_INFO_MSG(("acph-p: (")); + PICODBG_INFO_MSG(("'%c',", ittype)); + if ((32 <= acph->headx[i].head.info1) && + (acph->headx[i].head.info1 < 127) && + (ittype != PICODATA_ITEM_WORDPHON)) { + PICODBG_INFO_MSG(("'%c',",acph->headx[i].head.info1)); + } else { + PICODBG_INFO_MSG(("%3d,", acph->headx[i].head.info1)); + } + if ((32 <= acph->headx[i].head.info2) && + (acph->headx[i].head.info2 < 127)) { + PICODBG_INFO_MSG(("'%c',",acph->headx[i].head.info2)); + } else { + PICODBG_INFO_MSG(("%3d,", acph->headx[i].head.info2)); + } + PICODBG_INFO_MSG(("%3d)", acph->headx[i].head.len)); + + for (j = 0; j < acph->headx[i].head.len; j++) { + if ((ittype == PICODATA_ITEM_CMD)) { + PICODBG_INFO_MSG(("%c", + acph->cbuf[acph->headx[i].cind+j])); + } else { + PICODBG_INFO_MSG(("%4d", + acph->cbuf[acph->headx[i].cind+j])); + } + } + PICODBG_INFO_MSG(("\n")); + } + } +#endif + + break; + + + /* *********************************************************/ + /* process acc state: process items in headx and modify + * headx in place + */ + case SA_STEPSTATE_PROCESS_ACC: + /* ensure there is an item in inBuf */ + if (acph->headxLen > 0) { + /* we have a phrase in headx, cbuf (can be + single PUNC item), do accentuation and modify headx */ + if (PICO_OK != acphAccentuation(this, acph)) { + picoos_emRaiseException(this->common->em, + PICO_ERR_OTHER, NULL, NULL); + return PICODATA_PU_ERROR; + } + acph->procState = SA_STEPSTATE_FEED; + } else if (acph->headxLen == 0) { /* no items in inBuf */ + PICODBG_WARN(("no items in inBuf")); + acph->procState = SA_STEPSTATE_COLLECT; + return PICODATA_PU_BUSY; + } + break; + + + /* *********************************************************/ + /* feed state: copy item in internal outBuf to output charBuf */ + case SA_STEPSTATE_FEED: { + picoos_uint16 indupbound; + picoos_uint8 dopuoutfull; + + PICODBG_DEBUG(("put out items (bot, len): (%d, %d)", + acph->headxBottom, acph->headxLen)); + + indupbound = acph->headxBottom + acph->headxLen; + dopuoutfull = FALSE; + + if (acph->headxBottom == 0) { + /* construct first BOUND item in tmpbuf and put item */ + /* produce BOUND unless it is followed by a term/flush) */ + if (acph->headx[0].head.info1 + != PICODATA_ITEMINFO1_PUNC_FLUSH) { + if (!acphPutBoundItem(this, acph, + acph->headx[0].boundstrength, + acph->headx[0].boundtype, &dopuoutfull, + numBytesOutput)) { + if (dopuoutfull) { + PICODBG_DEBUG(("feeding overflow")); + return PICODATA_PU_OUT_FULL; + } else { + /* ERR-msg and exception done in acphPutBoundItem */ + return PICODATA_PU_ERROR; + } + } + } + } + + /* for all items in headx, cbuf */ + for (i = acph->headxBottom; i < indupbound; i++) { + + switch (acph->headx[i].head.type) { + case PICODATA_ITEM_PUNC: + /* if sentence end, put SEND bound */ + if ((acph->headx[i].head.info1 == + PICODATA_ITEMINFO1_PUNC_SENTEND) && + (i == (indupbound - 1))) { + /* construct and put BOUND item */ + if (!acphPutBoundItem(this, acph, + PICODATA_ITEMINFO1_BOUND_SEND, + PICODATA_ITEMINFO2_NA, + &dopuoutfull, numBytesOutput)) { + if (dopuoutfull) { + PICODBG_DEBUG(("feeding overflow")); + return PICODATA_PU_OUT_FULL; + } else { + /* ERR-msg and exception done + in acphPutBoundItem */ + return PICODATA_PU_ERROR; + } + } + } else if ((acph->headx[i].head.info1 == + PICODATA_ITEMINFO1_PUNC_FLUSH) && + (i == (indupbound - 1))) { + /* construct and put BOUND item */ + if (!acphPutBoundItem(this, acph, + PICODATA_ITEMINFO1_BOUND_TERM, + PICODATA_ITEMINFO2_NA, + &dopuoutfull, numBytesOutput)) { + if (dopuoutfull) { + PICODBG_DEBUG(("feeding overflow")); + return PICODATA_PU_OUT_FULL; + } else { + /* ERR-msg and exception done + in acphPutBoundItem */ + return PICODATA_PU_ERROR; + } + } + } + /* else, good-bye PUNC, not needed anymore */ + break; + default: + + /* PHR2/3 maybe existing, check and add + BOUND item now, if needed */ + if ((acph->headx[i].boundstrength == + PICODATA_ITEMINFO1_BOUND_PHR2) || + (acph->headx[i].boundstrength == + PICODATA_ITEMINFO1_BOUND_PHR3)) { + if (!acphPutBoundItem(this, acph, + acph->headx[i].boundstrength, + acph->headx[i].boundtype, + &dopuoutfull, numBytesOutput)) { + if (dopuoutfull) { + PICODBG_DEBUG(("feeding overflow")); + return PICODATA_PU_OUT_FULL; + } else { + /* ERR-msg and exception done + in acphPutBoundItem */ + return PICODATA_PU_ERROR; + } + } + } + + /* copy item unmodified */ + rv = picodata_put_itemparts(&(acph->headx[i].head), + &(acph->cbuf[acph->headx[i].cind]), + acph->headx[i].head.len, + acph->tmpbuf, PICODATA_MAX_ITEMSIZE, + &blen); + + rvP = picodata_cbPutItem(this->cbOut, acph->tmpbuf, + PICODATA_MAX_ITEMSIZE, &clen); + + *numBytesOutput += clen; + + PICODBG_DEBUG(("put item, status: %d", rvP)); + + if (rvP == PICO_OK) { + acph->headxBottom++; + acph->headxLen--; + } else if (rvP == PICO_EXC_BUF_OVERFLOW) { + /* try again next time, but PHR2/3 + bound already added if existing, + ensure it's not output a 2nd + time */ + PICODBG_DEBUG(("feeding overflow")); + acph->headx[i].boundstrength = 0; + return PICODATA_PU_OUT_FULL; + } else { + /* error, should never happen */ + PICODBG_ERROR(("untreated return value, rvP: %d", rvP)); + return PICODATA_PU_ERROR; + } + + PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], + (picoos_uint8 *)"acph: ", + acph->tmpbuf, PICODATA_MAX_ITEMSIZE); + + break; + } /*switch*/ + } /*for*/ + + /* reset headx, cbuf */ + acph->headxBottom = 0; + acph->headxLen = 0; + acph->cbufLen = 0; + for (i = 0; i < PICOACPH_MAXNR_HEADX; i++) { + acph->headx[i].boundstrength = 0; + } + + /* reset collect state support variables */ + acph->inspaceok = TRUE; + acph->needsmoreitems = TRUE; + + acph->procState = SA_STEPSTATE_COLLECT; + return PICODATA_PU_BUSY; + break; + } + + default: + break; + } /* switch */ + + } /* while */ + + /* should be never reached */ + PICODBG_ERROR(("reached end of function")); + picoos_emRaiseException(this->common->em, PICO_ERR_OTHER, NULL, NULL); + return PICODATA_PU_ERROR; +} + +#ifdef __cplusplus +} +#endif + + +/* end */ diff --git a/pico/lib/picoacph.h b/pico/lib/picoacph.h new file mode 100644 index 0000000..266ab6e --- /dev/null +++ b/pico/lib/picoacph.h @@ -0,0 +1,205 @@ +/* + * 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 picoacph.h + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + + +/** + * @addtogroup picoacph + * +itemtype, iteminfo1, iteminfo2, content -> TYPE(INFO1,INFO2)content +in the following + +items input +=========== + +processed by sa (POS disambiguation): +- WORDGRAPH(POSes,NA)graph +- WORDINDEX(POSes,NA)POS|1ind1...POSN|indN +- CMD(PICODATA_ITEMINFO1_CMD_FLUSH,PICODATA_ITEMINFO2_NA) + +processed by sa (Phrasing, Accentuation): +- PUNC(PUNCtype,PUNCsubtype) + +unprocessed: +- all other item types are forwarded through the PU without modification: + CMD + + +minimal input size (before processing starts) +================== + +processing (POS disambiguation, g2p, lexind, phrasing, accentuation) +is possible with + +- one punctuation-phrase, consisting of a sequence (see below for + limits) of items terminated by a PUNC item. + +(possible but not implemented: as long as the internal buffer is +empty, non-processed item types can be processed immediately) + +Ensuring terminal PUNC item: +- when reading items from the external buffer a CMD(...FLUSH...) is + converted to a PUNC(...FLUSH...) item +- If needed, a PUNC(PHRASE) is artificially added to ensure a phrase + fits in the PUs memory and processing can start. + + +items processed and output +========================== + +precondition: +CMD(...FLUSH...) already converted to PUNC(...FLUSH...) and trailing +PUNC item enforced if necessary. + +---- +-# PROCESS_POSD: processing input WORDGRAPH or WORDINDEX items, after +POS disambiguation (POSes -> POS), results in a sequence of: + - + - WORDGRAPH(POS,NA)graph + - WORDINDEX(POS,NA)POS|ind + - + . +-# PROCESS_WPHO: then, after lex-index lookup and G2P in a +sequence of: + - WORDPHON(POS,NA)phon + +(phon containing primary and secondary word-level stress) + +---- +3. PROCESS_PHR: then, after processing these WORDPHON items, +together with the trailing PUNC item results in: + +-> BOUND(BOUNDstrength,BOUNDtype) + +being added in the sequence of WORDPHON (respectively inserted instead +of the PUNC). All PUNC, incl PUNC(...FLUSH...) now gone. + +---- +4. PROCESS_ACC: then, after processing the WORDPHON and BOUND items +results in: + +-> WORDPHON(POS,ACC)phon + +A postprocessing step of accentuation is hard-coded in the +accentuation module: In case the whole word does not have any stress +at all (primary or secondary or both) then do the following mapping: + + ACC0 nostress -> ACC0 + ACC1 nostress -> ACC3 + ACC2 nostress -> ACC3 + ACC3 nostress -> ACC3 + +---- +- POS + a single, unambiguous POS + +cf. picodata.h for +- ACC (sentence-level accent (aka prominence)) %d + - PICODATA_ACC0 + - PICODATA_ACC1 + - PICODATA_ACC2 (<- maybe mapped to ACC1, ie. no ACC2 in output) + - PICODATA_ACC3 + +- BOUNDstrength %d + - PICODATA_ITEMINFO1_BOUND_SBEG (at sentence start) + - PICODATA_ITEMINFO1_BOUND_SEND (at sentence end) + - PICODATA_ITEMINFO1_BOUND_TERM (replaces a flush) + - PICODATA_ITEMINFO1_BOUND_PHR1 (primary boundary) + - PICODATA_ITEMINFO1_BOUND_PHR2 (short break) + - PICODATA_ITEMINFO1_BOUND_PHR3 (secondary phrase boundary, no break) + - PICODATA_ITEMINFO1_BOUND_PHR0 (no break, not produced by sa, not existing + BOUND in item sequence equals PHR0 bound strength) + +- BOUNDtype (created in sa base on punctuation, indicates type of phrase + following the boundary) %d + - PICODATA_ITEMINFO2_BOUNDTYPE_P + - PICODATA_ITEMINFO2_BOUNDTYPE_T + - PICODATA_ITEMINFO2_BOUNDTYPE_Q + - PICODATA_ITEMINFO2_BOUNDTYPE_E + + +output sequence (without CMDs): + + = { BOUND(BOUND_SBEG,PHRASEtype) BOUND(BOUND_SEND,..)} BOUND(BOUND_TERM,..) + + = { BOUND(BOUND_PHR1|2|3,BOUNDtype) } + + = WORDPHON(POS,ACC)phon { WORDPHON(POS,ACC)phon } + +Done in later PU: mapping ACC & word-level stress to syllable accent value + - ACC0 prim -> 0 + - ACC1 prim -> 1 + - ACC2 prim -> 2 + - ACC3 prim -> 3 + - ACC0 sec -> 0 + - ACC1 sec -> 4 + - ACC2 sec -> 4 + - ACC3 sec -> 4 + +other limitations +================= + +- item size: header plus len=256 (valid for Pico in general) +- see defines below for max nr of items. Item heads plus ref. to contents + buffer are stored in array with fixed size elements. Two restrictions: + - MAXNR_HEADX (max nr elements==items in headx array) + - CONTENTSSIZE (max size of all contents together + */ + + +#ifndef PICOACPH_H_ +#define PICOACPH_H_ + +#include "picoos.h" +#include "picodata.h" +#include "picorsrc.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/* nr item restriction: maximum number of extended item heads in headx */ +#define PICOACPH_MAXNR_HEADX 60 + +/* nr item restriction: maximum size of all item contents together in cont */ +#define PICOACPH_MAXSIZE_CBUF 7680 + + + +picodata_ProcessingUnit picoacph_newAccPhrUnit( + picoos_MemoryManager mm, + picoos_Common common, + picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, + picorsrc_Voice voice); + +#ifdef __cplusplus +} +#endif + +#endif /*PICOACPH_H_*/ diff --git a/pico/lib/picoapi.c b/pico/lib/picoapi.c new file mode 100644 index 0000000..c4ef8bf --- /dev/null +++ b/pico/lib/picoapi.c @@ -0,0 +1,801 @@ +/* + * 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 picoapi.c + * + * 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 "picorsrc.h" +#include "picoctrl.h" +#include "picoapi.h" +#include "picoapid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ****************************************************************************/ +/* System-level API functions */ +/* ****************************************************************************/ + +#define MAGIC_MASK 0x5069636F /* Pico */ + +#define SET_MAGIC_NUMBER(sys) \ + (sys)->magic = ((picoos_uint32) (sys)) ^ MAGIC_MASK + +#define CHECK_MAGIC_NUMBER(sys) \ + ((sys)->magic == (((picoos_uint32) (sys)) ^ MAGIC_MASK)) + + + +/* *** Auxiliary routines (may also be called from picoextapi.c) **************/ + + +int is_valid_system_handle(pico_System system) +{ + return (system != NULL) && CHECK_MAGIC_NUMBER(system); +} + + +picoos_Common pico_sysGetCommon(pico_System this) +{ + if (this != NULL) { + return this->common; + } else { + return NULL; + } +} + + + +/* *** System initialization and termination functions ************************/ +pico_Status pico_initialize_priv( + void *memory, + const pico_Uint32 size, + pico_Int16 enableMemProt, + pico_System *system + ) +{ + pico_Status status = PICO_OK; + + PICODBG_INITIALIZE(PICODBG_LOG_LEVEL_INFO); + PICODBG_ENABLE_COLORS(0); + /*PICODBG_SET_OUTPUT_FORMAT((PICODBG_SHOW_LEVEL | PICODBG_SHOW_SRCNAME));*/ + + if (memory == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else if (size == 0) { + status = PICO_ERR_INVALID_ARGUMENT; + } else if (system == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else { + byte_ptr_t rest_mem; + picoos_uint32 rest_mem_size; + pico_System sys; + picoos_MemoryManager sysMM; + picoos_ExceptionManager sysEM; + + sys = (pico_System) picoos_raw_malloc(memory, size, sizeof(pico_system_t), + &rest_mem, &rest_mem_size); + if (sys != NULL) { + sysMM = picoos_newMemoryManager(rest_mem, rest_mem_size, enableMemProt ? TRUE : FALSE); + if (sysMM != NULL) { + sysEM = picoos_newExceptionManager(sysMM); + sys->common = picoos_newCommon(sysMM); + sys->rm = picorsrc_newResourceManager(sysMM, sys->common); + if ((sysEM != NULL) && (sys->common != NULL) && (sys->rm != NULL)) { + sys->common->em = sysEM; + sys->common->mm = sysMM; + sys->engine = NULL; + + picorsrc_createDefaultResource(sys->rm /*,&defaultResource */); + + SET_MAGIC_NUMBER(sys); + status = PICO_OK; + } else { + status = PICO_EXC_OUT_OF_MEM; + } + } else { + status = PICO_EXC_OUT_OF_MEM; + } + } else { + status = PICO_EXC_OUT_OF_MEM; + } + *system = sys; + } + + if (status != PICO_OK) { + if (system != NULL) { + *system = NULL; + } + PICODBG_TERMINATE(); + } + + return status; +} +/** + * pico_initialize : initializes the pico system private memory + * @param memory : pointer to a free and already allocated memory area + * @param size : size of the memory area + * @param system : pointer to a pico_System struct + * @return PICO_OK : successful init, !PICO_OK : error on allocating private memory + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_initialize( + void *memory, + const pico_Uint32 size, + pico_System *system + ) +{ + return pico_initialize_priv(memory, size, /*enableMemProt*/ FALSE, system); +} + +/** + * pico_terminate : deallocates the pico system private memory + * @param system : pointer to a pico_System struct + * @return PICO_OK : successful de-init, !PICO_OK : error on de-allocating private memory + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_terminate( + pico_System *system + ) +{ + pico_Status status = PICO_OK; + + if ((system == NULL) || !is_valid_system_handle(*system)) { + status = PICO_ERR_INVALID_HANDLE; + } else { + pico_System sys = *system; + + /* close engine(s) */ + picoctrl_disposeEngine(sys->common->mm, sys->rm, &sys->engine); + + /* close all resources */ + picorsrc_disposeResourceManager(sys->common->mm, &sys->rm); + + sys->magic ^= 0xFFFEFDFC; + *system = NULL; + } + + PICODBG_TERMINATE(); + + return status; +} + + + +/* *** System status and error/warning message retrieval function *************/ + +/** + * pico_getSystemStatusMessage : Returns a description of the system status or errors + * @param system : pointer to a pico_System struct + * @param errCode : pico_System error code + * @param outMessage : memory area where to return a string + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_getSystemStatusMessage( + pico_System system, + pico_Status errCode, + pico_Retstring outMessage + ) +{ + pico_Status status = PICO_OK; + + if (!is_valid_system_handle(system)) { + status = PICO_ERR_INVALID_HANDLE; + if (outMessage != NULL) { + picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "'system' not initialized", PICO_RETSTRINGSIZE); + } + } else if (outMessage == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else { + if (picoos_emGetExceptionCode(system->common->em) == PICO_OK) { + if (errCode == PICO_OK) { + picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "system ok", PICO_RETSTRINGSIZE); + } else { + /* exceptionManager was not informed yet; produce default message */ + picoos_setErrorMsg((picoos_char *) outMessage, PICO_RETSTRINGSIZE, errCode, NULL, NULL, NULL); + } + } else { + picoos_emGetExceptionMessage(system->common->em, (picoos_char *) outMessage, PICO_RETSTRINGSIZE); + } + } + + return status; +} + +/** + * pico_getSystemStatusMessage : Returns the number of warnings + * @param system : pointer to a pico_System struct + * @param *outNrOfWarnings : pointer to location to receive number of warnings + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_getNrSystemWarnings( + pico_System system, + pico_Int32 *outNrOfWarnings + ) +{ + pico_Status status = PICO_OK; + + if (!is_valid_system_handle(system)) { + status = PICO_ERR_INVALID_HANDLE; + if (outNrOfWarnings != NULL) { + *outNrOfWarnings = 0; + } + } else if (outNrOfWarnings == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else { + *outNrOfWarnings = picoos_emGetNumOfWarnings(system->common->em); + } + + return status; +} + +/** + * pico_getSystemWarning : Returns a description of a warning + * @param system : pointer to a pico_System struct + * @param warningIndex : warning index + * @param *outCode : pointer to receive the warning code + * @param outMessage : pointer to receive the output message + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_getSystemWarning( + pico_System system, + const pico_Int32 warningIndex, + pico_Status *outCode, + pico_Retstring outMessage + ) +{ + pico_Status status = PICO_OK; + + if (!is_valid_system_handle(system)) { + status = PICO_ERR_INVALID_HANDLE; + if (outMessage != NULL) { + picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "'system' not initialized", PICO_RETSTRINGSIZE); + } + } else if (warningIndex < 0) { + status = PICO_ERR_INDEX_OUT_OF_RANGE; + } else if ((outCode == NULL) || (outMessage == NULL)) { + status = PICO_ERR_NULLPTR_ACCESS; + } else { + *outCode = picoos_emGetWarningCode(system->common->em, warningIndex); + picoos_emGetWarningMessage(system->common->em, warningIndex, (picoos_char *) outMessage, (picoos_uint16) PICO_RETSTRINGSIZE); + } + + return status; +} + + + +/* *** Resource loading and unloading functions *******************************/ + +/** + * pico_loadResource : Loads a resource file into the Pico system + * @param system : pointer to a pico_System struct + * @param *lingwareFileName : lingware resource file name + * @param *outLingware : pointer to receive the loaded lingware resource memory area address + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_loadResource( + pico_System system, + const pico_Char *lingwareFileName, + pico_Resource *outLingware + ) +{ + pico_Status status = PICO_OK; + + if (!is_valid_system_handle(system)) { + status = PICO_ERR_INVALID_HANDLE; + } else if ((lingwareFileName == NULL) || (outLingware == NULL)) { + status = PICO_ERR_NULLPTR_ACCESS; + } else { + PICODBG_DEBUG(("memory usage before resource loading")); + picoos_showMemUsage(system->common->mm, FALSE, TRUE); + picoos_emReset(system->common->em); + status = picorsrc_loadResource(system->rm, (picoos_char *) lingwareFileName, (picorsrc_Resource *) outLingware); + PICODBG_DEBUG(("memory used to load resource %s", lingwareFileName)); + picoos_showMemUsage(system->common->mm, TRUE, FALSE); + } + + return status; +} + +/** + * pico_unloadResource : unLoads a resource file from the Pico system + * @param system : pointer to a pico_System struct + * @param *inoutLingware : pointer to the loaded lingware resource memory area address + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_unloadResource( + pico_System system, + pico_Resource *inoutLingware + ) +{ + pico_Status status = PICO_OK; + + if (!is_valid_system_handle(system)) { + status = PICO_ERR_INVALID_HANDLE; + } else if (inoutLingware == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else if (!picoctrl_isValidResourceHandle(*((picorsrc_Resource *) inoutLingware))) { + status = PICO_ERR_INVALID_HANDLE; + } else { + PICODBG_DEBUG(("memory usage before resource unloading")); + picoos_showMemUsage(system->common->mm, FALSE, TRUE); + picoos_emReset(system->common->em); + status = picorsrc_unloadResource(system->rm, (picorsrc_Resource *) inoutLingware); + PICODBG_DEBUG(("memory released by resource unloading")); + picoos_showMemUsage(system->common->mm, TRUE, FALSE); + } + + return status; +} + +/* *** Resource inspection functions *******************************/ +/** + * pico_getResourceName : Gets a resource name + * @param system : pointer to a pico_System struct + * @param resource : pointer to the loaded resource memory area address + * @param outName : pointer to the area to receuive the resource name + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_getResourceName( + pico_System system, + pico_Resource resource, + pico_Retstring outName) { + + if (!is_valid_system_handle(system)) { + return PICO_ERR_INVALID_HANDLE; + } else if (NULL == outName) { + return PICO_ERR_NULLPTR_ACCESS; + } + return picorsrc_rsrcGetName((picorsrc_Resource)resource, (picoos_char *) outName, PICO_RETSTRINGSIZE); +} + + +/* *** Voice definition functions *********************************************/ + +/** + * pico_createVoiceDefinition : Creates a voice definition + * @param system : pointer to a pico_System struct + * @param *voiceName : pointer to the area to receive the voice definition + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_createVoiceDefinition( + pico_System system, + const pico_Char *voiceName + ) +{ + pico_Status status = PICO_OK; + + if (!is_valid_system_handle(system)) { + status = PICO_ERR_INVALID_HANDLE; + } else if (voiceName == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else if (picoos_strlen((picoos_char *) voiceName) == 0) { + status = PICO_ERR_INVALID_ARGUMENT; + } else { + picoos_emReset(system->common->em); + status = picorsrc_createVoiceDefinition(system->rm, (picoos_char *) voiceName); + } + + return status; +} + +/** + * pico_addResourceToVoiceDefinition : Adds a mapping pair to a voice definition + * @param system : pointer to a pico_System struct + * @param *voiceName : pointer to the area containing the voice definition + * @param *resourceName : pointer to the area containing the resource name + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_addResourceToVoiceDefinition( + pico_System system, + const pico_Char *voiceName, + const pico_Char *resourceName + ) +{ + pico_Status status = PICO_OK; + + if (!is_valid_system_handle(system)) { + status = PICO_ERR_INVALID_HANDLE; + } else if (voiceName == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else if (picoos_strlen((picoos_char *) voiceName) == 0) { + status = PICO_ERR_INVALID_ARGUMENT; + } else if (resourceName == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else if (picoos_strlen((picoos_char *) resourceName) == 0) { + status = PICO_ERR_INVALID_ARGUMENT; + } else { + picoos_emReset(system->common->em); + status = picorsrc_addResourceToVoiceDefinition(system->rm, (picoos_char *) voiceName, (picoos_char *) resourceName); + } + + return status; +} + +/** + * pico_releaseVoiceDefinition : Releases a voice definition + * @param system : pointer to a pico_System struct + * @param *voiceName : pointer to the area containing the voice definition + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_releaseVoiceDefinition( + pico_System system, + const pico_Char *voiceName + ) +{ + pico_Status status = PICO_OK; + + if (!is_valid_system_handle(system)) { + status = PICO_ERR_INVALID_HANDLE; + } else if (voiceName == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else if (picoos_strlen((picoos_char *) voiceName) == 0) { + status = PICO_ERR_INVALID_ARGUMENT; + } else { + picoos_emReset(system->common->em); + status = picorsrc_releaseVoiceDefinition(system->rm, (picoos_char *) voiceName); + } + + return status; +} + + + +/* *** Engine creation and deletion functions *********************************/ + +/** + * pico_newEngine : Creates and initializes a new Pico engine + * @param system : pointer to a pico_System struct + * @param *voiceName : pointer to the area containing the voice definition + * @param *outEngine : pointer to the Pico engine handle + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_newEngine( + pico_System system, + const pico_Char *voiceName, + pico_Engine *outEngine + ) +{ + pico_Status status = PICO_OK; + + PICODBG_DEBUG(("creating engine for voice '%s'", (picoos_char *) voiceName)); + + if (!is_valid_system_handle(system)) { + status = PICO_ERR_INVALID_HANDLE; + } else if (voiceName == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else if (picoos_strlen((picoos_char *) voiceName) == 0) { + status = PICO_ERR_INVALID_ARGUMENT; + } else if (outEngine == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else { + picoos_emReset(system->common->em); + if (system->engine == NULL) { + *outEngine = (pico_Engine) picoctrl_newEngine(system->common->mm, system->rm, voiceName); + if (*outEngine != NULL) { + system->engine = (picoctrl_Engine) *outEngine; + } else { + status = picoos_emRaiseException(system->common->em, PICO_EXC_OUT_OF_MEM, + (picoos_char *) "out of memory creating new engine", NULL); + } + } else { + status = picoos_emRaiseException(system->common->em, PICO_EXC_MAX_NUM_EXCEED, + NULL, (picoos_char *) "no more than %i engines", 1); + } + } + + return status; +} + +/** + * pico_disposeEngine : Disposes a Pico engine + * @param system : pointer to a pico_System struct + * @param *inoutEngine : pointer to the Pico engine handle + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_disposeEngine( + pico_System system, + pico_Engine *inoutEngine + ) +{ + pico_Status status = PICO_OK; + + if (!is_valid_system_handle(system)) { + status = PICO_ERR_INVALID_HANDLE; + } else if (inoutEngine == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else if (!picoctrl_isValidEngineHandle(*((picoctrl_Engine *) inoutEngine))) { + status = PICO_ERR_INVALID_HANDLE; + } else { + picoos_emReset(system->common->em); + picoctrl_disposeEngine(system->common->mm, system->rm, (picoctrl_Engine *) inoutEngine); + system->engine = NULL; + status = picoos_emGetExceptionCode(system->common->em); + } + + return status; +} + + + +/* ****************************************************************************/ +/* Engine-level API functions */ +/* ****************************************************************************/ + +/** + * pico_putTextUtf8 : Puts UTF8 text into Pico text input buffer + * @param engine : pointer to a Pico engine handle + * @param *text : pointer to the text buffer + * @param textSize : text buffer size + * @param *bytesPut : pointer to variable to receive the number of bytes put + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph + */ +PICO_FUNC pico_putTextUtf8( + pico_Engine engine, + const pico_Char *text, + const pico_Int16 textSize, + pico_Int16 *bytesPut) +{ + pico_Status status = PICO_OK; + + if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) { + status = PICO_ERR_INVALID_HANDLE; + } else if (text == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else if (textSize < 0) { + status = PICO_ERR_INVALID_ARGUMENT; + } else if (bytesPut == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else { + picoctrl_engResetExceptionManager((picoctrl_Engine) engine); + status = picoctrl_engFeedText((picoctrl_Engine) engine, (picoos_char *)text, textSize, bytesPut); + } + + return status; +} + +/** + * pico_getData : Gets speech data from the engine. + * @param engine : pointer to a Pico engine handle + * @param *buffer : pointer to output buffer + * @param bufferSize : out buffer size + * @param *bytesReceived : pointer to a variable to receive the number of bytes received + * @param *outDataType : pointer to a variable to receive the type of buffer received + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_getData( + pico_Engine engine, + void *buffer, + const pico_Int16 bufferSize, + pico_Int16 *bytesReceived, + pico_Int16 *outDataType + ) +{ + pico_Status status = PICO_OK; + + if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) { + status = PICO_STEP_ERROR; + } else if (buffer == NULL) { + status = PICO_STEP_ERROR; + } else if (bufferSize < 0) { + status = PICO_STEP_ERROR; + } else if (bytesReceived == NULL) { + status = PICO_STEP_ERROR; + } else { + picoctrl_engResetExceptionManager((picoctrl_Engine) engine); + status = picoctrl_engFetchOutputItemBytes((picoctrl_Engine) engine, (picoos_char *)buffer, bufferSize, bytesReceived); + if ((status != PICO_STEP_IDLE) && (status != PICO_STEP_BUSY)) { + status = PICO_STEP_ERROR; + } + } + + *outDataType = PICO_DATA_PCM_16BIT; + return status; +} + +/** + * pico_resetEngine : Resets the engine + * @param engine : pointer to a Pico engine handle + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_resetEngine( + pico_Engine engine) +{ + pico_Status status = PICO_OK; + + if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) { + status = PICO_ERR_INVALID_HANDLE; + } else { + picoctrl_engResetExceptionManager((picoctrl_Engine) engine); + status = picoctrl_engReset((picoctrl_Engine) engine); + } + + return status; +} + +/** + * pico_getEngineStatusMessage : Returns the engine status or error description + * @param engine : pointer to a Pico engine handle + * @param errCode : error code + * @param outMessage : pointer to a memory area to receive the output message + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_getEngineStatusMessage( + pico_Engine engine, + pico_Status errCode, + pico_Retstring outMessage + ) +{ + pico_Status status = PICO_OK; + + PICODBG_DEBUG(("got error code %i", errCode)); + + if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) { + status = PICO_ERR_INVALID_HANDLE; + if (outMessage != NULL) { + picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "'engine' not initialized", PICO_RETSTRINGSIZE); + } + } else if (outMessage == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else { + picoos_Common common = picoctrl_engGetCommon((picoctrl_Engine) engine); + if (picoos_emGetExceptionCode(common->em) == PICO_OK) { + if (errCode == PICO_OK) { + picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "engine ok", PICO_RETSTRINGSIZE); + } else { + /* exceptionManager was not informed yet; produce default message */ + picoos_setErrorMsg((picoos_char *) outMessage, PICO_RETSTRINGSIZE, errCode, NULL, NULL, NULL); + } + } else { + picoos_emGetExceptionMessage(common->em, (picoos_char *) outMessage, PICO_RETSTRINGSIZE); + } + } + + return status; +} + +/** + * pico_getNrEngineWarnings : Returns the number of warnings + * @param engine : pointer to a Pico engine handle + * @param *outNrOfWarnings: pointer to a variable to receive the number of warnings + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_getNrEngineWarnings( + pico_Engine engine, + pico_Int32 *outNrOfWarnings + ) +{ + pico_Status status = PICO_OK; + + if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) { + status = PICO_ERR_INVALID_HANDLE; + if (outNrOfWarnings != NULL) { + *outNrOfWarnings = 0; + } + } else if (outNrOfWarnings == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else { + picoos_Common common = picoctrl_engGetCommon((picoctrl_Engine) engine); + *outNrOfWarnings = picoos_emGetNumOfWarnings(common->em); + } + + return status; +} + +/** + * pico_getEngineWarning : Returns a description of a warning + * @param engine : pointer to a Pico engine handle + * @param warningIndex : warning index + * @param *outCode: pointer to a variable to receive the warning code + * @param outMessage: pointer to a memory area to receive the warning description + * @return PICO_OK : successful + * @return PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors + * @callgraph + * @callergraph +*/ +PICO_FUNC pico_getEngineWarning( + pico_Engine engine, + const pico_Int32 warningIndex, + pico_Status *outCode, + pico_Retstring outMessage + ) +{ + pico_Status status = PICO_OK; + + if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) { + status = PICO_ERR_INVALID_HANDLE; + if (outMessage != NULL) { + picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "'engine' not initialized", PICO_RETSTRINGSIZE); + } + } else if (warningIndex < 0) { + status = PICO_ERR_INDEX_OUT_OF_RANGE; + } else if ((outCode == NULL) || (outMessage == NULL)) { + status = PICO_ERR_NULLPTR_ACCESS; + } else { + picoos_Common common = picoctrl_engGetCommon((picoctrl_Engine) engine); + *outCode = picoos_emGetWarningCode(common->em, warningIndex); + picoos_emGetWarningMessage(common->em, warningIndex, (picoos_char *) outMessage, (picoos_uint16) PICO_RETSTRINGSIZE); + } + + return status; +} + +#ifdef __cplusplus +} +#endif + + +/* end */ diff --git a/pico/lib/picoapi.h b/pico/lib/picoapi.h new file mode 100644 index 0000000..0dad702 --- /dev/null +++ b/pico/lib/picoapi.h @@ -0,0 +1,469 @@ +/* + * 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 picoapi.h + * + * SVOX Pico application programming interface + * (SVOX Pico version 1.0 and later) + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + */ + + +/** + * @addtogroup picoapi + * +@b Basic_Concepts + +@e SVOX_Pico_System + +The SVOX Pico 'system' is the entity that manages data common to all +SVOX Pico engines, e.g. linguistic data needed to do text-to-speech +(TTS) synthesis, license key, etc. All API functions on the Pico +system level take a 'pico_System' handle as the first parameter. + +@e SVOX_Pico_Engine + +A SVOX Pico 'engine' provides the functions needed to perform actual +synthesis. Currently there can be only one engine instance at a time +(concurrent engines will be possible in the future). All API functions +at the engine level take a 'pico_Engine' handle as the first +parameter. + +@e SVOX_Pico_Resource + +A SVOX Pico 'resource' denotes all the language- and speaker-dependent +data needed to do TTS synthesis. In the following, the term 'resource' +may be used interchangeably with the term 'lingware'. A resource file +contains a set of knowledge bases for an entire TTS voice or parts of +it. + + +@b Basic_Usage + +In its most basic form, an application must call the following +functions in order to perform TTS synthesis: + + - pico_initialize + - pico_loadResource + - pico_createVoiceDefinition + - pico_addResourceToVoiceDefinition + - pico_newEngine + - pico_putTextUtf8 + - pico_getData (several times) + - pico_disposeEngine + - pico_releaseVoiceDefinition + - pico_unloadResource + - pico_terminate + +It is possible to repeatedly run the above sequence, i.e., the SVOX +Pico system may be initialized and terminated multiple times. This may +be useful in applications that need TTS functionality only from time +to time. + + +@b Conventions + +@e Function_arguments + +All arguments that only return values are marked by a leading 'out...' +in their name. All arguments that are used as input and output values +are marked by a leading 'inout...'. All other arguments are read-only +(input) arguments. + +@e Error_handling + +All API functions return a status code which is one of the status +constants defined in picodefs.h. In case of an error, a more detailed +description of the status can be retrieved by calling function +'pico_getSystemStatusMessage' (or 'pico_getEngineStatusMessage' +if the error happened on the SVOX Pico engine level). + +Unlike errors, warnings do not prevent an API function from performing +its function, but output might not be as intended. Functions +'pico_getNrSystemWarnings' and 'pico_getNrEngineWarnings' respectively +can be used to determine whether an API function caused any +warnings. Details about warnings can be retrieved by calling +'pico_getSystemWarning' and 'pico_getEngineWarning' respectively. + +*/ + + + +#ifndef PICOAPI_H_ +#define PICOAPI_H_ + + + +#include "picodefs.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +#ifdef _WIN32 +# define PICO_EXPORT __declspec( dllexport ) +#else +# define PICO_EXPORT extern +#endif + +#define PICO_FUNC PICO_EXPORT pico_Status + + + +/* ********************************************************************/ +/* PICO data types */ +/* ********************************************************************/ + +/* Handle types (opaque) for Pico system, resource, engine ************/ + +typedef struct pico_system *pico_System; +typedef struct pico_resource *pico_Resource; +typedef struct pico_engine *pico_Engine; + + +/* Signed/unsigned integer data types *********************************/ + +#define PICO_INT16_MAX 32767 +#define PICO_UINT16_MAX 0xffff +#define PICO_INT32_MAX 2147483647 +#define PICO_UINT32_MAX 0xffffffff + +#include + +#if (SHRT_MAX == PICO_INT16_MAX) +typedef short pico_Int16; +#else +#error "platform not supported" +#endif + +#if (USHRT_MAX == PICO_UINT16_MAX) +typedef unsigned short pico_Uint16; +#else +#error "platform not supported" +#endif + +#if (INT_MAX == PICO_INT32_MAX) +typedef int pico_Int32; +#else +#error "platform not supported" +#endif + +#if (UINT_MAX == PICO_UINT32_MAX) +typedef unsigned int pico_Uint32; +#else +#error "platform not supported" +#endif + + +/* Char data type *****************************************************/ + +typedef unsigned char pico_Char; + + +/* String type to be used when ASCII string values are returned *******/ + +#define PICO_RETSTRINGSIZE 200 /* maximum length of returned strings */ + +typedef char pico_Retstring[PICO_RETSTRINGSIZE]; + + + +/* ********************************************************************/ +/* System-level API functions */ +/* ********************************************************************/ + +/* System initialization and termination functions ********************/ + +/** + Initializes the Pico system and returns its handle in 'outSystem'. + 'memory' and 'size' define the location and maximum size of memory + in number of bytes that the Pico system will use. The minimum size + required depends on the number of engines and configurations of + lingware to be used. No additional memory will be allocated by the + Pico system. This function must be called before any other API + function is called. It may only be called once (e.g. at application + startup), unless a call to 'pico_terminate'. +*/ +PICO_FUNC pico_initialize( + void *memory, + const pico_Uint32 size, + pico_System *outSystem + ); + +/** + Terminates the Pico system. Lingware resources still being loaded + are unloaded automatically. The memory area provided to Pico in + 'pico_initialize' is released. The system handle becomes + invalid. It is not allowed to call this function as long as Pico + engine instances are existing. No API function may be called after + this function, except for 'pico_initialize', which reinitializes + the system. +*/ +PICO_FUNC pico_terminate( + pico_System *system + ); + + +/* System status and error/warning message retrieval ******************/ + +/** + Returns in 'outMessage' a description of the system status or of an + error that occurred with the most recently called system-level API + function. +*/ +PICO_FUNC pico_getSystemStatusMessage( + pico_System system, + pico_Status errCode, + pico_Retstring outMessage + ); + +/** + Returns in 'outNrOfWarnings' the number of warnings that occurred + with the most recently called system-level API function. +*/ +PICO_FUNC pico_getNrSystemWarnings( + pico_System system, + pico_Int32 *outNrOfWarnings + ); + +/** + Returns in 'outMessage' a description of a warning that occurred + with the most recently called system-level API function. + 'warningIndex' must be in the range 0..N-1 where N is the number of + warnings returned by 'pico_getNrSystemWarnings'. 'outCode' returns + the warning as an integer code (cf. PICO_WARN_*). +*/ +PICO_FUNC pico_getSystemWarning( + pico_System system, + const pico_Int32 warningIndex, + pico_Status *outCode, + pico_Retstring outMessage + ); + + +/* Resource loading and unloading functions ***************************/ + +/** + Loads a resource file into the Pico system. The number of resource + files loaded in parallel is limited by PICO_MAX_NUM_RESOURCES. + Loading of a resource file may be done at any time (even in + parallel to a running engine doing TTS synthesis), but with the + general restriction that functions taking a system handle as their + first argument must be called in a mutually exclusive fashion. The + loaded resource will be available only to engines started after the + resource is fully loaded, i.e., not to engines currently + running. +*/ +PICO_FUNC pico_loadResource( + pico_System system, + const pico_Char *resourceFileName, + pico_Resource *outResource + ); + +/** + Unloads a resource file from the Pico system. If no engine uses the + resource file, the resource is removed immediately and its + associated internal memory is released, otherwise + PICO_EXC_RESOURCE_BUSY is returned. +*/ +PICO_FUNC pico_unloadResource( + pico_System system, + pico_Resource *inoutResource + ); + +/* *** Resource inspection functions *******************************/ + +/** + Gets the unique resource name of a loaded resource +*/ +PICO_FUNC pico_getResourceName( + pico_System system, + pico_Resource resource, + pico_Retstring outName); + + +/* Voice definition ***************************************************/ + +/** + Creates a voice definition. Resources must be added to the created + voice with 'pico_addResourceToVoiceDefinition' before using the + voice in 'pico_newEngine'. It is an error to create a voice + definition with a previously defined voice name. In that case use + 'pico_releaseVoiceName' first. +*/ +PICO_FUNC pico_createVoiceDefinition( + pico_System system, + const pico_Char *voiceName + ); + +/** + Adds a mapping pair ('voiceName', 'resourceName') to the voice + definition. Multiple mapping pairs can added to a voice defintion. + When calling 'pico_newEngine' with 'voiceName', the corresponding + resources from the mappings will be used with that engine. */ + +PICO_FUNC pico_addResourceToVoiceDefinition( + pico_System system, + const pico_Char *voiceName, + const pico_Char *resourceName + ); + + +/** + Releases the voice definition 'voiceName'. + +*/ +PICO_FUNC pico_releaseVoiceDefinition( + pico_System system, + const pico_Char *voiceName + ); + + +/* Engine creation and deletion functions *****************************/ + +/** + Creates and initializes a new Pico engine instance and returns its + handle in 'outEngine'. Only one instance per system is currently + possible. +*/ +PICO_FUNC pico_newEngine( + pico_System system, + const pico_Char *voiceName, + pico_Engine *outEngine + ); + + +/** + Disposes a Pico engine and releases all memory it occupied. The + engine handle becomes invalid. +*/ +PICO_FUNC pico_disposeEngine( + pico_System system, + pico_Engine *inoutEngine + ); + + + +/* ********************************************************************/ +/* Engine-level API functions */ +/* ********************************************************************/ + +/** + Puts text 'text' encoded in UTF8 into the Pico text input buffer. + 'textSize' is the maximum size in number of bytes accessible in + 'text'. The input text may also contain text-input commands to + change, for example, speed or pitch of the resulting speech + output. The number of bytes actually copied to the Pico text input + buffer is returned in 'outBytesPut'. Sentence ends are + automatically detected. '\0' characters may be embedded in 'text' + to finish text input or separate independently to be synthesized + text parts from each other. Repeatedly calling 'pico_getData' will + result in the content of the text input buffer to be synthesized + (up to the last sentence end or '\0' character detected). To empty + the internal buffers without finishing synthesis, use the function + 'pico_resetEngine'. +*/ +PICO_FUNC pico_putTextUtf8( + pico_Engine engine, + const pico_Char *text, + const pico_Int16 textSize, + pico_Int16 *outBytesPut + ); + +/** + Gets speech data from the engine. Every time this function is + called, the engine performs, within a short time slot, a small + amount of processing its input text, and then gives control back to + the calling application. Ie. after calling 'pico_putTextUtf8' + (incl. a final embedded '\0'), this function needs to be called + repeatedly till 'outBytesReceived' bytes are returned in + 'outBuffer'. The type of data returned in 'outBuffer' (e.g. 8 or 16 + bit PCM samples) is returned in 'outDataType' and depends on the + lingware resources. Possible 'outDataType' values are listed in + picodefs.h (PICO_DATA_*). + This function returns PICO_STEP_BUSY while processing input and + producing speech output. Once all data is returned and there is no + more input text available in the Pico text input buffer, + PICO_STEP_IDLE is returned. All other function return values + indicate a system error. +*/ +PICO_FUNC pico_getData( + pico_Engine engine, + void *outBuffer, + const pico_Int16 bufferSize, + pico_Int16 *outBytesReceived, + pico_Int16 *outDataType + ); + +/** + Resets the engine and clears all engine-internal buffers, in + particular text input and signal data output buffers. +*/ +PICO_FUNC pico_resetEngine( + pico_Engine engine + ); + + +/* Engine status and error/warning message retrieval ******************/ + +/** + Returns in 'outMessage' a description of the engine status or of an + error that occurred with the most recently called engine-level API + function. +*/ +PICO_FUNC pico_getEngineStatusMessage( + pico_Engine engine, + pico_Status errCode, + pico_Retstring outMessage + ); + +/** + Returns in 'outNrOfWarnings' the number of warnings that occurred + with the most recently called engine-level API function. +*/ +PICO_FUNC pico_getNrEngineWarnings( + pico_Engine engine, + pico_Int32 *outNrOfWarnings + ); + +/** + Returns in 'outMessage' a description of a warning that occurred + with the most recently called engine-level API function. + 'warningIndex' must be in the range 0..N-1 where N is the number of + warnings returned by 'pico_getNrEngineWarnings'. 'outCode' returns + the warning as an integer code (cf. PICO_WARN_*). +*/ +PICO_FUNC pico_getEngineWarning( + pico_Engine engine, + const pico_Int32 warningIndex, + pico_Status *outCode, + pico_Retstring outMessage + ); + +#ifdef __cplusplus +} +#endif + +#endif /*PICOAPI_H_*/ diff --git a/pico/lib/picoapid.h b/pico/lib/picoapid.h new file mode 100644 index 0000000..ef62701 --- /dev/null +++ b/pico/lib/picoapid.h @@ -0,0 +1,70 @@ +/* + * 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 picoapid.h + * + * Pico api definitions commonly used by picoapi and picoapiext + * + * This header file must be part of the runtime-only pico system and therefore + * must not include picoapiext.h! + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#ifndef PICOAPID_H_ +#define PICOAPID_H_ + +#include "picodefs.h" +#include "picoapi.h" +#include "picoos.h" +#include "picorsrc.h" +#include "picoctrl.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* Pico system descriptor */ +typedef struct pico_system { + picoos_uint32 magic; /* magic number used to validate handles */ + picoos_Common common; + picorsrc_ResourceManager rm; + picoctrl_Engine engine; +} pico_system_t; + + +/* declared in picoapi.c */ +extern int is_valid_system_handle(pico_System system); +extern picoos_Common pico_sysGetCommon(pico_System this); + + +#if 0 +{ +#endif +#ifdef __cplusplus +} +#endif + +#endif /* PICOAPID_H_ */ diff --git a/pico/lib/picobase.c b/pico/lib/picobase.c new file mode 100644 index 0000000..9246551 --- /dev/null +++ b/pico/lib/picobase.c @@ -0,0 +1,1243 @@ +/* + * 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 picobase.c + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#include "picoos.h" +#include "picodbg.h" +#include "picodefs.h" +#include "picobase.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/** + * @addtogroup picobase + * + * @b Unicode_UTF8_functions + * + * UTF8 + * scalar value 1st Byte 2nd Byte 3rd Byte 4th Byte + * 00000000 0xxxxxxx 0xxxxxxx + * 00000yyy yyxxxxxx 110yyyyy 10xxxxxx + * zzzzyyyy yyxxxxxx 1110zzzz 10yyyyyy 10xxxxxx + * 000uuuuu zzzzyyyy yyxxxxx 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx + * +*/ +picoos_int32 picobase_utf8_length(const picoos_uint8 *utf8str, + const picoos_uint16 maxlen) { + + picoos_uint16 i; + picoos_uint16 len; + picoos_uint8 follow; + picoos_uint8 ok; + + ok = TRUE; + i = 0; + len = 0; + follow = 0; + while (ok && (i < maxlen) && (utf8str[i] != '\000')) { + if (follow > 0) { + if ((utf8str[i] >= (picoos_uint8)'\200') && + (utf8str[i] < (picoos_uint8)'\300')) { + follow--; + } else { + ok = FALSE; + } + } else if (utf8str[i] < (picoos_uint8)'\200') { + len++; + } else if (utf8str[i] >= (picoos_uint8)'\370') { + ok = FALSE; + } else if (utf8str[i] >= (picoos_uint8)'\360') { + follow = 3; + len++; + } else if (utf8str[i] >= (picoos_uint8)'\340') { + follow = 2; + len++; + } else if (utf8str[i] >= (picoos_uint8)'\300') { + follow = 1; + len++; + } else { + ok = FALSE; + } + i++; + } + if (ok) { + return len; + } else { + return -1; + } +} + + +static picoos_uint32 base_utf32_lowercase (picoos_uint32 utf32) +{ + + picoos_uint32 lc; + + lc = utf32; + if (((utf32 >= 65313) && (utf32 <= 65338))) { + lc = (utf32 + 32); + } else if (((utf32 >= 66560) && (utf32 <= 66599))) { + lc = (utf32 + 40); + } else if (((utf32 >= 7680) && (utf32 <= 9423))) { + switch (utf32) { + case 7680: case 7681: case 7682: case 7683: case 7684: case 7685: case 7686: case 7687: case 7688: case 7689: + case 7690: case 7691: case 7692: case 7693: case 7694: case 7695: case 7696: case 7697: case 7698: case 7699: case 7700: case 7701: + case 7702: case 7703: case 7704: case 7705: case 7706: case 7707: case 7708: case 7709: case 7710: case 7711: case 7712: case 7713: + case 7714: case 7715: case 7716: case 7717: case 7718: case 7719: case 7720: case 7721: case 7722: case 7723: case 7724: case 7725: + case 7726: case 7727: case 7728: case 7729: case 7730: case 7731: case 7732: case 7733: case 7734: case 7735: case 7736: case 7737: + case 7738: case 7739: case 7740: case 7741: case 7742: case 7743: case 7744: case 7745: case 7746: case 7747: case 7748: case 7749: + case 7750: case 7751: case 7752: case 7753: case 7754: case 7755: case 7756: case 7757: case 7758: case 7759: case 7760: case 7761: + case 7762: case 7763: case 7764: case 7765: case 7766: case 7767: case 7768: case 7769: case 7770: case 7771: case 7772: case 7773: + case 7774: case 7775: case 7776: case 7777: case 7778: case 7779: case 7780: case 7781: case 7782: case 7783: case 7784: case 7785: + case 7786: case 7787: case 7788: case 7789: case 7790: case 7791: case 7792: case 7793: case 7794: case 7795: case 7796: case 7797: + case 7798: case 7799: case 7800: case 7801: case 7802: case 7803: case 7804: case 7805: case 7806: case 7807: case 7808: case 7809: + case 7810: case 7811: case 7812: case 7813: case 7814: case 7815: case 7816: case 7817: case 7818: case 7819: case 7820: case 7821: + case 7822: case 7823: case 7824: case 7825: case 7826: case 7827: case 7828: case 7840: case 7841: case 7842: case 7843: + case 7844: case 7845: case 7846: case 7847: case 7848: case 7849: case 7850: case 7851: case 7852: case 7853: case 7854: case 7855: + case 7856: case 7857: case 7858: case 7859: case 7860: case 7861: case 7862: case 7863: case 7864: case 7865: case 7866: case 7867: + case 7868: case 7869: case 7870: case 7871: case 7872: case 7873: case 7874: case 7875: case 7876: case 7877: case 7878: case 7879: + case 7880: case 7881: case 7882: case 7883: case 7884: case 7885: case 7886: case 7887: case 7888: case 7889: case 7890: case 7891: + case 7892: case 7893: case 7894: case 7895: case 7896: case 7897: case 7898: case 7899: case 7900: case 7901: case 7902: case 7903: + case 7904: case 7905: case 7906: case 7907: case 7908: case 7909: case 7910: case 7911: case 7912: case 7913: case 7914: case 7915: + case 7916: case 7917: case 7918: case 7919: case 7920: case 7921: case 7922: case 7923: case 7924: case 7925: case 7926: case 7927: + case 7928: + if ( !(((utf32) % 2 == 1))) { + lc = (utf32 + 1); + } + break; + case 7944: case 7945: case 7946: case 7947: case 7948: case 7949: case 7950: case 7951: case 7960: + case 7961: case 7962: case 7963: case 7964: case 7965: case 7976: case 7977: case 7978: case 7979: case 7980: case 7981: + case 7982: case 7983: case 7992: case 7993: case 7994: case 7995: case 7996: case 7997: case 7998: case 7999: + case 8008: case 8009: case 8010: case 8011: case 8012: case 8013: case 8040: case 8041: case 8042: case 8043: case 8044: + case 8045: case 8046: case 8047: case 8072: case 8073: case 8074: case 8075: case 8076: case 8077: case 8078: case 8079: + case 8088: case 8089: case 8090: case 8091: case 8092: case 8093: case 8094: case 8095: case 8104: case 8105: + case 8106: case 8107: case 8108: case 8109: case 8110: case 8111: + lc = (utf32 - 8); + break; + case 8025: case 8026: case 8027: case 8028: case 8029: case 8030: case 8031: + if (((utf32) % 2 == 1)) { + lc = (utf32 - 8); + } + break; + case 8544: case 8545: case 8546: case 8547: case 8548: case 8549: case 8550: case 8551: case 8552: case 8553: + case 8554: case 8555: case 8556: case 8557: case 8558: case 8559: + lc = (utf32 + 16); + break; + case 9398: case 9399: case 9400: case 9401: case 9402: case 9403: case 9404: case 9405: case 9406: case 9407: + case 9408: case 9409: case 9410: case 9411: case 9412: case 9413: case 9414: case 9415: case 9416: case 9417: case 9418: case 9419: + case 9420: case 9421: case 9422: case 9423: + lc = (utf32 + 26); + break; + case 8120: + lc = 8112; + break; + case 8121: + lc = 8113; + break; + case 8122: + lc = 8048; + break; + case 8123: + lc = 8049; + break; + case 8124: + lc = 8115; + break; + case 8136: + lc = 8050; + break; + case 8137: + lc = 8051; + break; + case 8138: + lc = 8052; + break; + case 8139: + lc = 8053; + break; + case 8140: + lc = 8131; + break; + case 8152: + lc = 8144; + break; + case 8153: + lc = 8145; + break; + case 8154: + lc = 8054; + break; + case 8155: + lc = 8055; + break; + case 8168: + lc = 8160; + break; + case 8169: + lc = 8161; + break; + case 8170: + lc = 8058; + break; + case 8171: + lc = 8059; + break; + case 8172: + lc = 8165; + break; + case 8184: + lc = 8056; + break; + case 8185: + lc = 8057; + break; + case 8186: + lc = 8060; + break; + case 8187: + lc = 8061; + break; + case 8188: + lc = 8179; + break; + case 8486: + lc = 969; + break; + case 8490: + lc = 107; + break; + case 8491: + lc = 229; + break; + default: + break; + } + } else { + switch (utf32) { + case 65: case 66: case 67: case 68: case 69: case 70: case 71: case 72: case 73: case 74: + case 75: case 76: case 77: case 78: case 79: case 80: case 81: case 82: case 83: case 84: case 85: case 86: + case 87: case 88: case 89: case 90: case 192: case 193: case 194: case 195: case 196: case 197: case 198: + case 199: case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207: case 208: case 209: case 210: + case 211: case 212: case 213: case 214: case 216: case 217: case 218: case 219: case 220: case 221: case 222: + case 913: case 914: case 915: case 916: case 917: case 918: case 919: case 920: case 921: case 922: case 923: + case 924: case 925: case 926: case 927: case 928: case 929: case 931: case 932: case 933: case 934: case 935: + case 936: case 937: case 938: case 939: case 1040: case 1041: case 1042: case 1043: case 1044: case 1045: case 1046: + case 1047: case 1048: case 1049: case 1050: case 1051: case 1052: case 1053: case 1054: case 1055: case 1056: case 1057: case 1058: + case 1059: case 1060: case 1061: case 1062: case 1063: case 1064: case 1065: case 1066: case 1067: case 1068: case 1069: case 1070: + case 1071: + lc = (utf32 + 32); + break; + case 256: case 257: case 258: case 259: case 260: case 261: case 262: case 263: case 264: case 265: + case 266: case 267: case 268: case 269: case 270: case 271: case 272: case 273: case 274: case 275: case 276: case 277: + case 278: case 279: case 280: case 281: case 282: case 283: case 284: case 285: case 286: case 287: case 288: case 289: + case 290: case 291: case 292: case 293: case 294: case 295: case 296: case 297: case 298: case 299: case 300: case 301: + case 302: case 303: case 305: case 306: case 307: case 308: case 309: case 310: case 330: case 331: + case 332: case 333: case 334: case 335: case 336: case 337: case 338: case 339: case 340: case 341: case 342: case 343: + case 344: case 345: case 346: case 347: case 348: case 349: case 350: case 351: case 352: case 353: case 354: case 355: + case 356: case 357: case 358: case 359: case 360: case 361: case 362: case 363: case 364: case 365: case 366: case 367: + case 368: case 369: case 370: case 371: case 372: case 373: case 374: case 416: case 417: case 418: case 419: + case 420: case 478: case 479: case 480: case 481: case 482: case 483: case 484: case 485: case 486: case 487: + case 488: case 489: case 490: case 491: case 492: case 493: case 494: case 504: case 505: case 506: case 507: + case 508: case 509: case 510: case 511: case 512: case 513: case 514: case 515: case 516: case 517: case 518: case 519: + case 520: case 521: case 522: case 523: case 524: case 525: case 526: case 527: case 528: case 529: case 530: case 531: + case 532: case 533: case 534: case 535: case 536: case 537: case 538: case 539: case 540: case 541: case 542: + case 546: case 547: case 548: case 549: case 550: case 551: case 552: case 553: case 554: case 555: case 556: case 557: + case 558: case 559: case 560: case 561: case 562: case 984: case 985: case 986: case 987: case 988: case 989: + case 990: case 991: case 992: case 993: case 994: case 995: case 996: case 997: case 998: case 999: case 1000: case 1001: + case 1002: case 1003: case 1004: case 1005: case 1006: case 1120: case 1121: case 1122: case 1123: case 1124: case 1125: + case 1126: case 1127: case 1128: case 1129: case 1130: case 1131: case 1132: case 1133: case 1134: case 1135: case 1136: case 1137: + case 1138: case 1139: case 1140: case 1141: case 1142: case 1143: case 1144: case 1145: case 1146: case 1147: case 1148: case 1149: + case 1150: case 1151: case 1152: case 1162: case 1163: case 1164: case 1165: case 1166: case 1167: case 1168: case 1169: + case 1170: case 1171: case 1172: case 1173: case 1174: case 1175: case 1176: case 1177: case 1178: case 1179: case 1180: case 1181: + case 1182: case 1183: case 1184: case 1185: case 1186: case 1187: case 1188: case 1189: case 1190: case 1191: case 1192: case 1193: + case 1194: case 1195: case 1196: case 1197: case 1198: case 1199: case 1200: case 1201: case 1202: case 1203: case 1204: case 1205: + case 1206: case 1207: case 1208: case 1209: case 1210: case 1211: case 1212: case 1213: case 1214: case 1232: case 1233: + case 1234: case 1235: case 1236: case 1237: case 1238: case 1239: case 1240: case 1241: case 1242: case 1243: case 1244: case 1245: + case 1246: case 1247: case 1248: case 1249: case 1250: case 1251: case 1252: case 1253: case 1254: case 1255: case 1256: case 1257: + case 1258: case 1259: case 1260: case 1261: case 1262: case 1263: case 1264: case 1265: case 1266: case 1267: case 1268: + case 1280: case 1281: case 1282: case 1283: case 1284: case 1285: case 1286: case 1287: case 1288: case 1289: case 1290: case 1291: + case 1292: case 1293: case 1294: + if ( !(((utf32) % 2 == 1))) { + lc = (utf32 + 1); + } + break; + case 313: case 314: case 315: case 316: case 317: case 318: case 319: case 320: case 321: case 322: + case 323: case 324: case 325: case 326: case 327: case 377: case 378: case 379: case 380: case 381: + case 459: case 460: case 461: case 462: case 463: case 464: case 465: case 466: case 467: case 468: case 469: case 470: + case 471: case 472: case 473: case 474: case 475: case 1217: case 1218: case 1219: case 1220: case 1221: case 1222: + case 1223: case 1224: case 1225: case 1226: case 1227: case 1228: case 1229: + if (((utf32) % 2 == 1)) { + lc = (utf32 + 1); + } + break; + case 1024: case 1025: case 1026: case 1027: case 1028: case 1029: case 1030: case 1031: case 1032: case 1033: + case 1034: case 1035: case 1036: case 1037: case 1038: case 1039: + lc = (utf32 + 80); + break; + case 1329: case 1330: case 1331: case 1332: case 1333: case 1334: case 1335: case 1336: case 1337: case 1338: + case 1339: case 1340: case 1341: case 1342: case 1343: case 1344: case 1345: case 1346: case 1347: case 1348: case 1349: case 1350: + case 1351: case 1352: case 1353: case 1354: case 1355: case 1356: case 1357: case 1358: case 1359: case 1360: case 1361: case 1362: + case 1363: case 1364: case 1365: case 1366: + lc = (utf32 + 48); + break; + case 304: + lc = 105; + break; + case 376: + lc = 255; + break; + case 385: + lc = 595; + break; + case 386: + lc = 387; + break; + case 388: + lc = 389; + break; + case 390: + lc = 596; + break; + case 391: + lc = 392; + break; + case 393: + lc = 598; + break; + case 394: + lc = 599; + break; + case 395: + lc = 396; + break; + case 398: + lc = 477; + break; + case 399: + lc = 601; + break; + case 400: + lc = 603; + break; + case 401: + lc = 402; + break; + case 403: + lc = 608; + break; + case 404: + lc = 611; + break; + case 406: + lc = 617; + break; + case 407: + lc = 616; + break; + case 408: + lc = 409; + break; + case 412: + lc = 623; + break; + case 413: + lc = 626; + break; + case 415: + lc = 629; + break; + case 422: + lc = 640; + break; + case 423: + lc = 424; + break; + case 425: + lc = 643; + break; + case 428: + lc = 429; + break; + case 430: + lc = 648; + break; + case 431: + lc = 432; + break; + case 433: + lc = 650; + break; + case 434: + lc = 651; + break; + case 435: + lc = 436; + break; + case 437: + lc = 438; + break; + case 439: + lc = 658; + break; + case 440: + lc = 441; + break; + case 444: + lc = 445; + break; + case 452: + lc = 454; + break; + case 453: + lc = 454; + break; + case 455: + lc = 457; + break; + case 456: + lc = 457; + break; + case 458: + lc = 460; + break; + case 497: + lc = 499; + break; + case 498: + lc = 499; + break; + case 500: + lc = 501; + break; + case 502: + lc = 405; + break; + case 503: + lc = 447; + break; + case 544: + lc = 414; + break; + case 902: + lc = 940; + break; + case 904: + lc = 941; + break; + case 905: + lc = 942; + break; + case 906: + lc = 943; + break; + case 908: + lc = 972; + break; + case 910: + lc = 973; + break; + case 911: + lc = 974; + break; + case 1012: + lc = 952; + break; + case 1015: + lc = 1016; + break; + case 1017: + lc = 1010; + break; + case 1018: + lc = 1019; + break; + case 1272: + lc = 1273; + break; + default: + break; + } + } + return lc; +} + +/** + * Converts utf32 input to uppercase + * @param utf32 : a single character encoded in UTF32 + * @return a single uppercase character encoded in UTF32 +*/ +static picoos_uint32 base_utf32_uppercase (picoos_uint32 utf32) +{ + picoos_uint32 lc; + + lc = utf32; + if (((utf32 >= 65345) && (utf32 <= 65370))) { + lc = (utf32 - 32); + } else if (((utf32 >= 66600) && (utf32 <= 66639))) { + lc = (utf32 - 40); + } else if (((utf32 >= 7681) && (utf32 <= 9449))) { + switch (utf32) { + case 7681: case 7682: case 7683: case 7684: case 7685: case 7686: case 7687: case 7688: case 7689: case 7690: + case 7691: case 7692: case 7693: case 7694: case 7695: case 7696: case 7697: case 7698: case 7699: case 7700: case 7701: case 7702: + case 7703: case 7704: case 7705: case 7706: case 7707: case 7708: case 7709: case 7710: case 7711: case 7712: case 7713: case 7714: + case 7715: case 7716: case 7717: case 7718: case 7719: case 7720: case 7721: case 7722: case 7723: case 7724: case 7725: case 7726: + case 7727: case 7728: case 7729: case 7730: case 7731: case 7732: case 7733: case 7734: case 7735: case 7736: case 7737: case 7738: + case 7739: case 7740: case 7741: case 7742: case 7743: case 7744: case 7745: case 7746: case 7747: case 7748: case 7749: case 7750: + case 7751: case 7752: case 7753: case 7754: case 7755: case 7756: case 7757: case 7758: case 7759: case 7760: case 7761: case 7762: + case 7763: case 7764: case 7765: case 7766: case 7767: case 7768: case 7769: case 7770: case 7771: case 7772: case 7773: case 7774: + case 7775: case 7776: case 7777: case 7778: case 7779: case 7780: case 7781: case 7782: case 7783: case 7784: case 7785: case 7786: + case 7787: case 7788: case 7789: case 7790: case 7791: case 7792: case 7793: case 7794: case 7795: case 7796: case 7797: case 7798: + case 7799: case 7800: case 7801: case 7802: case 7803: case 7804: case 7805: case 7806: case 7807: case 7808: case 7809: case 7810: + case 7811: case 7812: case 7813: case 7814: case 7815: case 7816: case 7817: case 7818: case 7819: case 7820: case 7821: case 7822: + case 7823: case 7824: case 7825: case 7826: case 7827: case 7828: case 7829: case 7841: case 7842: case 7843: case 7844: + case 7845: case 7846: case 7847: case 7848: case 7849: case 7850: case 7851: case 7852: case 7853: case 7854: case 7855: case 7856: + case 7857: case 7858: case 7859: case 7860: case 7861: case 7862: case 7863: case 7864: case 7865: case 7866: case 7867: case 7868: + case 7869: case 7870: case 7871: case 7872: case 7873: case 7874: case 7875: case 7876: case 7877: case 7878: case 7879: case 7880: + case 7881: case 7882: case 7883: case 7884: case 7885: case 7886: case 7887: case 7888: case 7889: case 7890: case 7891: case 7892: + case 7893: case 7894: case 7895: case 7896: case 7897: case 7898: case 7899: case 7900: case 7901: case 7902: case 7903: case 7904: + case 7905: case 7906: case 7907: case 7908: case 7909: case 7910: case 7911: case 7912: case 7913: case 7914: case 7915: case 7916: + case 7917: case 7918: case 7919: case 7920: case 7921: case 7922: case 7923: case 7924: case 7925: case 7926: case 7927: case 7928: + case 7929: + if (((utf32) % 2 == 1)) { + lc = (utf32 - 1); + } + break; + case 7936: case 7937: case 7938: case 7939: case 7940: case 7941: case 7942: case 7943: case 7952: + case 7953: case 7954: case 7955: case 7956: case 7957: case 7968: case 7969: case 7970: case 7971: case 7972: case 7973: + case 7974: case 7975: case 7984: case 7985: case 7986: case 7987: case 7988: case 7989: case 7990: case 7991: + case 8000: case 8001: case 8002: case 8003: case 8004: case 8005: case 8032: case 8033: case 8034: case 8035: case 8036: + case 8037: case 8038: case 8039: case 8064: case 8065: case 8066: case 8067: case 8068: case 8069: case 8070: case 8071: + case 8080: case 8081: case 8082: case 8083: case 8084: case 8085: case 8086: case 8087: case 8096: case 8097: + case 8098: case 8099: case 8100: case 8101: case 8102: case 8103: + lc = (utf32 + 8); + break; + case 8017: case 8018: case 8019: case 8020: case 8021: case 8022: case 8023: + if (((utf32) % 2 == 1)) { + lc = (utf32 + 8); + } + break; + case 8560: case 8561: case 8562: case 8563: case 8564: case 8565: case 8566: case 8567: case 8568: case 8569: + case 8570: case 8571: case 8572: case 8573: case 8574: case 8575: + lc = (utf32 - 16); + break; + case 9424: case 9425: case 9426: case 9427: case 9428: case 9429: case 9430: case 9431: case 9432: case 9433: + case 9434: case 9435: case 9436: case 9437: case 9438: case 9439: case 9440: case 9441: case 9442: case 9443: case 9444: case 9445: + case 9446: case 9447: case 9448: case 9449: + lc = (utf32 - 26); + break; + case 7835: + lc = 7776; + break; + case 8048: + lc = 8122; + break; + case 8049: + lc = 8123; + break; + case 8050: + lc = 8136; + break; + case 8051: + lc = 8137; + break; + case 8052: + lc = 8138; + break; + case 8053: + lc = 8139; + break; + case 8054: + lc = 8154; + break; + case 8055: + lc = 8155; + break; + case 8056: + lc = 8184; + break; + case 8057: + lc = 8185; + break; + case 8058: + lc = 8170; + break; + case 8059: + lc = 8171; + break; + case 8060: + lc = 8186; + break; + case 8061: + lc = 8187; + break; + case 8112: + lc = 8120; + break; + case 8113: + lc = 8121; + break; + case 8115: + lc = 8124; + break; + case 8126: + lc = 921; + break; + case 8131: + lc = 8140; + break; + case 8144: + lc = 8152; + break; + case 8145: + lc = 8153; + break; + case 8160: + lc = 8168; + break; + case 8161: + lc = 8169; + break; + case 8165: + lc = 8172; + break; + case 8179: + lc = 8188; + break; + default: + break; + } + } else { + switch (utf32) { + case 97: case 98: case 99: case 100: case 101: case 102: case 103: case 104: case 105: case 106: + case 107: case 108: case 109: case 110: case 111: case 112: case 113: case 114: case 115: case 116: case 117: case 118: + case 119: case 120: case 121: case 122: case 224: case 225: case 226: case 227: case 228: case 229: case 230: + case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: + case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: + case 945: case 946: case 947: case 948: case 949: case 950: case 951: case 952: case 953: case 954: case 955: + case 956: case 957: case 958: case 959: case 960: case 961: case 963: case 964: case 965: case 966: case 967: + case 968: case 969: case 970: case 971: case 1072: case 1073: case 1074: case 1075: case 1076: case 1077: case 1078: + case 1079: case 1080: case 1081: case 1082: case 1083: case 1084: case 1085: case 1086: case 1087: case 1088: case 1089: case 1090: + case 1091: case 1092: case 1093: case 1094: case 1095: case 1096: case 1097: case 1098: case 1099: case 1100: case 1101: case 1102: + case 1103: + if ((utf32 != 247)) { + lc = (utf32 - 32); + } + break; + case 257: case 258: case 259: case 260: case 261: case 262: case 263: case 264: case 265: case 266: + case 267: case 268: case 269: case 270: case 271: case 272: case 273: case 274: case 275: case 276: case 277: case 278: + case 279: case 280: case 281: case 282: case 283: case 284: case 285: case 286: case 287: case 288: case 289: case 290: + case 291: case 292: case 293: case 294: case 295: case 296: case 297: case 298: case 299: case 300: case 301: case 302: + case 303: case 304: case 306: case 307: case 308: case 309: case 310: case 311: case 331: case 332: + case 333: case 334: case 335: case 336: case 337: case 338: case 339: case 340: case 341: case 342: case 343: case 344: + case 345: case 346: case 347: case 348: case 349: case 350: case 351: case 352: case 353: case 354: case 355: case 356: + case 357: case 358: case 359: case 360: case 361: case 362: case 363: case 364: case 365: case 366: case 367: case 368: + case 369: case 370: case 371: case 372: case 373: case 374: case 375: case 417: case 418: case 419: case 420: + case 421: case 481: case 482: case 483: case 484: case 485: case 486: case 487: case 488: case 489: case 490: + case 491: case 492: case 493: case 494: case 495: case 507: case 508: case 509: case 510: case 511: + case 513: case 514: case 515: case 516: case 517: case 518: case 519: case 520: case 521: case 522: case 523: case 524: + case 525: case 526: case 527: case 528: case 529: case 530: case 531: case 532: case 533: case 534: case 535: case 536: + case 537: case 538: case 539: case 540: case 541: case 542: case 543: case 544: case 546: case 547: case 548: + case 549: case 550: case 551: case 552: case 553: case 554: case 555: case 556: case 557: case 558: case 559: case 560: + case 561: case 562: case 563: case 985: case 986: case 987: case 988: case 989: case 990: case 991: case 992: + case 993: case 994: case 995: case 996: case 997: case 998: case 999: case 1000: case 1001: case 1002: case 1003: case 1004: + case 1005: case 1006: case 1007: case 1121: case 1122: case 1123: case 1124: case 1125: case 1126: case 1127: case 1128: + case 1129: case 1130: case 1131: case 1132: case 1133: case 1134: case 1135: case 1136: case 1137: case 1138: case 1139: case 1140: + case 1141: case 1142: case 1143: case 1144: case 1145: case 1146: case 1147: case 1148: case 1149: case 1150: case 1151: case 1152: + case 1153: case 1163: case 1164: case 1165: case 1166: case 1167: case 1168: case 1169: case 1170: case 1171: case 1172: + case 1173: case 1174: case 1175: case 1176: case 1177: case 1178: case 1179: case 1180: case 1181: case 1182: case 1183: case 1184: + case 1185: case 1186: case 1187: case 1188: case 1189: case 1190: case 1191: case 1192: case 1193: case 1194: case 1195: case 1196: + case 1197: case 1198: case 1199: case 1200: case 1201: case 1202: case 1203: case 1204: case 1205: case 1206: case 1207: case 1208: + case 1209: case 1210: case 1211: case 1212: case 1213: case 1214: case 1215: case 1233: case 1234: case 1235: case 1236: + case 1237: case 1238: case 1239: case 1240: case 1241: case 1242: case 1243: case 1244: case 1245: case 1246: case 1247: case 1248: + case 1249: case 1250: case 1251: case 1252: case 1253: case 1254: case 1255: case 1256: case 1257: case 1258: case 1259: case 1260: + case 1261: case 1262: case 1263: case 1264: case 1265: case 1266: case 1267: case 1268: case 1269: case 1281: case 1282: + case 1283: case 1284: case 1285: case 1286: case 1287: case 1288: case 1289: case 1290: case 1291: case 1292: case 1293: case 1294: + case 1295: + if (((utf32) % 2 == 1)) { + lc = (utf32 - 1); + } + break; + case 314: case 315: case 316: case 317: case 318: case 319: case 320: case 321: case 322: case 323: + case 324: case 325: case 326: case 327: case 328: case 378: case 379: case 380: case 381: case 382: + case 464: case 465: case 466: case 467: case 468: case 469: case 470: case 471: case 472: case 473: case 474: case 475: + case 476: case 1218: case 1219: case 1220: case 1221: case 1222: case 1223: case 1224: case 1225: case 1226: case 1227: + case 1228: case 1229: case 1230: + if ( !(((utf32) % 2 == 1))) { + lc = (utf32 - 1); + } + break; + case 1104: case 1105: case 1106: case 1107: case 1108: case 1109: case 1110: case 1111: case 1112: case 1113: + case 1114: case 1115: case 1116: case 1117: case 1118: case 1119: + lc = (utf32 - 80); + break; + case 1377: case 1378: case 1379: case 1380: case 1381: case 1382: case 1383: case 1384: case 1385: case 1386: + case 1387: case 1388: case 1389: case 1390: case 1391: case 1392: case 1393: case 1394: case 1395: case 1396: case 1397: case 1398: + case 1399: case 1400: case 1401: case 1402: case 1403: case 1404: case 1405: case 1406: case 1407: case 1408: case 1409: case 1410: + case 1411: case 1412: case 1413: case 1414: + lc = (utf32 - 48); + break; + case 181: + lc = 924; + break; + case 255: + lc = 376; + break; + case 305: + lc = 73; + break; + case 383: + lc = 83; + break; + case 387: + lc = 386; + break; + case 389: + lc = 388; + break; + case 392: + lc = 391; + break; + case 396: + lc = 395; + break; + case 402: + lc = 401; + break; + case 405: + lc = 502; + break; + case 409: + lc = 408; + break; + case 414: + lc = 544; + break; + case 424: + lc = 423; + break; + case 429: + lc = 428; + break; + case 432: + lc = 431; + break; + case 436: + lc = 435; + break; + case 438: + lc = 437; + break; + case 441: + lc = 440; + break; + case 445: + lc = 444; + break; + case 447: + lc = 503; + break; + case 453: + lc = 452; + break; + case 454: + lc = 452; + break; + case 456: + lc = 455; + break; + case 457: + lc = 455; + break; + case 459: + lc = 458; + break; + case 460: + lc = 458; + break; + case 462: + lc = 461; + break; + case 477: + lc = 398; + break; + case 479: + lc = 478; + break; + case 498: + lc = 497; + break; + case 499: + lc = 497; + break; + case 501: + lc = 500; + break; + case 505: + lc = 504; + break; + case 595: + lc = 385; + break; + case 596: + lc = 390; + break; + case 598: + lc = 393; + break; + case 599: + lc = 394; + break; + case 601: + lc = 399; + break; + case 603: + lc = 400; + break; + case 608: + lc = 403; + break; + case 611: + lc = 404; + break; + case 616: + lc = 407; + break; + case 617: + lc = 406; + break; + case 623: + lc = 412; + break; + case 626: + lc = 413; + break; + case 629: + lc = 415; + break; + case 640: + lc = 422; + break; + case 643: + lc = 425; + break; + case 648: + lc = 430; + break; + case 650: + lc = 433; + break; + case 651: + lc = 434; + break; + case 658: + lc = 439; + break; + case 837: + lc = 921; + break; + case 940: + lc = 902; + break; + case 941: + lc = 904; + break; + case 942: + lc = 905; + break; + case 943: + lc = 906; + break; + case 962: + lc = 931; + break; + case 972: + lc = 908; + break; + case 973: + lc = 910; + break; + case 974: + lc = 911; + break; + case 976: + lc = 914; + break; + case 977: + lc = 920; + break; + case 981: + lc = 934; + break; + case 982: + lc = 928; + break; + case 1008: + lc = 922; + break; + case 1009: + lc = 929; + break; + case 1010: + lc = 1017; + break; + case 1013: + lc = 917; + break; + case 1016: + lc = 1015; + break; + case 1019: + lc = 1018; + break; + case 1273: + lc = 1272; + break; + default: + break; + } + } + return lc; +} + +/** + * Gets the UTF8 character 'utf8char' from the UTF8 string 'utf8str' from + * position 'pos' + * @param utf8str: utf8 string + * @param pos: position from where the utf8 character is copied + * (also output set as position of the next utf8 character in the utf8 string) + * @param utf8char: zero terminated utf8 character containing 1 to 4 bytes (output) +*/ +static void picobase_get_utf8char (picoos_uint8 utf8[], picoos_int32 * pos, picobase_utf8char utf8char) +{ + + int i; + int l; + + utf8char[0] = 0; + l = picobase_det_utf8_length(utf8[*pos]); + i = 0; + while ((((i < l) && (i < PICOBASE_UTF8_MAXLEN)) && (utf8[*pos] != 0))) { + utf8char[i] = utf8[*pos]; + (*pos)++; + i++; + } + utf8char[i] = 0; +} + + +picoos_uint8 picobase_get_next_utf8char(const picoos_uint8 *utf8s, + const picoos_uint32 utf8slenmax, + picoos_uint32 *pos, + picobase_utf8char utf8char) { + picoos_uint8 i; + picoos_uint8 len; + picoos_uint32 poscnt; + + utf8char[0] = 0; + len = picobase_det_utf8_length(utf8s[*pos]); + if ((((*pos) + len) > utf8slenmax) || + (len > PICOBASE_UTF8_MAXLEN)) { + return FALSE; + } + + poscnt = *pos; + i = 0; + while ((i < len) && (utf8s[poscnt] != 0)) { + utf8char[i] = utf8s[poscnt]; + poscnt++; + i++; + } + utf8char[i] = 0; + if ((i < len) && (utf8s[poscnt] == 0)) { + return FALSE; + } + *pos = poscnt; + return TRUE; +} + +picoos_uint8 picobase_get_next_utf8charpos(const picoos_uint8 *utf8s, + const picoos_uint32 utf8slenmax, + picoos_uint32 *pos) { + picoos_uint8 i; + picoos_uint8 len; + picoos_uint32 poscnt; + + len = picobase_det_utf8_length(utf8s[*pos]); + if ((((*pos) + len) > utf8slenmax) || + (len > PICOBASE_UTF8_MAXLEN)){ + return FALSE; + } + + poscnt = *pos; + i = 0; + while ((i < len) && (utf8s[poscnt] != 0)) { + poscnt++; + i++; + } + if ((i < len) && (utf8s[poscnt] == 0)) { + return FALSE; + } + *pos = poscnt; + return TRUE; +} + +picoos_uint8 picobase_get_prev_utf8char(const picoos_uint8 *utf8s, + const picoos_uint32 utf8slenmin, + picoos_uint32 *pos, + picobase_utf8char utf8char) { + picoos_uint8 i, j; + picoos_uint8 len; + picoos_uint32 poscnt; + + utf8char[0] = 0; + if ((*pos) == 0) { + return FALSE; + } + poscnt = (*pos) - 1; + i = 1; + while ((i <= PICOBASE_UTF8_MAXLEN) && (poscnt >= utf8slenmin) && + (utf8s[poscnt] != 0)) { + len = picobase_det_utf8_length(utf8s[poscnt]); + if (len == i) { + for (j = 0; j < len; j++) { + utf8char[j] = utf8s[poscnt + j]; + } + utf8char[j] = 0; + *pos = poscnt; + return TRUE; + } + i++; + poscnt--; + } + return FALSE; +} + +picoos_uint8 picobase_get_prev_utf8charpos(const picoos_uint8 *utf8s, + const picoos_uint32 utf8slenmin, + picoos_uint32 *pos) { + picoos_uint8 i; + picoos_uint8 len; + picoos_uint32 poscnt; + + if ((*pos) == 0) { + return FALSE; + } + poscnt = (*pos) - 1; + i = 1; + while ((i <= PICOBASE_UTF8_MAXLEN) && (poscnt >= utf8slenmin) && + (utf8s[poscnt] != 0)) { + len = picobase_det_utf8_length(utf8s[poscnt]); + if (len == i) { + *pos = poscnt; + return TRUE; + } + i++; + poscnt--; + } + return FALSE; +} + +/** + * Converts utf8 input to utf32 + * @param utf8[] : character encoded in utf8 + * @param done : boolean indicating the completion of the operation (FALSE: conversion not done) + * @return a single character encoded in UTF32 +*/ +static picobase_utf32 picobase_utf8_to_utf32 (picoos_uint8 utf8[], picoos_uint8 * done) +{ + (*done) = TRUE; + if ((utf8[0] < (picoos_uint8)'\200')) { + return utf8[0]; + } else if ((utf8[0] >= (picoos_uint8)'\370')) { + return 0; + } else if ((utf8[0] >= (picoos_uint8)'\360')) { + return ((((262144 * (utf8[0] % 8)) + (4096 * (utf8[1] % 64))) + (64 * (utf8[2] % 64))) + (utf8[3] % 64)); + } else if ((utf8[0] >= (picoos_uint8)'\340')) { + return (((4096 * (utf8[0] % 16)) + (64 * (utf8[1] % 64))) + (utf8[2] % 64)); + } else if ((utf8[(0)] >= (picoos_uint8)'\300')) { + return ((64 * (utf8[0] % 32)) + (utf8[1] % 64)); + } else { + (*done) = FALSE; + return 0; + } +} + +static picoos_int32 picobase_utf32_to_utf8 (picobase_utf32 utf32, picobase_utf8 utf8[], picoos_int32 utf8MaxLen, picoos_uint8 * done) +{ + picoos_int32 len; + + (*done) = TRUE; + if (utf8MaxLen >= 4) { + if (utf32 < 128) { + len = 1; + utf8[0] = utf32; + } else if (utf32 < 2048) { + len = 2; + utf8[1] = (128 + (utf32 % 64)); + utf32 = (utf32 / 64); + utf8[0] = (192 + (utf32 % 32)); + } else if (utf32 < 65536) { + len = 3; + utf8[2] = (128 + (utf32 % 64)); + utf32 = (utf32 / 64); + utf8[1] = (128 + (utf32 % 64)); + utf32 = (utf32 / 64); + utf8[0] = (224 + utf32); + } else if (utf32 < 1048576) { + len = 4; + utf8[3] = (128 + (utf32 % 64)); + utf32 = (utf32 / 64); + utf8[2] = (128 + (utf32 % 64)); + utf32 = (utf32 / 64); + utf8[1] = (128 + (utf32 % 64)); + utf32 = (utf32 / 64); + utf8[0] = (240 + utf32); + } else { + (*done) = FALSE; + return 0; + } + if (len <= (utf8MaxLen-1)) { + utf8[len] = 0; + } + return len; + } else { + (*done) = FALSE; + return 0; + } +} + + +extern picoos_int32 picobase_lowercase_utf8_str (picoos_uchar utf8str[], picoos_char lowercase[], int lowercaseMaxLen, picoos_uint8 * done) +{ + picobase_utf8char utf8char; + picoos_int32 i; + picoos_int32 j; + picoos_int32 k; + picoos_int32 l; + picobase_utf32 utf32; + picoos_uint8 done1; + + k = 0; + i = 0; + (*done) = TRUE; + while (utf8str[i] != 0) { + picobase_get_utf8char(utf8str,& i,utf8char); + utf32 = picobase_utf8_to_utf32(utf8char, & done1); + utf32 = base_utf32_lowercase(utf32); + l = picobase_utf32_to_utf8(utf32, utf8char, PICOBASE_UTF8_MAXLEN, & done1); + j = 0; + while ((j < l) && (k < (lowercaseMaxLen-1))) { + lowercase[k] = utf8char[j]; + k++; + j++; + } + *done = *done && (j == l); + } + lowercase[k] = 0; + return k; +} + + +extern picoos_int32 picobase_uppercase_utf8_str (picoos_uchar utf8str[], picoos_char uppercase[], int uppercaseMaxLen, picoos_uint8 * done) +{ + picobase_utf8char utf8char; + picoos_int32 i; + picoos_int32 j; + picoos_int32 k; + picoos_int32 l; + picobase_utf32 utf32; + picoos_uint8 done1; + + k = 0; + i = 0; + (*done) = TRUE; + while (utf8str[i] != 0) { + picobase_get_utf8char(utf8str,& i,utf8char); + utf32 = picobase_utf8_to_utf32(utf8char, & done1); + utf32 = base_utf32_uppercase(utf32); + l = picobase_utf32_to_utf8(utf32, utf8char, PICOBASE_UTF8_MAXLEN, & done1); + j = 0; + while ((j < l) && (k < (uppercaseMaxLen-1))) { + uppercase[k] = utf8char[j]; + k++; + j++; + } + *done = *done && (j == l); + } + uppercase[k] = 0; + return k; +} + + +extern picoos_bool picobase_is_utf8_uppercase (picoos_uchar utf8str[], picoos_int32 utf8strmaxlen) +{ + picobase_utf8char utf8char; + picoos_int32 i; + picoos_uint32 utf32; + picoos_bool done; + picoos_bool isUpperCase; + + isUpperCase = TRUE; + i = 0; + while (isUpperCase && (i <= utf8strmaxlen-1) && (utf8str[i] != 0)) { + picobase_get_utf8char(utf8str,& i,utf8char); + utf32 = picobase_utf8_to_utf32(utf8char,& done); + isUpperCase = isUpperCase && (utf32 == base_utf32_uppercase(utf32)); + } + return isUpperCase; +} + + +extern picoos_bool picobase_is_utf8_lowercase (picoos_uchar utf8str[], picoos_int32 utf8strmaxlen) +{ + picobase_utf8char utf8char; + picoos_int32 i; + picoos_uint32 utf32; + picoos_bool done; + picoos_bool isLowerCase; + + isLowerCase = TRUE; + i = 0; + while (isLowerCase && (i <= utf8strmaxlen-1) && (utf8str[i] != 0)) { + picobase_get_utf8char(utf8str,& i,utf8char); + utf32 = picobase_utf8_to_utf32(utf8char,& done); + isLowerCase = isLowerCase && (utf32 == base_utf32_lowercase(utf32)); + } + return isLowerCase; +} + + +#ifdef __cplusplus +} +#endif + + + +/* end */ diff --git a/pico/lib/picobase.h b/pico/lib/picobase.h new file mode 100644 index 0000000..1c384e1 --- /dev/null +++ b/pico/lib/picobase.h @@ -0,0 +1,171 @@ +/* + * 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 picobase.h + * + * base functionality + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#ifndef PICOBASE_H_ +#define PICOBASE_H_ + +#include "picoos.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/* maximum number of bytes of an UTF8 character */ +#define PICOBASE_UTF8_MAXLEN 4 + +typedef picoos_uint8 picobase_utf8char[PICOBASE_UTF8_MAXLEN+1]; /* always zero terminated */ +typedef picoos_uint8 picobase_utf8; +typedef picoos_uint16 picobase_utf16; +typedef picoos_uint32 picobase_utf32; + +/* ***************************************************************/ +/* Unicode UTF8 functions */ +/* ***************************************************************/ + +/** + * Determines the number of UTF8 characters contained in + * the UTF8 string 'utf8str' of maximum length maxlen (in bytes) + * @param utf8str : a string encoded in UTF8 + * @param maxlen : max length (in bytes) accessible in utf8str + * @return >=0 : length of the UTF8 string in number of UTF8 characters + * up to the first '\0' or maxlen + * @return <0 : not starting with a valid UTF8 character + * @remarks strict implementation, not allowing invalid utf8 +*/ +picoos_int32 picobase_utf8_length(const picoos_uint8 *utf8str, + const picoos_uint16 maxlen); + + +/** + * Determines the number of bytes an UTF8 character used based + * on the first byte of the UTF8 character + * @param firstchar: the first (and maybe only) byte of an UTF8 character + * @return positive value in {1,4} : number of bytes of the UTF8 character + * @return 0 :if not a valid UTF8 character start + * @remarks strict implementation, not allowing invalid utf8 +*/ +/* picoos_uint8 picobase_det_utf8_length(const picoos_uint8 firstchar); */ + +#define picobase_det_utf8_length(x) ( ((x)<(picoos_uint8)'\200')?1:(((x)>=(picoos_uint8)'\370')?0:(((x)>=(picoos_uint8)'\360')?4:(((x)>=(picoos_uint8)'\340')?3:(((x)>=(picoos_uint8)'\300')?2:0)))) ) + +/** + * Converts the content of 'utf8str' to lowercase and stores it on 'lowercase' + * on the first byte of the UTF8 character + * @param utf8str : utf8 string + * @param lowercaseMaxLen : maximal number of bytes available in 'lowercase' + * @param lowercase : string converted to lowercase (output) + * @param done : flag to report success/failure of the operation (output) + * @return TRUE if successful, FALSE otherwise +*/ +picoos_int32 picobase_lowercase_utf8_str (picoos_uchar utf8str[], picoos_char lowercase[], picoos_int32 lowercaseMaxLen, picoos_uint8 * done); + +/** + * Converts the content of 'utf8str' to upperrcase and stores it on 'uppercase' + * @param utf8str : utf8 string + * @param uppercase : string converted to uppercase (output) + * @param uppercaseMaxLen : maximal number of bytes available in 'uppercase' + * @param done : flag to report success/failure of the operation (output) + * @return TRUE if successful, FALSE otherwise +*/ +picoos_int32 picobase_uppercase_utf8_str (picoos_uchar utf8str[], picoos_char uppercase[], int uppercaseMaxLen, picoos_uint8 * done); + +/** + * Gets next UTF8 character 'utf8char' from the UTF8 string + * 'utf8s' starting at position 'pos' + * @param utf8s : UTF8 string + * @param utf8slenmax : max length accessible in utf8s + * @param pos : position from where the UTF8 character is checked and copied + * (set also as output to the position directly following the UTF8 char) + * @param utf8char : zero terminated UTF8 character containing 1 to 4 bytes (output) + * @return TRUE if okay + * @return FALSE if there is no valid UTF8 char or no more UTF8 char available within utf8len +*/ +picoos_uint8 picobase_get_next_utf8char(const picoos_uint8 *utf8s, + const picoos_uint32 utf8slenmax, + picoos_uint32 *pos, + picobase_utf8char utf8char); + +/** + * Same as picobase_get_next_utf8char + * without copying the char to utf8char +*/ +picoos_uint8 picobase_get_next_utf8charpos(const picoos_uint8 *utf8s, + const picoos_uint32 utf8slenmax, + picoos_uint32 *pos); + +/** + * Gets previous UTF8 character 'utf8char' from the UTF8 string + * 'utf8s' starting the backward search at position 'pos-1' + * @param utf8s : UTF8 string + * @param utf8slenmin : min length accessible in utf8s + * @param pos : the search for the prev UTF8 char starts at [pos-1] + * (set also as output to the start position of the prev UTF8 character) + * @param utf8char : zero terminated UTF8 character containing 1 to 4 bytes (output) + * @return TRUE if okay + * @return FALSE if there is no valid UTF8 char preceeding pos or no more UTF8 char available within utf8len +*/ +picoos_uint8 picobase_get_prev_utf8char(const picoos_uint8 *utf8s, + const picoos_uint32 utf8slenmin, + picoos_uint32 *pos, + picobase_utf8char utf8char); + +/** + * Same as picobase_get_prev_utf8char + * without copying the char to utf8char +*/ +picoos_uint8 picobase_get_prev_utf8charpos(const picoos_uint8 *utf8s, + const picoos_uint32 utf8slenmin, + picoos_uint32 *pos); + + +/** + * returns TRUE if the input string is UTF8 and uppercase + * @param str : UTF8 string + * @param strmaxlen : max length for the input string + * @return TRUE if string is UTF8 and uppercase + * @return FALSE otherwise +*/ +extern picoos_bool picobase_is_utf8_uppercase (picoos_uchar str[], picoos_int32 strmaxlen); + +/** + * returns TRUE if the input string is UTF8 and lowercase + * @param str : UTF8 string + * @param strmaxlen : max length for the input string + * @return TRUE if string is UTF8 and lowercase + * @return FALSE otherwise +*/ +extern picoos_bool picobase_is_utf8_lowercase (picoos_uchar str[], picoos_int32 strmaxlen); + +#ifdef __cplusplus +} +#endif + +#endif /*PICOBASE_H_*/ diff --git a/pico/lib/picocep.c b/pico/lib/picocep.c new file mode 100644 index 0000000..2510c13 --- /dev/null +++ b/pico/lib/picocep.c @@ -0,0 +1,1965 @@ +/* + * 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 picocep.c + * + * Phonetic to Acoustic Mapping PU - Implementation + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +/** + * @addtogroup picocep + * Pico Cepstral Smoothing \n + * + itemtype, iteminfo1, iteminfo2, content -> TYPE(INFO1,INFO2)content + in the following + + items input + + processed: + + - PHONE(PHONID,StatesPerPhone)[FramesPerState|f0Index|mgcIndex]{StatesPerPhone} + + (StatesPerPhone is a constant (5) for the time being. The content size is therfore allways 34) + + unprocessed: + - all other item types are forwarded through the PU without modification + + items output + + FRAME(PHONID,F0 [?])ceps{25} + + each PHONE produces at least StatesPerPhone FRAME (if each state has FramesPerState == 1), but usually more. + + minimal input size (before processing starts) + + other limitations + + */ +#include "picodefs.h" +#include "picoos.h" +#include "picodbg.h" +#include "picodata.h" +#include "picokpdf.h" +#include "picodsp.h" +#include "picocep.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +#define PICOCEP_MAXWINLEN 10000 /* maximum number of frames that can be smoothed, i.e. maximum sentence length */ +#define PICOCEP_MSGSTR_SIZE 32 +#define PICOCEP_IN_BUFF_SIZE PICODATA_BUFSIZE_DEFAULT + +#define PICOCEP_OUT_DATA_FORMAT PICODATA_ITEMINFO1_FRAME_PAR_DATA_FORMAT_FIXED /* we output coefficients as fixed point values */ + +#define PICOCEP_STEPSTATE_COLLECT 0 +#define PICOCEP_STEPSTATE_PROCESS_PARSE 1 +#define PICOCEP_STEPSTATE_PROCESS_SMOOTH 2 +#define PICOCEP_STEPSTATE_PROCESS_FRAME 3 +#define PICOCEP_STEPSTATE_FEED 4 + +#define PICOCEP_LFZINVPOW 31 /* cannot be higher than 31 because 1< 2^16 */ + picoos_uint8 * outVoiced; + picoos_uint16 outVoicedReadPos, outVoicedWritePos; + + /*---------------------- LINGWARE related data -------------------*/ + /* pdflfz knowledge base */ + picokpdf_PdfMUL pdflfz, pdfmgc; + +} cep_subobj_t; + +/** + * picocep_highestBit + * @brief find the highest non-zero bit in input x + * @remarks this may be implemented by comparing x to powers of 2 + * or instead of calling this function perform multiplication + * and consult overflow register if available on target + * @note implemented as a series of macros + */ + +#define picocep_highestBitNZ(x) (x>=POW17?(x>=POW25?(x>=POW29?(x>=POW31?31:(x>=POW30?30:29)):(x>=POW27?(x>=POW28?28:27):(x>=POW26?26:25))):(x>=POW21?(x>=POW23?(x>=POW24?24:23):(x>=POW22?22:21)):(x>=POW19?(x>=POW20?20:19):(x>=POW18?18:17)))):(x>=POW9?(x>=POW13?(x>=POW15?(x>=POW16?16:15):(x>=POW14?14:13)):(x>=POW11?(x>=POW12?12:11):(x>=POW10?10:9))):(x>=POW5?(x>=POW7?(x>=POW8?8:7):(x>=POW6?6:5)):(x>=POW3?(x>=POW4?4:3):(x>=POW2?2:1))))) +#define picocep_highestBitU(x) (x==0?0:picocep_highestBitNZ(x)) +#define picocep_highestBitS(x,zz) (x==0?0:(x<0?((zz)=(-x),picocep_highestBitNZ(zz)):picocep_highestBitNZ(x))) + +/* ------------------------------------------------------------------------------ + Internal function definitions + ---------------------------------------------------------------------------------*/ + +static void initSmoothing(cep_subobj_t * cep); + +static picoos_int32 getFromPdf(picokpdf_PdfMUL pdf, picoos_uint32 vecstart, + picoos_uint8 cepnum, picocep_WantMeanOrIvar_t wantMeanOrIvar, + picocep_WantStaticOrDelta_t wantStaticOrDeltax); + +static void invMatrix(cep_subobj_t * cep, picoos_uint16 N, + picoos_int16 *smoothcep, picoos_uint8 cepnum, + picokpdf_PdfMUL pdf, picoos_uint8 invpow, picoos_uint8 invDoubleDec); + +static picoos_uint8 makeWUWandWUm(cep_subobj_t * cep, picokpdf_PdfMUL pdf, + picoos_uint16 *indices, picoos_uint16 b, picoos_uint16 N, + picoos_uint8 cepnum); + +static void getDirect(picokpdf_PdfMUL pdf, picoos_uint16 *indices, + picoos_uint16 activeEndPos, + picoos_uint8 cepnum, picoos_int16 *smoothcep); + +static void getVoiced(picokpdf_PdfMUL pdf, picoos_uint16 *indices, + picoos_uint16 activeEndPos, + picoos_uint8 *smoothcep); + +static picoos_uint16 get_pi_uint16(picoos_uint8 * buf, picoos_uint16 *pos); + +static void treat_phone(cep_subobj_t * cep, picodata_itemhead_t * ihead); + +static picoos_uint8 forwardingItem(picodata_itemhead_t * ihead); + +static picodata_step_result_t cepStep(register picodata_ProcessingUnit this, + picoos_int16 mode, picoos_uint16 * numBytesOutput); + +/* -------------------------------------------- + * generic PU management + * -------------------------------------------- + */ + +/** + * initialization of a cep PU (processing unit) + * @param this : handle to a cep PU struct + * @return PICO_OK : init succeded + * @return PICO_ERR_OTHER : init failed + * @callgraph + * @callergraph + */ +static pico_status_t cepInitialize(register picodata_ProcessingUnit this) +{ + /*pico_status_t nRes;*/ + cep_subobj_t * cep; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + cep = (cep_subobj_t *) this->subObj; + /* inBuf */ + cep->inBufSize = PICODATA_BUFSIZE_CEP; + cep->inReadPos = 0; + cep->inWritePos = 0; + /* headx and cbuf */ + cep->headxBottom = cep->headxWritePos = 0; + cep->cbufBufSize = PICOCEP_MAXSIZE_CBUF; + cep->cbufWritePos = 0; + /* outBuf */ + cep->outBufSize = PICODATA_MAX_ITEMSIZE; + cep->outReadPos = 0; + cep->outWritePos = 0; + /* indices* */ + cep->indexReadPos = 0; + cep->indexWritePos = 0; + /* outCep, outF0, outVoiced */ + cep->outXCepReadPos = 0; + cep->outXCepWritePos = 0; + cep->outVoicedReadPos = 0; + cep->outVoicedWritePos = 0; + cep->outF0ReadPos = 0; + cep->outF0WritePos = 0; + + cep->needMoreInput = 0; + cep->inIgnoreState = 0; + cep->sentenceEnd = FALSE; + cep->procState = PICOCEP_STEPSTATE_COLLECT; + + cep->nNumFrames = 0; + + /*----------------------------------------------------------------- + * MANAGE Item I/O control management + ------------------------------------------------------------------*/ + cep->activeEndPos = PICOCEP_MAXWINLEN; + + /* kb pdflfz */ + cep->pdflfz = picokpdf_getPdfMUL( + this->voice->kbArray[PICOKNOW_KBID_PDF_LFZ]); + + /* kb pdfmgc */ + cep->pdfmgc = picokpdf_getPdfMUL( + this->voice->kbArray[PICOKNOW_KBID_PDF_MGC]); + + /* kb tab phones */ + /* cep->phones = + picoktab_getPhones(this->voice->kbArray[PICOKNOW_KBID_TAB_PHONES]); */ + + /*---------------------- other working variables ---------------------------*/ + /* define the (constant) FRAME_PAR item header */ + cep->framehead.type = PICODATA_ITEM_FRAME_PAR; + cep->framehead.info1 = PICOCEP_OUT_DATA_FORMAT; + cep->framehead.info2 = cep->pdfmgc->ceporder; + cep->framehead.len = sizeof(picoos_uint16) + (cep->framehead.info2 + 4) + * sizeof(picoos_uint16); + + /* constants used in makeWUWandWUm */ + initSmoothing(cep); + + cep->scmeanpowLFZ = cep->pdflfz->bigpow - cep->pdflfz->meanpow; + cep->scmeanpowMGC = cep->pdfmgc->bigpow - cep->pdfmgc->meanpow; + + cep->scmeanLFZ = (1 << (picoos_uint32) cep->scmeanpowLFZ); + + cep->scmeanMGC = (1 << (picoos_uint32) cep->scmeanpowMGC); + + return PICO_OK; +}/*cepInitialize*/ + +/** + * termination of a cep PU (processing unit) + * @param this : handle to a cep PU struct + * @return PICO_OK : termination succeded + * @return PICO_ERR_OTHER : termination failed + * @callgraph + * @callergraph + */ +static pico_status_t cepTerminate(register picodata_ProcessingUnit this) +{ + return PICO_OK; +} + +/** + * deallocation of a cep PU internal sub object + * @param this : handle to a cep PU struct + * @param mm : handle of the engine memory manager + * @return PICO_OK : deallocation succeded + * @return PICO_ERR_OTHER : deallocation failed + * @callgraph + * @callergraph + */ +static pico_status_t cepSubObjDeallocate(register picodata_ProcessingUnit this, + picoos_MemoryManager mm) +{ + + mm = mm; /* avoid warning "var not used in this function"*/ +#if defined(PICO_DEVEL_MODE) + printf("number of long mult is %d, number of short mult is %i\n",numlongmult,numshortmult); +#else + PICODBG_INFO_MSG(("number of long mult is %d, number of short mult is %i\n",numlongmult,numshortmult)); +#endif + if (NULL != this) { + cep_subobj_t * cep = (cep_subobj_t *) this->subObj; + picoos_deallocate(this->common->mm, (void *) &cep->outXCep); + picoos_deallocate(this->common->mm, (void *) &cep->outVoiced); + picoos_deallocate(this->common->mm, (void *) &cep->outF0); + picoos_deallocate(this->common->mm, (void *) &this->subObj); + } + return PICO_OK; +} + +/** + * creates a new cep PU (processing unit) + * @param mm : engine memory manager object pointer + * @param common : engine common object pointer + * @param cbIn : PU input buffer + * @param cbOut : PU output buffer + * @param voice : the voice descriptor object + * @return a valid PU handle if creation succeded + * @return NULL : creation failed + * @callgraph + * @callergraph + */ +picodata_ProcessingUnit picocep_newCepUnit(picoos_MemoryManager mm, + picoos_Common common, picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, picorsrc_Voice voice) +{ + picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, + cbOut, voice); + cep_subobj_t * cep; + + if (this == NULL) { + return NULL; + } + this->initialize = cepInitialize; + + PICODBG_DEBUG(("set this->step to cepStep")); + + this->step = cepStep; + this->terminate = cepTerminate; + this->subDeallocate = cepSubObjDeallocate; + this->subObj = picoos_allocate(mm, sizeof(cep_subobj_t)); + + cep = (cep_subobj_t *) this->subObj; + + if (this->subObj == NULL) { + picoos_deallocate(mm, (void*) &this); + return NULL; + }; + + /* allocate output coeeficient buffers */ + cep->outF0 = (picoos_int16 *) picoos_allocate(this->common->mm, + PICOCEP_MAXWINLEN * PICOKPDF_MAX_MUL_LFZ_CEPORDER + * sizeof(picoos_int16)); + cep->outXCep = (picoos_int16 *) picoos_allocate(this->common->mm, + PICOCEP_MAXWINLEN * PICOKPDF_MAX_MUL_MGC_CEPORDER + * sizeof(picoos_int16)); + cep->outVoiced = (picoos_uint8 *) picoos_allocate(this->common->mm, + PICOCEP_MAXWINLEN * sizeof(picoos_uint8)); + + if ((NULL == cep->outF0) || (NULL == cep->outXCep) || (NULL + == cep->outVoiced)) { + picoos_deallocate(this->common->mm, (void *) &(cep->outF0)); + picoos_deallocate(this->common->mm, (void *) &(cep->outXCep)); + picoos_deallocate(this->common->mm, (void *) &(cep->outVoiced)); + picoos_deallocate(mm, (void*) &cep); + picoos_deallocate(mm, (void*) &this); + return NULL; + } + cepInitialize(this); + + return this; +}/*picocep_newCepUnit*/ + +/* -------------------------------------------- + * processing and internal functions + * -------------------------------------------- + */ + +/** + * multiply by 1< 0) { + b -= 1; /* maximum positive value */ + }PICODBG_WARN(("picocep_fixptmultpow warning: overflow in fixed point multiplication %i*1<<%i. Clipping to %i\n", a, pow, b)); + } + return b; +} + +/** + * divide by 1< 0) { + a = (a + big) >> pow; + } else { + a = -1 * ((-1 * a + big) >> pow); + } + + return a; +} + +/** + * fixed point multiplication of x and y for large values of x or y or both + * @param x,y : operands 1 & 2, in fixed point S:M:N representation + * @param bigpow (int) : normalization factor=2**N, where N=number of binary decimal digits + * @param invDoubleDec : boolean indicating that x has double decimal size. + * do extra division by 1<= 0) { + a = x >> bigpow; + b = x - (a << bigpow); + } else { + a = -1 * ((x * -1) >> bigpow); /* most significant 2 bytes of x */ + b = x - (a << bigpow); + } + + /* least significant 2 bytes of x i.e. x modulo big */ + /* c = floor(y/big); */ + if (y >= 0) { + c = y >> bigpow; + d = y - (c << bigpow); + } else { + c = -1 * ((y * -1) >> bigpow); + d = y - (c << bigpow); + } + + if (invDoubleDec == 1) { + e = a * d + b * c + picocep_fixptdivpow(b * d, bigpow); + z = a * c + picocep_fixptdivpow(e, bigpow); + } else { + z = ((a * c) << bigpow) + (a * d + b * c) + picocep_fixptdivpow(b * d, + bigpow); /* 4 mult and 3 add instead of 1 mult. */ + } + + return z; +} + +/** + * fixed point multiplication of x and y + * @param x,y : operands 1 & 2, in fixed point S:M:N representation + * @param bigpow (int) : normalization factor=2**N, where N=number of binary decimal digits + * @param invDoubleDec : boolean indicating that x has double decimal size. + * do extra division by 1< 31 + pow) { + PICODBG_WARN(("picocep_fixptmult warning: overflow in fixed point multiplication %i*%i, multsz = %i, pow = %i, decrease bigpow\n", x, y, multsz, pow)); + } +#endif + z = picocep_fixptmultdouble(x, y, bigpow, invDoubleDec); /* perform long multiplication for large x and y */ +#if defined(PICO_DEBUG) + numlongmult++; /* keep track of number of long multiplications */ +#endif + } + return z; +}/* picocep_fixptmult */ + +/** + * fixed point ^division of a vs b + * @param a,b : operands 1 & 2, in fixed point S:M:N representation + * @param bigpow (int) : normalization factor=2**N, where N=number of binary decimal digits + * @return z(int) : result, in fixed point S:M:N representation + * Notes + * - input and output values are 32 bit signed integers + * meant to represent a S.M.N encoding of a floating point value where + * - S : 1 sign bit + * - M : number of binary integer digits (M=32-1-N) + * - N : number of binary decimal digits (N=log2(big)) + * - standard implementation of division by iteratively calculating + * the remainder and setting corresponding bit + * calculate integer part by integer division (DIV), + * then add X bits of precision in decimal part + * @callgraph + * @callergraph + */ +static picoos_int32 picocep_fixptdiv(picoos_int32 a, picoos_int32 b, + picoos_uint8 bigpow) +{ + picoos_int32 r, c, f, h, stop; + r = (a < 0) ? -a : a; /* take absolute value; b is already guaranteed to be positive in smoothing operation */ + if (r == 0) { + return 0; + } + c = 0; + stop = 0; + + /* can speed up slightly by setting stop = 2 => slightly less precision */ + h = r / b; /* in first loop h can be multiple bits, after first loop h can only be 0 or 1 */ + /* faster implementation on target by using comparison instead of DIV? */ + /* For our LDL even in first loop h <= 1, but not in backward step */ + c = c + (h << bigpow); /* after first loop simply set bit */ + r = r - h * b; /* corresponds to modulo operation */ + bigpow--; + r <<= 1; + + while ((bigpow > stop) && (r != 0)) { /* calculate bigpow bits after fixed point */ + /* can speed up slightly by setting stop = 2 => slightly less precision */ + if (r >= b) { + c += (1 << bigpow); /* after first loop simply set bit */ + r -= b; /* corresponds to modulo operation */ + } + bigpow--; + r <<= 1; + } + + if (r != 0) { + f = r + (b >> 1); + if (f >= b) { + if (f >= b + b) { + c += 2; + } else { + c++; + } + } + } + /* final step: do rounding (experimentally improves accuracy for our problem) */ + c = (a >= 0) ? c : -c; /* b is guaranteed to be positive because corresponds to diag0 */ + return c; +}/* picocep_fixptdiv */ + +/** + * perform inversion of diagonal element of WUW matrix + * @param d : diagonal element to be inverted + * @param rowscpow (int) : fixed point base for each dimension of the vectors stored in the database + * @param bigpow (int) : fixed point base used during cepstral smoothing + * @param invpow : fixed point base of inverted pivot elements + * @return inverted pivot element + * @note + * - d is guaranteed positive + * @callgraph + * @callergraph + */ +static picoos_int32 picocep_fixptInvDiagEle(picoos_uint32 d, + picoos_uint8* rowscpow, picoos_uint8 bigpow, picoos_uint8 invpow) +{ + picoos_uint32 r, b, c, h, f, stop; + picoos_uint8 dlen; + /* picoos_int32 zz; */ + c = 0; + stop = 0; + + dlen = picocep_highestBitU(d); + if (invpow + bigpow > 30 + dlen) { /* c must be < 2^32, hence d which is >= 2^(dlen-1) must be > 2^(invpow+bigpow-32), or invpow+bigpow must be <= dlen+30*/ + *rowscpow = invpow + bigpow - 30 - dlen;PICODBG_DEBUG(("input to picocep_fixptInvDiagEle is %i <= 1<<%i = 1< 0) { + c += (h << bigpow); + r -= h * b; + } + bigpow--; + r <<= 1; + + /* loop */ + while ((bigpow > stop) && (r != 0)) { + if (r >= b) { + c += (1 << bigpow); + r -= b; + } + bigpow--; + r <<= 1; + } + + if (r != 0) { + f = r + (b >> 1); + if (f >= b) { + if (f >= b + b) { + c += 2; + } else { + c++; + } + } + } + + return c; +}/* picocep_fixptInvDiagEle */ + +/** + * perform division of two operands a and b by multiplication by inverse of b + * @param a (int32) : operand 1 in fixed point S:M:N representation + * @param invb(uint32) : inverse of operand b, in fixed point P:Q representation (sign is positive) + * @param bigpow(uint8) : N = bigpow when invDoubleDec==0, else N = 2*bigpow + * @param invpow(uint8) : Q = invpow = number of binary decimal digits for invb + * @param invDoubleDec : boolean to indicate that a and the return value c have 2*N binary decimal digits instead of N + * @return c(int32) : result in fixed point S:v:w where w = 2*N when invDoubleDec == 1 + * @note Calls + * - picocep_fixptmult + * @callgraph + * @callergraph + */ +static picoos_int32 picocep_fixptinv(picoos_int32 a, picoos_uint32 invb, + picoos_uint8 bigpow, picoos_uint8 invpow, picoos_uint8 invDoubleDec) +{ + picoos_int32 c; + picoos_int8 normpow; + + c = picocep_fixptmult(a, invb, bigpow, invDoubleDec); + + /* if invDoubleDec==0, picocep_fixptmult assumes a and invb are in base 1< normfactor = big^3/big2 + */ + if (invDoubleDec == 1) { + normpow = 3 * bigpow; + } else { + normpow = bigpow; + } + if (normpow < invpow) { + /* divide with rounding */ + c = picocep_fixptdivpow(c, invpow - normpow); + } else { + c = picocep_fixptmultpow(c, normpow - invpow); + } + return c; +} + +/** + * initializes the coefficients to calculate delta and delta-delta values and the squares of the coefficients + * @param cep : the CEP PU sub-object handle + * @callgraph + * @callergraph + */ +static void initSmoothing(cep_subobj_t * cep) +{ + cep->xi[0] = 1; + cep->xi[1] = -1; + cep->xi[2] = 2; + cep->xi[3] = -4; + cep->xi[4] = 2; + cep->xsqi[0] = 1; + cep->xsqi[1] = 1; + cep->xsqi[2] = 4; + cep->xsqi[3] = 16; + cep->xsqi[4] = 4; + + cep->x1[0] = -1; + cep->x1[1] = 2; + cep->xsq1[0] = 1; + cep->xsq1[1] = 4; + + cep->x2[0] = -1; + cep->x2[1] = -4; + cep->x2[2] = 2; + cep->xsq2[0] = 1; + cep->xsq2[1] = 16; + cep->xsq2[2] = 4; + + cep->xm[0] = 1; + cep->xm[1] = 2; + cep->xm[2] = -4; + cep->xsqm[0] = 1; + cep->xsqm[1] = 4; + cep->xsqm[2] = 16; + + cep->xn[0] = 1; + cep->xn[1] = 2; + cep->xsqn[0] = 1; + cep->xsqn[1] = 4; +} + +/** + * matrix inversion + * @param cep : PU sub object pointer + * @param N + * @param smoothcep : pointer to picoos_int16, sequence of smoothed cepstral vectors + * @param cepnum : cepstral dimension to be treated + * @param pdf : pdf resource + * @param invpow : fixed point base for inverse + * @param invDoubleDec : boolean indicating that result of picocep_fixptinv has fixed point base 2*bigpow + * picocep_fixptmult absorbs double decimal size by dividing its result by extra factor big + * @return void + * @remarks diag0, diag1, diag2, WUm, invdiag0 globals needed in this function (object members in pico) + * @callgraph + * @callergraph + */ +static void invMatrix(cep_subobj_t * cep, picoos_uint16 N, + picoos_int16 *smoothcep, picoos_uint8 cepnum, + picokpdf_PdfMUL pdf, picoos_uint8 invpow, picoos_uint8 invDoubleDec) +{ + picoos_int32 j, v1, v2, h; + picoos_uint32 k; + picoos_uint8 rowscpow, prevrowscpow; + picoos_uint8 ceporder = pdf->ceporder; + picoos_uint8 bigpow = pdf->bigpow; + picoos_uint8 meanpow = pdf->meanpow; + + /* LDL factorization */ + prevrowscpow = 0; + cep->invdiag0[0] = picocep_fixptInvDiagEle(cep->diag0[0], &rowscpow, + bigpow, invpow); /* inverse has fixed point basis 1<diag1[0] = picocep_fixptinv((cep->diag1[0]) << rowscpow, + cep->invdiag0[0], bigpow, invpow, invDoubleDec); /* perform division via inverse */ + cep->diag2[0] = picocep_fixptinv((cep->diag2[0]) << rowscpow, + cep->invdiag0[0], bigpow, invpow, invDoubleDec); + cep->WUm[0] = (cep->WUm[0]) << rowscpow; /* if diag0 too low, multiply LHS and RHS of row in matrix equation by 1<WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag1[j - 1], + cep->WUm[j - 1], bigpow, invDoubleDec); + if (j > 1) { + cep->WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag2[j - 2], + cep->WUm[j - 2], bigpow, invDoubleDec); + } + + /* update row j */ + v1 = picocep_fixptmult((cep->diag1[j - 1]) / (1 << rowscpow), + cep->diag0[j - 1], bigpow, invDoubleDec); /* undo scaling by 1<diag0[j] = cep->diag0[j] - picocep_fixptmult(cep->diag1[j - 1], + v1, bigpow, invDoubleDec); + if (j > 1) { + v2 = picocep_fixptmult((cep->diag2[j - 2]) / (1 << prevrowscpow), + cep->diag0[j - 2], bigpow, invDoubleDec); /* undo scaling by 1<diag0[j] = cep->diag0[j] - picocep_fixptmult( + cep->diag2[j - 2], v2, bigpow, invDoubleDec); + } + prevrowscpow = rowscpow; + cep->invdiag0[j] = picocep_fixptInvDiagEle(cep->diag0[j], &rowscpow, + bigpow, invpow); /* inverse has fixed point basis 1<WUm[j] = (cep->WUm[j]) << rowscpow; + if (j < N - 1) { + h = picocep_fixptmult(cep->diag2[j - 1], v1, bigpow, invDoubleDec); + cep->diag1[j] = picocep_fixptinv((cep->diag1[j] - h) << rowscpow, + cep->invdiag0[j], bigpow, invpow, invDoubleDec); /* eliminate column j below pivot */ + } + if (j < N - 2) { + cep->diag2[j] = picocep_fixptinv((cep->diag2[j]) << rowscpow, + cep->invdiag0[j], bigpow, invpow, invDoubleDec); /* eliminate column j below pivot */ + } + } + + /* divide all entries of WUm by diag0 */ + for (j = 0; j < N; j++) { + cep->WUm[j] = picocep_fixptinv(cep->WUm[j], cep->invdiag0[j], bigpow, + invpow, invDoubleDec); + if (invDoubleDec == 1) { + cep->WUm[j] = picocep_fixptdivpow(cep->WUm[j], bigpow); + } + } + + /* backward substitution */ + for (j = N - 2; j >= 0; j--) { + cep->WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag1[j], cep->WUm[j + + 1], bigpow, invDoubleDec); + if (j < N - 2) { + cep->WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag2[j], + cep->WUm[j + 2], bigpow, invDoubleDec); + } + } + /* copy N frames into smoothcep (only for coeff # "cepnum") */ + /* coefficients normalized to occupy short; for correct waveform energy, divide by (1<<(bigpow-meanpow)) then convert e.g. to picoos_single */ + k = cepnum; + for (j = 0; j < N; j++) { + smoothcep[k] = (picoos_int16)(cep->WUm[j]/(1< At x W x A + * @remarks WUm --> At x W x b + * @callgraph + * @callergraph + */ +static picoos_uint8 makeWUWandWUm(cep_subobj_t * cep, picokpdf_PdfMUL pdf, + picoos_uint16 *indices, picoos_uint16 b, picoos_uint16 N, + picoos_uint8 cepnum) +{ + picoos_uint16 Id[2], Idd[3]; + /*picoos_uint32 vecstart, k;*/ + picoos_uint32 vecstart; + picoos_int32 *x = NULL, *xsq = NULL; + picoos_int32 mean, ivar; + picoos_uint16 i, j, numd = 0, numdd = 0; + picoos_uint8 vecsize = pdf->vecsize; + picoos_int32 prev_WUm, prev_diag0, prev_diag1, prev_diag1_1, prev_diag2; + + prev_WUm = prev_diag0 = prev_diag1 = prev_diag1_1 = prev_diag2 = 0; + for (i = 0; i < N; i++) { + + if ((1 < i) && (i < N - 2)) { + x = cep->xi; + xsq = cep->xsqi; + numd = 2; + numdd = 3; + Id[0] = Idd[0] = i - 1; + Id[1] = Idd[2] = i + 1; + Idd[1] = i; + } else if (i == 0) { + x = cep->x1; + xsq = cep->xsq1; + numd = numdd = 1; + Id[0] = Idd[0] = 1; + } else if (i == 1) { + x = cep->x2; + xsq = cep->xsq2; + numd = 1; + numdd = 2; + Id[0] = Idd[1] = 2; + Idd[0] = 1; + } else if (i == N - 2) { + x = cep->xm; + xsq = cep->xsqm; + numd = 1; + numdd = 2; + Id[0] = Idd[0] = N - 3; + Idd[1] = N - 2; + } else if (i == N - 1) { + x = cep->xn; + xsq = cep->xsqn; + numd = numdd = 1; + Id[0] = Idd[0] = N - 2; + } + + /* process static means and static inverse variances */ + if (i > 0 && indices[b + i] == indices[b + i - 1]) { + cep->diag0[i] = prev_diag0; + cep->WUm[i] = prev_WUm; + } else { + vecstart = indices[b + i] * vecsize; + ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, + PICOCEP_WANTSTATIC); + prev_diag0 = cep->diag0[i] = ivar << 2; /* multiply ivar by 4 (4 used to be first entry of xsq) */ + mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN, + PICOCEP_WANTSTATIC); + prev_WUm = cep->WUm[i] = mean << 1; /* multiply mean by 2 (2 used to be first entry of x) */ + } + + /* process delta means and delta inverse variances */ + for (j = 0; j < numd; j++) { + vecstart = indices[b + Id[j]] * vecsize; + ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, + PICOCEP_WANTDELTA); + cep->diag0[i] += xsq[j] * ivar; + + mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN, + PICOCEP_WANTDELTA); + if (mean != 0) { + cep->WUm[i] += x[j] * mean; + } + } + + /* process delta delta means and delta delta inverse variances */ + for (j = 0; j < numdd; j++) { + vecstart = indices[b + Idd[j]] * vecsize; + ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, + PICOCEP_WANTDELTA2); + cep->diag0[i] += xsq[numd + j] * ivar; + + mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN, + PICOCEP_WANTDELTA2); + if (mean != 0) { + cep->WUm[i] += x[numd + j] * mean; + } + } + + cep->diag0[i] = (cep->diag0[i] + 2) / 4; /* long DIV with rounding */ + cep->WUm[i] = (cep->WUm[i] + 1) / 2; /* long DIV with rounding */ + + /* calculate diag(A,-1) */ + if (i < N - 1) { + if (i < N - 2) { + if (i > 0 && indices[b + i + 1] == indices[b + i]) { + cep->diag1[i] = prev_diag1; + } else { + vecstart = indices[b + i + 1] * vecsize; + /* + diag1[i] = getFromPdf(pdf, vecstart, numvuv, ceporder, numdeltas, cepnum, + bigpow, meanpowUm, ivarpow, PICOCEP_WANTIVAR, PICOCEP_WANTDELTA2); + */ + prev_diag1 = cep->diag1[i] = getFromPdf(pdf, vecstart, + cepnum, PICOCEP_WANTIVAR, PICOCEP_WANTDELTA2); + } + /* + k = vecstart +pdf->numvuv+pdf->ceporder*2 + pdf->numdeltas*3 + + pdf->ceporder*2 +cepnum; + cep->diag1[i] = (picoos_int32)(pdf->content[k]) << pdf->bigpow; + */ + } else { + cep->diag1[i] = 0; + } + if (i > 0) { + if (i > 1 && indices[b + i] == indices[b + i - 1]) { + cep->diag1[i] += prev_diag1_1; + } else { + vecstart = indices[b + i] * vecsize; + /* + k = vecstart + pdf->numvuv + pdf->ceporder * 2 + pdf->numdeltas * 3 + pdf->ceporder * 2 + cepnum; + cep->diag1[i] += (picoos_int32)(pdf->content[k]) << pdf->bigpow; */ + /* cepnum'th delta delta ivar */ + + prev_diag1_1 = getFromPdf(pdf, vecstart, cepnum, + PICOCEP_WANTIVAR, PICOCEP_WANTDELTA2); + cep->diag1[i] += prev_diag1_1; + } + + } /*i < N-1 */ + cep->diag1[i] *= -2; + } + } + + /* calculate diag(A,-2) */ + for (i = 0; i < N - 2; i++) { + if (i > 0 && indices[b + i + 1] == indices[b + i]) { + cep->diag2[i] = prev_diag2; + } else { + vecstart = indices[b + i + 1] * vecsize; + /* + k = vecstart + pdf->numvuv + pdf->ceporder * 2 + pdf->numdeltas * 3 + pdf->ceporder * 2 + cepnum; + cep->diag2[i] = (picoos_int32)(pdf->content[k]) << pdf->bigpow; + k -= pdf->ceporder; + ivar = (picoos_int32)(pdf->content[k]) << pdf->bigpow; + */ + cep->diag2[i] = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, + PICOCEP_WANTDELTA2); + ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, + PICOCEP_WANTDELTA); + cep->diag2[i] -= (ivar + 2) / 4; + prev_diag2 = cep->diag2[i]; + } + } + + return 0; +}/* makeWUWandWUm */ + +/** + * Retrieve actual values for MGC from PDF resource + * @param pdf : pointer to picoos_uint8, sequence of pdf vectors, each vector of length 1+ceporder*2+numdeltas*3+ceporder*3 + * @param vecstart : indices of pdf vectors for all frames in current sentence + * @param cepnum : cepstral dimension to be treated + * @param wantMeanOrIvar : flag to select mean or variance values + * @param wantStaticOrDeltax : flag to select static or delta values + * @return the actual value retrieved + * @callgraph + * @callergraph + */ +static picoos_int32 getFromPdf(picokpdf_PdfMUL pdf, picoos_uint32 vecstart, + picoos_uint8 cepnum, picocep_WantMeanOrIvar_t wantMeanOrIvar, + picocep_WantStaticOrDelta_t wantStaticOrDeltax) +{ + picoos_uint8 s, ind; + picoos_uint8 *p; + picoos_uint8 ceporder, ceporder2, cc; + picoos_uint32 k; + picoos_int32 mean = 0, ivar = 0; + + if (pdf->numdeltas == 0xFF) { + switch (wantMeanOrIvar) { + case PICOCEP_WANTMEAN: + switch (wantStaticOrDeltax) { + case PICOCEP_WANTSTATIC: + p = pdf->content + + (vecstart + pdf->numvuv + cepnum * 2); /* cepnum'th static mean */ + mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8)) + | *p) << (pdf->meanpowUm[cepnum]); + break; + case PICOCEP_WANTDELTA: + cc = pdf->ceporder + cepnum; + p = pdf->content + (vecstart + pdf->numvuv + cc * 2); /* cepnum'th delta mean */ + mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8)) + | *p) << (pdf->meanpowUm[cc]); + break; + case PICOCEP_WANTDELTA2: + cc = pdf->ceporder * 2 + cepnum; + p = pdf->content + (vecstart + pdf->numvuv + cc * 2); /* cepnum'th delta delta mean */ + mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8)) + | *p) << (pdf->meanpowUm[cc]); + break; + default: + /* should never come here */ + PICODBG_ERROR(("unknown type wantStaticOrDeltax = %i", wantStaticOrDeltax)); + } + return mean; + break; + case PICOCEP_WANTIVAR: + switch (wantStaticOrDeltax) { + case PICOCEP_WANTSTATIC: + k = vecstart + pdf->numvuv + pdf->ceporder * 6 + cepnum; /* cepnum'th static ivar */ + ivar = (picoos_int32) (pdf->content[k]) + << (pdf->ivarpow[cepnum]); + break; + case PICOCEP_WANTDELTA: + ceporder = pdf->ceporder; + k = vecstart + pdf->numvuv + ceporder * 7 + cepnum; /* cepnum'th delta ivar */ + ivar = (picoos_int32) (pdf->content[k]) + << (pdf->ivarpow[ceporder + cepnum]); + break; + case PICOCEP_WANTDELTA2: + ceporder = pdf->ceporder; + k = vecstart + pdf->numvuv + ceporder * 8 + cepnum; /* cepnum'th delta delta ivar */ + ivar = (picoos_int32) (pdf->content[k]) + << (pdf->ivarpow[2 * ceporder + cepnum]); + break; + default: + /* should never get here */ + PICODBG_ERROR(("unknown type wantStaticOrDeltax = %i", wantStaticOrDeltax)); + } + return ivar; + break; + default: + /* should never come here */ + PICODBG_ERROR(("unknown type wantMeanOrIvar = %n", wantMeanOrIvar)); + return 0; + } + } else { + switch (wantMeanOrIvar) { + case PICOCEP_WANTMEAN: + switch (wantStaticOrDeltax) { + case PICOCEP_WANTSTATIC: + p = pdf->content + + (vecstart + pdf->numvuv + cepnum * 2); /* cepnum'th static mean */ + mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8)) + | *p) << (pdf->meanpowUm[cepnum]); + return mean; + break; + case PICOCEP_WANTDELTA: + ceporder = pdf->ceporder; + s = 0; + ind = 0; + while ((s < pdf->numdeltas) && (ind < cepnum || (ind + == 0 && cepnum == 0))) { /* rawmean deltas are sparse so investigate indices in column */ + k = vecstart + pdf->numvuv + ceporder * 2 + s; /* s'th delta index */ + ind = (picoos_uint8) (pdf->content[k]); /* is already picoos_uint8 but just to make explicit */ + if (ind == cepnum) { + k = vecstart + pdf->numvuv + ceporder * 2 + + pdf->numdeltas + s * 2; /* s'th sparse delta mean, corresponds to cepnum'th delta mean */ + mean + = ((picoos_int32) ((picoos_int16) ((pdf->content[k + + 1]) << 8)) | pdf->content[k]) + << (pdf->meanpowUm[ceporder + + cepnum]); + return mean; + } + s++; + } + return 0; + break; + case PICOCEP_WANTDELTA2: + ceporder = pdf->ceporder; + ceporder2 = ceporder * 2; + s = pdf->numdeltas; + ind = 2 * ceporder; + while ((s-- > 0) && (ind > ceporder + cepnum)) { /* rawmean deltas are sparse so investigate indices in column */ + k = vecstart + pdf->numvuv + ceporder2 + s; /* s'th delta index */ + ind = (picoos_uint8) (pdf->content[k]); /* is already picoos_uint8 but just to make explicit */ + if (ind == ceporder + cepnum) { + k = vecstart + pdf->numvuv + ceporder2 + + pdf->numdeltas + s * 2; /* s'th sparse delta mean, corresponds to cepnum'th delta delta mean */ + mean + = ((picoos_int32) ((picoos_int16) ((pdf->content[k + + 1]) << 8)) | pdf->content[k]) + << (pdf->meanpowUm[ceporder2 + + cepnum]); + return mean; + } + } + return 0; + break; + default: + PICODBG_ERROR(("getFromPdf: unknown type wantStaticOrDeltax = %i\n", wantStaticOrDeltax)); + return 0; + } + break; + case PICOCEP_WANTIVAR: + switch (wantStaticOrDeltax) { + case PICOCEP_WANTSTATIC: + k = vecstart + pdf->numvuv + pdf->ceporder * 2 + + pdf->numdeltas * 3 + cepnum; /* cepnum'th static ivar */ + ivar = (picoos_int32) (pdf->content[k]) + << (pdf->ivarpow[cepnum]); + break; + case PICOCEP_WANTDELTA: + ceporder = pdf->ceporder; + k = vecstart + pdf->numvuv + ceporder * 3 + + pdf->numdeltas * 3 + cepnum; /* cepnum'th delta ivar */ + ivar = (picoos_int32) (pdf->content[k]) + << (pdf->ivarpow[ceporder + cepnum]); + break; + case PICOCEP_WANTDELTA2: + ceporder2 = 2 * pdf->ceporder; + k = vecstart + pdf->numvuv + ceporder2 + pdf->numdeltas + * 3 + ceporder2 + cepnum; /* cepnum'th delta delta ivar */ + ivar = (picoos_int32) (pdf->content[k]) + << (pdf->ivarpow[ceporder2 + cepnum]); + break; + default: + PICODBG_ERROR(("unknown type wantStaticOrDeltax = %i", wantStaticOrDeltax)); + } + return ivar; + break; + default: + PICODBG_ERROR(("unknown type wantMeanOrIvar = %i", wantMeanOrIvar)); + return 0; + } + } + return 0; +} + +/** + * Retrieve actual values for MGC from PDF resource - Variant "Direct" + * @param pdf : pointer to picoos_uint8, sequence of pdf vectors, each vector of length 1+ceporder*2+numdeltas*3+ceporder*3 + * @param indices : indices of pdf vectors for all frames in current sentence + * @param activeEndPos : ?? + * @param cepnum : cepstral dimension to be treated + * @param smoothcep : ?? + * @return the actual value retrieved + * @callgraph + * @callergraph + */ +static void getDirect(picokpdf_PdfMUL pdf, picoos_uint16 *indices, + picoos_uint16 activeEndPos, + picoos_uint8 cepnum, picoos_int16 *smoothcep) +{ + picoos_uint16 i; + picoos_uint32 j; + picoos_uint32 vecstart; + picoos_int32 mean, ivar; + picoos_int32 prev_mean; + picoos_uint8 vecsize = pdf->vecsize; + picoos_uint8 order = pdf->ceporder; + + j = cepnum; + prev_mean = 0; + for (i = 0; i < activeEndPos; i++) { + if (i > 0 && indices[i] == indices[i - 1]) { + mean = prev_mean; + } else { + vecstart = indices[i] * vecsize; + mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN, + PICOCEP_WANTSTATIC); + ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, + PICOCEP_WANTSTATIC); + prev_mean = mean = picocep_fixptdiv(mean, ivar, pdf->bigpow); + } + smoothcep[j] = (picoos_int16)(mean/(1<meanpow)); + j += order; + } +} + +/** + * Retrieve actual values for voicing from PDF resource + * @param pdf : pointer to picoos_uint8, sequence of pdf vectors, each vector of length 1+ceporder*2+numdeltas*3+ceporder*3 + * @param indices : indices of pdf vectors for all frames in current sentence + * @param activeEndPos : end position of indices to be considered + * @return smoothcep : the values retrieved + * @callgraph + * @callergraph + */ +static void getVoiced(picokpdf_PdfMUL pdf, picoos_uint16 *indices, + picoos_uint16 activeEndPos, + picoos_uint8 *smoothcep) +{ + picoos_uint16 i, j; + picoos_uint32 vecstart; + picoos_uint8 vecsize = pdf->vecsize; + + if (pdf->numvuv == 0) { + /* do nothing */ + } else { + for (i = 0, j = 0; i < activeEndPos; i++, j++) { + vecstart = indices[i] * vecsize; + smoothcep[j] = pdf->content[vecstart]; /* odd value is voiced, even if unvoiced */ + } + } +} + +/** reads platform-independent uint16 from buffer at *pos and advances *pos + * @param buf : buffer picoos_uint8 + * @param *pos : start position inside buffer of pi uint16 + * @return the uint16 + * @callgraph + * @callergraph + */ +static picoos_uint16 get_pi_uint16(picoos_uint8 * buf, picoos_uint16 *pos) +{ + picoos_uint16 res; + res = buf[(*pos)] | ((picoos_uint16) buf[(*pos) + 1] << 8); + *pos += 2; + return res; +} +/** + * Looks up indices of one phone item and fills index buffers. Consumes Item + * @param cep : the CEP PU sub object pointer + * @param ihead : pointer to the start of the phone item + * @callgraph + * @callergraph + */ +static void treat_phone(cep_subobj_t * cep, picodata_itemhead_t * ihead) +{ + picoos_uint16 state, frame, frames; + picoos_uint16 indlfz, indmgc; + picoos_uint16 pos; + picoos_uint8 bufferFull; + + /* treat all states + * for each state, repeat putting the index into the index buffer framesperstate times. + */ + /* set state and frame to the first state and frame in the phone to be considered */ + state = 0; /* the first state to be considered */ + frame = 0; /* the first frame to be considered */ + /* numFramesPerState: 2 byte, lf0Index: 2 byte, mgcIndex: 2 byte -> 6 bytes per state */ + PICODBG_DEBUG(("skipping to phone state %i ",state)); + pos = cep->inReadPos + PICODATA_ITEM_HEADSIZE + state * 6; + /* */ + PICODBG_DEBUG(("state info starts at inBuf pos %i ",pos)); + /* get the current frames per state */ + frames = get_pi_uint16(cep->inBuf, &pos); + /* */ + PICODBG_DEBUG(("number of frames for this phone state: %i",frames)); + /* */ + PICODBG_DEBUG(("PARSE starting with frame %i",frame)); + + bufferFull = cep->indexWritePos >= PICOCEP_MAXWINLEN; + while ((state < ihead->info2) && (bufferFull == FALSE)) { + + /* get the current state's lf0 and mgc indices and adjust according to state */ + /* the indices have to be calculated as follows: + * new index = (index-1) + stateoffset(state) */ + + indlfz = get_pi_uint16(cep->inBuf, &pos); /* lfz index */ + indlfz += -1 + cep->pdflfz->stateoffset[state]; /* transform index */ + indmgc = get_pi_uint16(cep->inBuf, &pos); /* mgc index */ + indmgc += -1 + cep->pdfmgc->stateoffset[state]; /* transform index */ + + /* are we reaching the end of the index buffers? */ + if ((cep->indexWritePos - frame) + frames > PICOCEP_MAXWINLEN) { + /* number of frames that will still fit */ + frames = PICOCEP_MAXWINLEN - (cep->indexWritePos - frame); + bufferFull = TRUE; + PICODBG_DEBUG(("smoothing buffer full at state=%i frame=%i",state, frame)); + } + while (frame < frames) { + cep->indicesMGC[cep->indexWritePos] = indmgc; + cep->indicesLFZ[cep->indexWritePos] = indlfz; + cep->phoneId[cep->indexWritePos] = ihead->info1; + cep->indexWritePos++; + frame++; + } + /* proceed to next state */ + PICODBG_DEBUG(("finished state %i with %i frames, now at index write pos %i", + state, frames,cep->indexWritePos)); + state++; + if (state < ihead->info2) { + frame = 0; + frames = get_pi_uint16(cep->inBuf, &pos); + } + } + /* consume the phone item */ + cep->inReadPos = cep->nextInPos; + /* */ + PICODBG_DEBUG(("finished phone, advancing inReadPos to %i",cep->inReadPos)); +} + +/** + * Returns true if an Item has to be forwarded to next PU + * @param ihead : pointer to item head structure + * @return TRUE : the item should be forwarded + * @return FALSE : the item should be consumed + * @callgraph + * @callergraph + */ +static picoos_uint8 forwardingItem(picodata_itemhead_t * ihead) +{ + if ((PICODATA_ITEM_CMD == ihead->type) && (PICODATA_ITEMINFO1_CMD_IGNSIG + == ihead->info1)) { + return FALSE; + } else { + return TRUE; + } +} + +/** + * performs a step of the cep processing + * @param this : pointer to current PU (Control Unit) + * @param mode : mode for the PU (not used) + * @param numBytesOutput : pointer to output number fo bytes produced + * @return one of the "picodata_step_result_t" values + * @callgraph + * @callergraph + */ +static picodata_step_result_t cepStep(register picodata_ProcessingUnit this, + picoos_int16 mode, picoos_uint16 * numBytesOutput) +{ + register cep_subobj_t * cep; + picodata_itemhead_t ihead /* , ohead */; + picoos_uint8 * icontents; + pico_status_t sResult = PICO_OK; + picoos_uint16 blen, clen; + picoos_uint16 numinb, numoutb; + +#if defined (PICO_DEBUG) + picoos_char msgstr[PICOCEP_MSGSTR_SIZE]; +#endif + numinb = 0; + numoutb = 0; + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + cep = (cep_subobj_t *) this->subObj; + mode = mode; /* avoid warning "var not used in this function"*/ + + /*Init number of output bytes*/ + *numBytesOutput = 0; + + while (1) { /* exit via return */ + + PICODBG_DEBUG(("doing pu state %i", cep->procState)); + + switch (cep->procState) { + + case PICOCEP_STEPSTATE_COLLECT: + /* *************** item collector ***********************************/ + + PICODBG_TRACE(("COLLECT")); + + /*collecting items from the PU input buffer*/ + sResult = picodata_cbGetItem(this->cbIn, + &(cep->inBuf[cep->inWritePos]), cep->inBufSize + - cep->inWritePos, &blen); + if (PICO_EOF == sResult) { /* there are no more items available and we always need more data here */ + PICODBG_DEBUG(("COLLECT need more data, returning IDLE")); + return PICODATA_PU_IDLE; + } + + PICODBG_DEBUG(("got item, status: %d", sResult)); + + if ((PICO_OK == sResult) && (blen > 0)) { + /* we now have one item */ + cep->inWritePos += blen; + cep->procState = PICOCEP_STEPSTATE_PROCESS_PARSE; + } else { + /* ignore item and stay in collect */ + PICODBG_ERROR(("COLLECT got bad result %i", sResult)); + cep->inReadPos = cep->inWritePos = 0; + } + /* return PICODATA_PU_ATOMIC; */ + break; + + case PICOCEP_STEPSTATE_PROCESS_PARSE: + /* **************** put item indices into index buffers (with repetition) ******************/ + + PICODBG_TRACE(("PARSE")); + + PICODBG_DEBUG(("getting info from inBuf in range: [%i,%i[", cep->inReadPos, cep->inWritePos)); + if (cep->inWritePos <= cep->inReadPos) { + /* no more items in inBuf */ + /* we try to get more data */ + PICODBG_DEBUG(("no more items in inBuf, try to collect more")); + /* cep->needMoreInput = TRUE; */ + cep->inReadPos = cep->inWritePos = 0; + cep->procState = PICOCEP_STEPSTATE_COLLECT; + break; + } + /* look at the current item */ + /*verify that current item is valid */ + if (!picodata_is_valid_item(cep->inBuf + cep->inReadPos, + cep->inWritePos - cep->inReadPos)) { + PICODBG_ERROR(("found invalid item")); + sResult = picodata_get_iteminfo( + cep->inBuf + cep->inReadPos, cep->inWritePos + - cep->inReadPos, &ihead, &icontents);PICODBG_DEBUG(("PARSE bad item %s",picodata_head_to_string(&ihead,msgstr,PICOCEP_MSGSTR_SIZE))); + + return PICODATA_PU_ERROR; + } + + sResult = picodata_get_iteminfo(cep->inBuf + cep->inReadPos, + cep->inWritePos - cep->inReadPos, &ihead, &icontents); + + if (PICO_EXC_BUF_UNDERFLOW == sResult) { + /* no more items in inBuf */ + /* we try to get more data */ + PICODBG_DEBUG(("no more items in inBuf, try to collect more")); + /* cep->needMoreInput = TRUE; */ + cep->inReadPos = cep->inWritePos = 0; + cep->procState = PICOCEP_STEPSTATE_COLLECT; + break; + } else if (PICO_OK != sResult) { + PICODBG_ERROR(("unknown exception (sResult == %i)",sResult)); + return (picodata_step_result_t) picoos_emRaiseException( + this->common->em, sResult, NULL, NULL); + break; + } + + PICODBG_DEBUG(("PARSE looking at item %s",picodata_head_to_string(&ihead,msgstr,PICOCEP_MSGSTR_SIZE))); + + cep->nextInPos = PICODATA_ITEM_HEADSIZE + ihead.len; + + /* we decide what to do next depending on the item and the state of the index buffer: + * - process buffer if buffer not empty and sentence end or flush or ignsig/start (don't consume item yet) + * - fill buffer with (part of) phone contents if item is a phone + * - consume or copy for later output otherwise + */ + + if (cep->inIgnoreState) { + if ((PICODATA_ITEM_CMD == ihead.type) + && (PICODATA_ITEMINFO1_CMD_IGNSIG == ihead.info1) + && (PICODATA_ITEMINFO2_CMD_END == ihead.info2)) { + cep->inIgnoreState = 0; + }PICODBG_DEBUG(("cep: PARSE consuming item of inBuf")); + cep->inReadPos = cep->nextInPos; + break; + } + + /* see if it is a sentence end boundary or termination boundary (flush) and there are indices to smooth -> smooth */ + if ((PICODATA_ITEM_BOUND == ihead.type) + && ((PICODATA_ITEMINFO1_BOUND_SEND == ihead.info1) + || (PICODATA_ITEMINFO1_BOUND_TERM == ihead.info1)) + && (cep->indexWritePos > 0)) { + /* we smooth the buffer */ + cep->activeEndPos = cep->indexWritePos; + cep->sentenceEnd = TRUE; + /* output whatever we got */ + PICODBG_DEBUG(("cep: PARSE found sentence terminator; setting activeEndPos to %i",cep->activeEndPos)); + cep->procState = PICOCEP_STEPSTATE_PROCESS_SMOOTH; + break; + } else if (PICODATA_ITEM_PHONE == ihead.type) { + /* it is a phone */ + PICODBG_DEBUG(("cep: PARSE treating PHONE")); + treat_phone(cep, &ihead); + + } else { + if ((PICODATA_ITEM_CMD == ihead.type) + && (PICODATA_ITEMINFO1_CMD_IGNSIG == ihead.info1) + && (PICODATA_ITEMINFO2_CMD_START == ihead.info2)) { + cep->inIgnoreState = 1; + } + /* sentence end or flush remaining after frame or other non-processable item, e.g. command */ + /* do we have to forward? */ + if (forwardingItem(&ihead)) { + /* if no active frames, output immediately */ + if (cep->indexWritePos <= 0) { + /* copy item to outBuf */ + PICODBG_DEBUG(("PARSE copy item in inBuf to outBuf")); + picodata_copy_item(cep->inBuf + cep->inReadPos, + cep->inWritePos - cep->inReadPos, + cep->outBuf, cep->outBufSize, &blen); + cep->outWritePos += blen; + PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], + (picoos_uint8 *)"cep: do forward item ", + cep->outBuf, PICODATA_MAX_ITEMSIZE); + /* output item and then go to parse to treat a new item. */ + cep->feedFollowState + = PICOCEP_STEPSTATE_PROCESS_PARSE; + cep->procState = PICOCEP_STEPSTATE_FEED; + } else if ((cep->headxWritePos < PICOCEP_MAXNR_HEADX) + && (cep->cbufWritePos + ihead.len + < cep->cbufBufSize)) { + /* there is enough space to store item */ + PICODBG_DEBUG(("unhandled item (type %c, length %i). Storing associated with index %i",ihead.type, ihead.len, cep->indexWritePos)); + sResult + = picodata_get_itemparts( + cep->inBuf + cep->inReadPos, + cep->inWritePos - cep->inReadPos, + &(cep->headx[cep->headxWritePos].head), + &(cep->cbuf[cep->cbufWritePos]), + cep->cbufBufSize + - cep->cbufWritePos, &clen); + + if (sResult != PICO_OK) { + PICODBG_ERROR(("problem getting item parts")); + picoos_emRaiseException(this->common->em, + sResult, NULL, NULL); + return PICODATA_PU_ERROR; + } + /* remember sync position */ + cep->headx[cep->headxWritePos].frame + = cep->indexWritePos; + + if (clen > 0) { + cep->headx[cep->headxWritePos].cind + = cep->cbufWritePos; + cep->cbufWritePos += clen; + } else { + cep->headx[cep->headxWritePos].cind = 0; + } + cep->headxWritePos++; + } else { + /* buffer full, smooth and output whatever we got */ + PICODBG_DEBUG(("PARSE is forced to smooth prematurely; setting activeEndPos to %i", cep->activeEndPos)); + cep->procState = PICOCEP_STEPSTATE_PROCESS_SMOOTH; + /* don't consume item yet */ + break; + } + } else { + }PICODBG_DEBUG(("cep: PARSE consuming item of inBuf")); + cep->inReadPos = cep->nextInPos; + } + break; + + case PICOCEP_STEPSTATE_PROCESS_SMOOTH: + /* **************** smooth (indexed) coefficients and store smoothed in outBuffers ****************/ + + PICODBG_TRACE(("SMOOTH")); + { + picokpdf_PdfMUL pdf; + + /* picoos_uint16 framesTreated = 0; */ + picoos_uint8 cepnum; + picoos_uint16 N; + + N = cep->activeEndPos; /* numframes in current step */ + + /* the range to be smoothed starts at 0 and is N long */ + + /* smooth each cepstral dimension separately */ + /* still to be experimented if higher order coeff can remain unsmoothed, i.e. simple copy from pdf */ + + /* reset the f0, ceps and voiced outfuffers */ + cep->outXCepReadPos = cep->outXCepWritePos = 0; + cep->outVoicedReadPos = cep->outVoicedWritePos = 0; + cep->outF0ReadPos = cep->outF0WritePos = 0; + + PICODBG_DEBUG(("smoothing %d frames\n", N)); + + /* smooth f0 */ + pdf = cep->pdflfz; + for (cepnum = 0; cepnum < pdf->ceporder; cepnum++) { + if (cep->activeEndPos <= 0) { + /* do nothing */ + } else if (3 < N) { + makeWUWandWUm(cep, pdf, cep->indicesLFZ, 0, N, + cepnum); /* update diag0, diag1, diag2, WUm */ + invMatrix(cep, N, cep->outF0 + cep->outF0WritePos, cepnum, pdf, + PICOCEP_LFZINVPOW, PICOCEP_LFZDOUBLEDEC); + } else { + getDirect(pdf, cep->indicesLFZ, cep->activeEndPos, + cepnum, cep->outF0 + cep->outF0WritePos); + } + }/* end for cepnum */ + cep->outF0WritePos += cep->activeEndPos * pdf->ceporder; + + /* smooth mgc */ + pdf = cep->pdfmgc; + for (cepnum = 0; cepnum < pdf->ceporder; cepnum++) { + if (cep->activeEndPos <= 0) { + /* do nothing */ + } else if (3 < N) { + makeWUWandWUm(cep, pdf, cep->indicesMGC, 0, N, + cepnum); /* update diag0, diag1, diag2, WUm */ + invMatrix(cep, N, cep->outXCep + + cep->outXCepWritePos, cepnum, + pdf, PICOCEP_MGCINVPOW, + PICOCEP_MGCDOUBLEDEC); + } else { + getDirect(pdf, cep->indicesMGC, cep->activeEndPos, + cepnum, cep->outXCep + cep->outXCepWritePos); + } + }/* end for cepnum */ + cep->outXCepWritePos += cep->activeEndPos * pdf->ceporder; + + getVoiced(pdf, cep->indicesMGC, cep->activeEndPos, cep->outVoiced + + cep->outVoicedWritePos); + cep->outVoicedWritePos += cep->activeEndPos; + + } + /* setting indexReadPos to the next active index to be used. (will be advanced by FRAME when + * reading the phoneId */ + cep->indexReadPos = 0; + cep->procState = PICOCEP_STEPSTATE_PROCESS_FRAME; + return PICODATA_PU_BUSY; /*data to feed*/ + + break; + + case PICOCEP_STEPSTATE_PROCESS_FRAME: + + /* *************** creating output items (type FRAME) ***********************************/ + + PICODBG_TRACE(("FRAME")); + + if ((cep->headxBottom < cep->headxWritePos) + && (cep->headx[cep->headxBottom].frame + <= cep->indexReadPos)) { + + /* output item in headx/cbuf */ + /* copy item to outBuf */ + PICODBG_DEBUG(("FRAME copy item in inBuf to outBuf")); + picodata_put_itemparts( + &(cep->headx[cep->headxBottom].head), + &(cep->cbuf[cep->headx[cep->headxBottom].cind]), + cep->headx[cep->headxBottom].head.len, cep->outBuf, + cep->outBufSize, &blen); + cep->outWritePos += blen; + /* consume item in headx/cbuf */ + PICODBG_DEBUG(("PARSE consuming item of headx/cbuf")); + cep->headxBottom++; + + /* output item and then go to parse to treat a new item. */ + cep->feedFollowState = PICOCEP_STEPSTATE_PROCESS_FRAME; + cep->procState = PICOCEP_STEPSTATE_FEED; + break; + } + + if (cep->indexReadPos < cep->activeEndPos) { + /*------------ there are frames to output ----------------------------------------*/ + /* still frames to output, create new FRAME_PAR item */ + + cep->nNumFrames++; + + PICODBG_DEBUG(("FRAME creating FRAME_PAR: active: [0,%i[, read=%i, write=%i", + cep->activeEndPos, cep->indexReadPos, cep->indexWritePos + )); + + /* create FRAME_PAR items from cep->outXX one by one */ + + /* converting the ceps shorts into floats: + * scmeanpow = pdf->bigpow - pdf->meanpow; + * for all sval: + * fval = (picoos_single) sval / scmeanpow; + */ + + cep->outWritePos = cep->outReadPos = 0; + cep->outBuf[cep->outWritePos++] = cep->framehead.type; + cep->outBuf[cep->outWritePos++] = cep->framehead.info1; + cep->outBuf[cep->outWritePos++] = cep->framehead.info2; + cep->outBuf[cep->outWritePos++] = cep->framehead.len; + + PICODBG_DEBUG(("FRAME writing position after header: %i",cep->outWritePos)); + + { + picoos_uint16 tmpUint16; + picoos_int16 tmpInt16; + picoos_uint16 i; + + /* */ + PICODBG_DEBUG(("FRAME reading phoneId[%i] = %c:",cep->indexReadPos, cep->phoneId[cep->indexReadPos])); + /* */ + + tmpUint16 + = (picoos_uint16) cep->phoneId[cep->indexReadPos]; + + picoos_mem_copy((void *) &tmpUint16, + (void *) &cep->outBuf[cep->outWritePos], + sizeof(tmpUint16)); + + cep->outWritePos += sizeof(tmpUint16); + + PICODBG_DEBUG(("FRAME writing position after phone id: %i",cep->outWritePos)); + + for (i = 0; i < cep->pdflfz->ceporder; i++) { + + tmpUint16 = (cep->outVoiced[cep->outVoicedReadPos] + & 0x01) ? cep->outF0[cep->outF0ReadPos] + : (picoos_uint16) 0; + + picoos_mem_copy((void *) &tmpUint16, + (void *) &cep->outBuf[cep->outWritePos], + sizeof(tmpUint16)); + cep->outWritePos += sizeof(tmpUint16); + + tmpUint16 + = (picoos_uint16) (cep->outVoiced[cep->outVoicedReadPos]); + picoos_mem_copy((void *) &tmpUint16, + (void *) &cep->outBuf[cep->outWritePos], + sizeof(tmpUint16)); + cep->outWritePos += sizeof(tmpUint16); + tmpUint16 + = (picoos_uint16) (cep->outF0[cep->outF0ReadPos]); + picoos_mem_copy((void *) &tmpUint16, + (void *) &cep->outBuf[cep->outWritePos], + sizeof(tmpUint16)); + cep->outWritePos += sizeof(tmpUint16); + + cep->outVoicedReadPos++; + cep->outF0ReadPos++; + } + + PICODBG_DEBUG(("FRAME writing position after f0: %i",cep->outWritePos)); + + for (i = 0; i < cep->pdfmgc->ceporder; i++) { + tmpInt16 = cep->outXCep[cep->outXCepReadPos++]; + picoos_mem_copy((void *) &tmpInt16, + (void *) &cep->outBuf[cep->outWritePos], + sizeof(tmpInt16)); + cep->outWritePos += sizeof(tmpInt16); + } + + PICODBG_DEBUG(("FRAME writing position after cepstrals: %i",cep->outWritePos)); + + tmpUint16 + = (picoos_uint16) cep->indicesMGC[cep->indexReadPos++]; + + picoos_mem_copy((void *) &tmpUint16, + (void *) &cep->outBuf[cep->outWritePos], + sizeof(tmpUint16)); + + PICODBG_DEBUG(("FRAME writing position after mgc index: %i",cep->outWritePos)); + + cep->outWritePos += sizeof(tmpUint16); + + } + /* finished to create FRAME_PAR, now output and then come back*/ + cep->feedFollowState = PICOCEP_STEPSTATE_PROCESS_FRAME; + cep->procState = PICOCEP_STEPSTATE_FEED; + + } else if (cep->sentenceEnd) { + /*------------ no more frames to output at end of sentence ----------------------------------------*/ + PICODBG_INFO(("End of sentence - Processed frames : %d", + cep->nNumFrames)); + cep->nNumFrames = 0;PICODBG_DEBUG(("FRAME no more active frames for this sentence")); + /* no frames left in this sentence*/ + /* reset for new sentence */ + initSmoothing(cep); + cep->sentenceEnd = FALSE; + cep->indexReadPos = cep->indexWritePos = 0; + cep->activeEndPos = PICOCEP_MAXWINLEN; + cep->headxBottom = cep->headxWritePos = 0; + cep->cbufWritePos = 0; + cep->procState = PICOCEP_STEPSTATE_PROCESS_PARSE; + } else { + /*------------ no more frames can be output but sentence end not reached ----------------------------------------*/ + PICODBG_DEBUG(("Maximum number of frames per sentence reached")); + cep->procState = PICOCEP_STEPSTATE_PROCESS_PARSE; + } + /*----------------------------------------------------*/ + break; + + case PICOCEP_STEPSTATE_FEED: + /* ***********************************************************************/ + /* FEED: combine input item with pos/phon pairs to output item */ + /* ***********************************************************************/ + + PICODBG_DEBUG(("FEED")); + + PICODBG_DEBUG(("FEED putting outBuf item into cb")); + + /*feeding items to PU output buffer*/ + sResult = picodata_cbPutItem(this->cbOut, cep->outBuf, + cep->outBufSize, &blen); + + if (PICO_EXC_BUF_OVERFLOW == sResult) { + /* we have to redo this item */ + PICODBG_DEBUG(("FEED got overflow, returning PICODATA_PU_OUT_FULL")); + return PICODATA_PU_OUT_FULL; + } else if (PICO_OK == sResult) { + + if (cep->outBuf[0] != 'k') { + PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], + (picoos_uint8 *)"cep: ", + cep->outBuf, PICODATA_MAX_ITEMSIZE); + } + + *numBytesOutput += blen; + /*-------------------------*/ + /*reset the output pointers*/ + /*-------------------------*/ + if (cep->outReadPos >= cep->outWritePos) { + cep->outReadPos = 0; + cep->outWritePos = 0; + } + cep->procState = cep->feedFollowState; + PICODBG_DEBUG(("FEED ok, going back to procState %i", cep->procState)); + return PICODATA_PU_BUSY; + } else { + PICODBG_DEBUG(("FEED got exception %i when trying to output item",sResult)); + cep->procState = cep->feedFollowState; + return (picodata_step_result_t) sResult; + } + break; + + default: + /*NOT feeding items*/ + sResult = PICO_EXC_BUF_IGNORE; + break; + }/*end switch (cep->procState) */ + return PICODATA_PU_BUSY; /*check if there is more data to process after feeding*/ + + }/*end while*/ + /* we should never come here */ + return PICODATA_PU_ERROR; +}/*cepStep*/ + +/* Picocep.c end */ diff --git a/pico/lib/picocep.h b/pico/lib/picocep.h new file mode 100644 index 0000000..79a5d7c --- /dev/null +++ b/pico/lib/picocep.h @@ -0,0 +1,54 @@ +/* + * 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 picocep.h + * + * Cepstral Smoothing PU - Header file + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#ifndef PICOCEP_H_ +#define PICOCEP_H_ + +#include "picoos.h" +#include "picodata.h" +#include "picorsrc.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/* ****************************************************************************** + * items related to the generic interface + ********************************************************************************/ +picodata_ProcessingUnit picocep_newCepUnit(picoos_MemoryManager mm, + picoos_Common common, picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, picorsrc_Voice voice); + +#ifdef __cplusplus +} +#endif + +#endif /*PICOCEP_H_*/ diff --git a/pico/lib/picoctrl.c b/pico/lib/picoctrl.c new file mode 100644 index 0000000..5af70e3 --- /dev/null +++ b/pico/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 */ diff --git a/pico/lib/picoctrl.h b/pico/lib/picoctrl.h new file mode 100644 index 0000000..1dfea54 --- /dev/null +++ b/pico/lib/picoctrl.h @@ -0,0 +1,101 @@ +/* + * 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.h + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#ifndef PICOCTRL_H_ +#define PICOCTRL_H_ + +#include "picodefs.h" +#include "picoos.h" +#include "picorsrc.h" +#include "picodata.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +#define PICOCTRL_MAX_PROC_UNITS 25 + +/* temporarily increased for preprocessing +#define PICOCTRL_DEFAULT_ENGINE_SIZE 200000 +*/ +#define PICOCTRL_DEFAULT_ENGINE_SIZE 1000000 + +typedef struct picoctrl_engine * picoctrl_Engine; + +picoos_int16 picoctrl_isValidEngineHandle(picoctrl_Engine this); + +picoctrl_Engine picoctrl_newEngine ( + picoos_MemoryManager mm, + picorsrc_ResourceManager rm, + const picoos_char * voiceName + ); + +void picoctrl_disposeEngine( + picoos_MemoryManager mm, + picorsrc_ResourceManager rm, + picoctrl_Engine * this + ); + +pico_status_t picoctrl_engFeedText( + picoctrl_Engine engine, + picoos_char * text, + picoos_int16 textSize, + picoos_int16 * bytesPut); + +pico_status_t picoctrl_engReset( + picoctrl_Engine engine + ); + +picoos_Common picoctrl_engGetCommon(picoctrl_Engine this); + +picodata_step_result_t picoctrl_engFetchOutputItemBytes( + picoctrl_Engine engine, + picoos_char * buffer, + picoos_int16 bufferSize, + picoos_int16 * bytesReceived +); + +void picoctrl_engResetExceptionManager( + picoctrl_Engine this + ); + + +picodata_step_result_t picoctrl_getLastScheduledPU( + picoctrl_Engine engine + ); + +picodata_step_result_t picoctrl_getLastProducedItemType( + picoctrl_Engine engine + ); + +#ifdef __cplusplus +} +#endif + +#endif /*PICOCTRL_H_*/ diff --git a/pico/lib/picodata.c b/pico/lib/picodata.c new file mode 100644 index 0000000..244e4b6 --- /dev/null +++ b/pico/lib/picodata.c @@ -0,0 +1,1152 @@ +/* + * 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 picodata.c + * + * 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 "picorsrc.h" +#include "picotrns.h" +#include "picodata.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/* we output coefficients as fixed point values */ +#define PICOCEP_OUT_DATA_FORMAT PICODATA_ITEMINFO1_FRAME_PAR_DATA_FORMAT_FIXED + +/* *************************************************************** + * CharBuffer * + *****************************************************************/ + +/* + * method signatures + */ +typedef pico_status_t (* picodata_cbPutItemMethod) (register picodata_CharBuffer this, + const picoos_uint8 *buf, const picoos_uint16 blenmax, + picoos_uint16 *blen); + +typedef pico_status_t (* picodata_cbGetItemMethod) (register picodata_CharBuffer this, + picoos_uint8 *buf, const picoos_uint16 blenmax, + picoos_uint16 *blen, const picoos_uint8 issd); + +typedef pico_status_t (* picodata_cbSubResetMethod) (register picodata_CharBuffer this); +typedef pico_status_t (* picodata_cbSubDeallocateMethod) (register picodata_CharBuffer this, picoos_MemoryManager mm); + +typedef struct picodata_char_buffer +{ + picoos_char *buf; + picoos_uint16 rear; /* next free position to write */ + picoos_uint16 front; /* next position to read */ + picoos_uint16 len; /* empty: len = 0, full: len = size */ + picoos_uint16 size; + + picoos_Common common; + + picodata_cbGetItemMethod getItem; + picodata_cbPutItemMethod putItem; + + picodata_cbSubResetMethod subReset; + picodata_cbSubDeallocateMethod subDeallocate; + void * subObj; +} char_buffer_t; + + +static pico_status_t data_cbPutItem(register picodata_CharBuffer this, + const picoos_uint8 *buf, const picoos_uint16 blenmax, + picoos_uint16 *blen); + +static pico_status_t data_cbGetItem(register picodata_CharBuffer this, + picoos_uint8 *buf, const picoos_uint16 blenmax, + picoos_uint16 *blen, const picoos_uint8 issd); + +pico_status_t picodata_cbReset(register picodata_CharBuffer this) +{ + this->rear = 0; + this->front = 0; + this->len = 0; + if (NULL != this->subObj) { + return this->subReset(this); + } else { + return PICO_OK; + } +} + +/* CharBuffer constructor */ +picodata_CharBuffer picodata_newCharBuffer(picoos_MemoryManager mm, + picoos_Common common, + picoos_objsize_t size) +{ + picodata_CharBuffer this; + + this = (picodata_CharBuffer) picoos_allocate(mm, sizeof(*this)); + PICODBG_DEBUG(("new character buffer, size=%i", size)); + if (NULL == this) { + return NULL; + } + this->buf = picoos_allocate(mm, size); + if (NULL == this->buf) { + picoos_deallocate(mm, (void*) &this); + return NULL; + } + this->size = size; + this->common = common; + + this->getItem = data_cbGetItem; + this->putItem = data_cbPutItem; + + this->subReset = NULL; + this->subDeallocate = NULL; + this->subObj = NULL; + + picodata_cbReset(this); + return this; +} + +void picodata_disposeCharBuffer(picoos_MemoryManager mm, + picodata_CharBuffer *this) +{ + if (NULL != (*this)) { + /* terminate */ + if (NULL != (*this)->subObj) { + (*this)->subDeallocate(*this,mm); + } + picoos_deallocate(mm,(void*)&(*this)->buf); + picoos_deallocate(mm,(void*)this); + } +} + +pico_status_t picodata_cbPutCh(register picodata_CharBuffer this, + picoos_char ch) +{ + if (this->len < this->size) { + this->buf[this->rear++] = ch; + this->rear %= this->size; + this->len++; + return PICO_OK; + } else { + return PICO_EXC_BUF_OVERFLOW; + } +} + + +picoos_int16 picodata_cbGetCh(register picodata_CharBuffer this) +{ + picoos_char ch; + if (this->len > 0) { + ch = this->buf[this->front++]; + this->front %= this->size; + this->len--; + return ch; + } else { + return PICO_EOF; + } +} + +/* *************************************************************** + * items: CharBuffer functions * + *****************************************************************/ + +static pico_status_t data_cbGetItem(register picodata_CharBuffer this, + picoos_uint8 *buf, const picoos_uint16 blenmax, + picoos_uint16 *blen, const picoos_uint8 issd) +{ + picoos_uint16 i; + + if (this->len < PICODATA_ITEM_HEADSIZE) { /* item not in cb? */ + *blen = 0; + if (this->len == 0) { /* is cb empty? */ + PICODBG_DEBUG(("no item to get")); + return PICO_EOF; + } else { /* cb not empty, but not a valid item */ + PICODBG_WARN(("problem getting item, incomplete head, underflow")); + } + return PICO_EXC_BUF_UNDERFLOW; + } + *blen = PICODATA_ITEM_HEADSIZE + (picoos_uint8)(this->buf[((this->front) + + PICODATA_ITEMIND_LEN) % this->size]); + + /* if getting speech data in item */ + if (issd) { + /* check item type */ + if (this->buf[this->front] != PICODATA_ITEM_FRAME) { + PICODBG_WARN(("item type mismatch for speech data: %c", + this->buf[this->front])); + for (i=0; i<*blen; i++) { + this->front++; + this->front %= this->size; + this->len--; + } + *blen = 0; + return PICO_OK; + } + } + + if (*blen > this->len) { /* item in cb not complete? */ + PICODBG_WARN(("problem getting item, incomplete content, underflow; " + "blen=%d, len=%d", *blen, this->len)); + *blen = 0; + return PICO_EXC_BUF_UNDERFLOW; + } + if (blenmax < *blen) { /* buf not large enough? */ + PICODBG_WARN(("problem getting item, overflow")); + *blen = 0; + return PICO_EXC_BUF_OVERFLOW; + } + + /* if getting speech data in item */ + if (issd) { + /* skip item header */ + for (i = 0; i < PICODATA_ITEM_HEADSIZE; i++) { + this->front++; + this->front %= this->size; + this->len--; + } + *blen -= PICODATA_ITEM_HEADSIZE; + } + + /* all ok, now get item (or speech data only) */ + for (i = 0; i < *blen; i++) { + buf[i] = (picoos_uint8)(this->buf[this->front++]); + this->front %= this->size; + this->len--; + } + +#if defined(PICO_DEBUG) + if (issd) { + PICODBG_DEBUG(("got speech data: %d samples", *blen)); + } else { + PICODBG_DEBUG(("got item: %c|%d|%d|%d||", buf[PICODATA_ITEMIND_TYPE], + buf[PICODATA_ITEMIND_INFO1], buf[PICODATA_ITEMIND_INFO2], + buf[PICODATA_ITEMIND_LEN])); + for (i=PICODATA_ITEM_HEADSIZE; i<*blen; i++) { + if (buf[PICODATA_ITEMIND_TYPE] == PICODATA_ITEM_WORDGRAPH) { + PICODBG_DEBUG(("%c", buf[i])); + } else { + PICODBG_DEBUG((" %d", buf[i])); + } + } + } +#endif + + return PICO_OK; +} + +static pico_status_t data_cbPutItem(register picodata_CharBuffer this, + const picoos_uint8 *buf, const picoos_uint16 blenmax, + picoos_uint16 *blen) +{ + picoos_uint16 i; + + if (blenmax < PICODATA_ITEM_HEADSIZE) { /* itemlen not accessible? */ + PICODBG_WARN(("problem putting item, underflow")); + *blen = 0; + return PICO_EXC_BUF_UNDERFLOW; + } + *blen = buf[PICODATA_ITEMIND_LEN] + PICODATA_ITEM_HEADSIZE; + if (*blen > (this->size - this->len)) { /* cb not enough space? */ + PICODBG_WARN(("problem putting item, overflow")); + *blen = 0; + return PICO_EXC_BUF_OVERFLOW; + } + if (*blen > blenmax) { /* item in buf not completely accessible? */ + PICODBG_WARN(("problem putting item, underflow")); + *blen = 0; + return PICO_EXC_BUF_UNDERFLOW; + } + /* all ok, now put complete item */ + +#if defined(PICO_DEBUG) + PICODBG_DEBUG(("putting item: %c|%d|%d|%d||", + buf[PICODATA_ITEMIND_TYPE], + buf[PICODATA_ITEMIND_INFO1], + buf[PICODATA_ITEMIND_INFO2], + buf[PICODATA_ITEMIND_LEN])); + for (i=PICODATA_ITEM_HEADSIZE; i<*blen; i++) { + if (buf[PICODATA_ITEMIND_TYPE] == PICODATA_ITEM_WORDGRAPH) { + PICODBG_DEBUG(("%c", buf[i])); + } else { + PICODBG_DEBUG((" %d", buf[i])); + } + } +#endif + + for (i = 0; i < *blen; i++) { + /* put single byte */ + this->buf[this->rear++] = (picoos_char)buf[i]; + this->rear %= this->size; + this->len++; + } + return PICO_OK; +} + +/*---------------------------------------------------------- + * Names : picodata_cbGetItem + * picodata_cbGetSpeechData + * Function: gets one item from 'this' and writes it on 'blenmax' sized 'buf'. + * gets one item from 'this' and writes the speech data to + * 'blenmax' sized 'buf'. + * Returns : PICO_OK : one item was copied + * PICO_EOF : 'this' is empty; no new items available + * PICO_BUF_UNDERFLOW : 'this' doesn't contain a full/valid item + * PICO_BUF_OVERFLOW : 'buf[blenmax]' too small to hold item + * on return, '*blen' contains the number of bytes written to 'buf' + * ---------------------------------------------------------*/ +pico_status_t picodata_cbGetItem(register picodata_CharBuffer this, + picoos_uint8 *buf, const picoos_uint16 blenmax, + picoos_uint16 *blen) +{ + return this->getItem(this, buf, blenmax, blen, FALSE); +} + +pico_status_t picodata_cbGetSpeechData(register picodata_CharBuffer this, + picoos_uint8 *buf, const picoos_uint16 blenmax, + picoos_uint16 *blen) +{ + + return this->getItem(this, buf, blenmax, blen, TRUE); +} + + +pico_status_t picodata_cbPutItem(register picodata_CharBuffer this, + const picoos_uint8 *buf, const picoos_uint16 blenmax, + picoos_uint16 *blen) +{ + + return this->putItem(this,buf,blenmax,blen); +} + +/* unsafe, just for measuring purposes */ +picoos_uint8 picodata_cbGetFrontItemType(register picodata_CharBuffer this) +{ + return this->buf[this->front]; +} +/* *************************************************************** + * items: support function * + *****************************************************************/ + +picoos_uint8 is_valid_itemtype(const picoos_uint8 ch) { + switch (ch) { + case PICODATA_ITEM_WSEQ_GRAPH: + case PICODATA_ITEM_TOKEN: + case PICODATA_ITEM_WORDGRAPH: + case PICODATA_ITEM_WORDINDEX: + case PICODATA_ITEM_WORDPHON: + case PICODATA_ITEM_SYLLPHON: + case PICODATA_ITEM_BOUND: + case PICODATA_ITEM_PUNC: + case PICODATA_ITEM_CMD: + case PICODATA_ITEM_PHONE: + case PICODATA_ITEM_FRAME: + case PICODATA_ITEM_FRAME_PAR: + return TRUE; + break; + case PICODATA_ITEM_OTHER: + default: + break; + } + PICODBG_WARN(("item type problem: %c", ch)); + return FALSE; +} + +picoos_uint8 picodata_is_valid_itemhead(const picodata_itemhead_t *head) { + if ((NULL != head) && is_valid_itemtype(head->type)) { + return TRUE; + } else { + PICODBG_WARN(("item header problem")); + return FALSE; + } +} + +/* ***************************************************/ + + +pico_status_t picodata_get_itemparts_nowarn( + const picoos_uint8 *buf, const picoos_uint16 blenmax, + picodata_itemhead_t *head, picoos_uint8 *content, + const picoos_uint16 clenmax, picoos_uint16 *clen) +{ + if (blenmax >= PICODATA_ITEM_HEADSIZE) { + head->type = buf[PICODATA_ITEMIND_TYPE]; + head->info1 = buf[PICODATA_ITEMIND_INFO1]; + head->info2 = buf[PICODATA_ITEMIND_INFO2]; + head->len = buf[PICODATA_ITEMIND_LEN]; + *clen = head->len; + if (blenmax >= (*clen + PICODATA_ITEM_HEADSIZE)) { + if (clenmax >= head->len) { + picoos_uint16 i; + for (i=0; ilen; i++) { + content[i] = buf[PICODATA_ITEM_HEADSIZE+i]; + } + return PICO_OK; + } + *clen = 0; + return PICO_EXC_BUF_OVERFLOW; + } + } + *clen = 0; + return PICO_EXC_BUF_UNDERFLOW; +} + +pico_status_t picodata_get_itemparts( + const picoos_uint8 *buf, const picoos_uint16 blenmax, + picodata_itemhead_t *head, picoos_uint8 *content, + const picoos_uint16 clenmax, picoos_uint16 *clen) +{ + pico_status_t status = picodata_get_itemparts_nowarn(buf,blenmax,head,content,clenmax,clen); + if (PICO_EXC_BUF_OVERFLOW == status) { + PICODBG_WARN(("problem getting item, overflow")); + } else if (PICO_EXC_BUF_UNDERFLOW == status) { + PICODBG_WARN(("problem getting item, overflow")); + } + return status; +} +pico_status_t picodata_put_itemparts(const picodata_itemhead_t *head, + const picoos_uint8 *content, const picoos_uint16 clenmax, + picoos_uint8 *buf, const picoos_uint16 blenmax, picoos_uint16 *blen) +{ + *blen = head->len + PICODATA_ITEM_HEADSIZE; + if (blenmax >= *blen) { + if (clenmax >= head->len) { + picoos_uint16 i; + buf[PICODATA_ITEMIND_TYPE] = head->type; + buf[PICODATA_ITEMIND_INFO1] = head->info1; + buf[PICODATA_ITEMIND_INFO2] = head->info2; + buf[PICODATA_ITEMIND_LEN] = head->len; + for (i=0; ilen; i++) { + buf[PICODATA_ITEM_HEADSIZE+i] = content[i]; + } + return PICO_OK; + } + PICODBG_WARN(("problem putting item, underflow")); + *blen = 0; + return PICO_EXC_BUF_UNDERFLOW; + } + PICODBG_WARN(("problem putting item, overflow")); + *blen = 0; + return PICO_EXC_BUF_OVERFLOW; +} + +pico_status_t picodata_get_iteminfo( + picoos_uint8 *buf, const picoos_uint16 blenmax, + picodata_itemhead_t *head, picoos_uint8 **content) { + if (blenmax >= PICODATA_ITEM_HEADSIZE) { + head->type = buf[PICODATA_ITEMIND_TYPE]; + head->info1 = buf[PICODATA_ITEMIND_INFO1]; + head->info2 = buf[PICODATA_ITEMIND_INFO2]; + head->len = buf[PICODATA_ITEMIND_LEN]; + if (head->len == 0) { + *content = NULL; + } else { + *content = &buf[PICODATA_ITEM_HEADSIZE]; + } + return PICO_OK; + } + return PICO_EXC_BUF_UNDERFLOW; +} + +pico_status_t picodata_copy_item(const picoos_uint8 *inbuf, + const picoos_uint16 inlenmax, picoos_uint8 *outbuf, + const picoos_uint16 outlenmax, picoos_uint16 *numb) +{ + if (picodata_is_valid_item(inbuf, inlenmax)) { + *numb = PICODATA_ITEM_HEADSIZE + inbuf[PICODATA_ITEMIND_LEN]; + } else { + *numb = 0; + } + if (*numb > 0) { + if (outlenmax >= inlenmax) { + picoos_uint16 i; + for (i=0; i<*numb; i++) { + outbuf[i] = inbuf[i]; + } + return PICO_OK; + } else { + PICODBG_WARN(("buffer problem, out: %d > in: %d", outlenmax, inlenmax)); + *numb = 0; + return PICO_EXC_BUF_OVERFLOW; + } + } else { + PICODBG_WARN(("item problem in inbuf")); + return PICO_ERR_OTHER; + } +} + +pico_status_t picodata_set_iteminfo1(picoos_uint8 *buf, + const picoos_uint16 blenmax, const picoos_uint8 info) { + if (PICODATA_ITEMIND_INFO1 < blenmax) { + buf[PICODATA_ITEMIND_INFO1] = info; + return PICO_OK; + } else + return PICO_EXC_BUF_UNDERFLOW; +} + +pico_status_t picodata_set_iteminfo2(picoos_uint8 *buf, + const picoos_uint16 blenmax, const picoos_uint8 info) { + if (PICODATA_ITEMIND_INFO2 < blenmax) { + buf[PICODATA_ITEMIND_INFO2] = info; + return PICO_OK; + } else + return PICO_EXC_BUF_UNDERFLOW; +} + +/* sets the len field in the header contained in the item in buf; + return values: + PICO_OK <- all ok + PICO_EXC_BUF_UNDERFLOW <- underflow in buf +*/ +pico_status_t picodata_set_itemlen(picoos_uint8 *buf, + const picoos_uint16 blenmax, const picoos_uint8 len) { + if (PICODATA_ITEMIND_LEN < blenmax) { + buf[PICODATA_ITEMIND_LEN] = len; + return PICO_OK; + } else + return PICO_EXC_BUF_UNDERFLOW; +} + +picoos_uint8 picodata_is_valid_item(const picoos_uint8 *item, + const picoos_uint16 ilenmax) +{ + if (ilenmax >= PICODATA_ITEM_HEADSIZE) { + picodata_itemhead_t head; + head.type = item[0]; + head.info1 = item[1]; + head.info2 = item[2]; + head.len = item[3]; + if ((ilenmax >= (head.len + PICODATA_ITEM_HEADSIZE)) && + picodata_is_valid_itemhead(&head)) + { + return TRUE; + } + } + return FALSE; +} + +/* *************************************************************** + * ProcessingUnit * + *****************************************************************/ +picoos_uint16 picodata_get_default_buf_size (picodata_putype_t puType) +{ + return (PICODATA_PUTYPE_TEXT == puType) ? PICODATA_BUFSIZE_TEXT + : (PICODATA_PUTYPE_TOK == puType) ? PICODATA_BUFSIZE_TOK + : (PICODATA_PUTYPE_PR == puType) ? PICODATA_BUFSIZE_PR + : (PICODATA_PUTYPE_PR == puType) ? PICODATA_BUFSIZE_PR + : (PICODATA_PUTYPE_WA == puType) ? PICODATA_BUFSIZE_WA + : (PICODATA_PUTYPE_SA == puType) ? PICODATA_BUFSIZE_SA + : (PICODATA_PUTYPE_ACPH == puType) ? PICODATA_BUFSIZE_ACPH + : (PICODATA_PUTYPE_SPHO == puType) ? PICODATA_BUFSIZE_SPHO + : (PICODATA_PUTYPE_PAM == puType) ? PICODATA_BUFSIZE_PAM + : (PICODATA_PUTYPE_CEP == puType) ? PICODATA_BUFSIZE_CEP + : (PICODATA_PUTYPE_SIG == puType) ? PICODATA_BUFSIZE_SIG + : (PICODATA_PUTYPE_SINK == puType) ? PICODATA_BUFSIZE_SINK + : PICODATA_BUFSIZE_DEFAULT; +} + + +typedef struct simple_pu_data +{ + picorsrc_Voice voice; +} simple_pu_data_t; + +static pico_status_t puSimpleInitialize (register picodata_ProcessingUnit this) { + return PICO_OK; +} + +static pico_status_t puSimpleTerminate (register picodata_ProcessingUnit this) { + return PICO_OK; +} + +static picodata_step_result_t puSimpleStep (register picodata_ProcessingUnit this, + picoos_int16 mode, + picoos_uint16 * numBytesOutput) { + picoos_int16 ch; + picoos_int16 result = PICO_OK; + mode = mode; /*PP 13.10.08 : fix warning "var not used in this function"*/ + *numBytesOutput = 0; + while ((result == PICO_OK) && (ch = picodata_cbGetCh(this->cbIn)) != PICO_EOF) { + result = picodata_cbPutCh(this->cbOut,(picoos_char) ch); + (*numBytesOutput)++; + } + if (PICO_OK != result) { + (*numBytesOutput)--; + } + if (PICO_OK == result) { + return PICODATA_PU_IDLE; + } else { + return PICODATA_PU_ERROR; + } +} + + +picodata_ProcessingUnit picodata_newProcessingUnit( + picoos_MemoryManager mm, + picoos_Common common, + picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, + picorsrc_Voice voice) +{ + picodata_ProcessingUnit this = (picodata_ProcessingUnit) picoos_allocate(mm, sizeof(*this)); + if (this == NULL) { + picoos_emRaiseException(common->em,PICO_EXC_OUT_OF_MEM,NULL,NULL); + return NULL; + } + this->common = common; + this->cbIn = cbIn; + this->cbOut = cbOut; + this->voice = voice; + this->initialize = puSimpleInitialize; + this->terminate = puSimpleTerminate; + this->step = puSimpleStep; + this->subDeallocate = NULL; + this->subObj = NULL; + return this; +} + +void picodata_disposeProcessingUnit( + picoos_MemoryManager mm, + picodata_ProcessingUnit * this) +{ + if (NULL != (*this)) { + /* terminate */ + if (NULL != (*this)->subObj) { + (*this)->subDeallocate(*this,mm); + } + picoos_deallocate(mm,(void *)this); + } + +} + + +picodata_CharBuffer picodata_getCbIn(picodata_ProcessingUnit this) +{ + if (NULL == this) { + picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL); + return NULL; + } else { + return this->cbIn; + } +} + +picodata_CharBuffer picodata_getCbOut(picodata_ProcessingUnit this) +{ + if (NULL == this) { + picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL); + return NULL; + } else { + return this->cbOut; + } +} + +pico_status_t picodata_setCbIn(picodata_ProcessingUnit this, picodata_CharBuffer cbIn) +{ + if (NULL == this) { + picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL); + return PICO_ERR_OTHER; + } else { + this->cbIn = cbIn; + return PICO_OK; + } + +} + +pico_status_t picodata_setCbOut(picodata_ProcessingUnit this, picodata_CharBuffer cbOut) +{ + if (NULL == this) { + picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL); + return PICO_ERR_OTHER; + } else { + this->cbOut = cbOut; + return PICO_OK; + } +} + + +/* *************************************************************** + * auxiliary functions * + *****************************************************************/ + +static void transDurUniform( + picoos_uint8 frame_duration_exp, /* 2's exponent of frame duration in ms, e.g. 2 for 4ms, 3 for 8ms */ + picoos_int8 array_length, + picoos_uint8 * inout, + picoos_int16 inputdur, /* input duration in ms */ + picoos_int16 targetdur, /* target duration in ms */ + picoos_int16 * restdur /* in/out, rest in ms */ + ) +{ + picoos_int8 i; + picoos_int32 fact, rest; + + /* calculate rest and factor in number of frames (in PICODATA_PICODATA_PRECISION) */ + rest = (*restdur) << (PICODATA_PRECISION - frame_duration_exp); + fact = (targetdur << (PICODATA_PRECISION - frame_duration_exp)) / inputdur; + + for (i = 0; i < array_length; i++) { + rest += fact * inout[i]; + /* instead of rounding, we carry the rest to the next state */ + inout[i] = rest >> PICODATA_PRECISION; + rest -= inout[i] << PICODATA_PRECISION; + } + (*restdur) = rest >> (PICODATA_PRECISION - frame_duration_exp); +} + +static void transDurWeighted( + picoos_uint8 frame_duration_exp, /* 2's exponent of frame duration in ms, e.g. 2 for 4ms, 3 for 8ms */ + picoos_int8 array_length, + picoos_uint8 * inout, + const picoos_uint16 * weight, /* integer weights */ + picoos_int16 inputdur, /* input duration in ms */ + picoos_int16 targetdur, /* target duration in ms */ + picoos_int16 * restdur /* in/out, rest in ms */ + ) +{ + picoos_int8 i; + picoos_int32 fact, rest, out, weighted_sum; + + /* calculate rest and factor in number of frames (in PICODATA_PICODATA_PRECISION) */ + rest = (*restdur) << (PICODATA_PRECISION - frame_duration_exp); + weighted_sum = 0; + for (i=0; i < array_length; i++) { + weighted_sum += inout[i] * weight[i]; + } + if (0 == weighted_sum) { + transDurUniform(frame_duration_exp,array_length,inout,inputdur,targetdur,restdur); + return; + } + /* get the additive change factor in PICODATA_PRECISION: */ + if (targetdur > inputdur) { + fact = ((targetdur - inputdur) << (PICODATA_PRECISION-frame_duration_exp))/ weighted_sum; + } else { + fact = -((inputdur - targetdur) << (PICODATA_PRECISION-frame_duration_exp))/ weighted_sum; + } + + /* input[i] * fact * weight[i] is the additive modification in PICODATA_PRECISION */ + for (i=0; i < array_length; i++) { + rest += fact * inout[i] * weight[i]; + /* instead of rounding, we carry the rest to the next state */ + out = inout[i] + (rest >> PICODATA_PRECISION); + if (out < 0) { + out = 0; + } + rest -= ((out-inout[i]) << PICODATA_PRECISION); + inout[i] = out; + } + (*restdur) = rest >> (PICODATA_PRECISION - frame_duration_exp); +} + + + +void picodata_transformDurations( + picoos_uint8 frame_duration_exp, + picoos_int8 array_length, + picoos_uint8 * inout, + const picoos_uint16 * weight, /* integer weights */ + picoos_int16 mintarget, /* minimum target duration in ms */ + picoos_int16 maxtarget, /* maximum target duration in ms */ + picoos_int16 facttarget, /* factor to be multiplied with original length to get the target + the factor is fixed-point with PICODATA_PRECISION PICODATA_PRECISION, i.e. + the factor as float would be facttarget / PICODATA_PRECISION_FACT + if factor is 0, only min/max are considered */ + picoos_int16 * dur_rest /* in/out, rest in ms */ + ) +{ + picoos_int32 inputdur, targetdur; + picoos_int8 i; + + /* find the original duration in ms */ + inputdur = 0; + for (i=0; i < array_length; i++) { + inputdur += inout[i]; + } + + PICODBG_TRACE(("######## transforming duration fact=%i, limits = [%i,%i] (input frames: %i)",facttarget,mintarget,maxtarget, inputdur)); + + inputdur <<= frame_duration_exp; + + /* find the target duration */ + if (facttarget) { + targetdur = (facttarget * inputdur + PICODATA_PREC_HALF) >> PICODATA_PRECISION; + } else { + targetdur = inputdur; + } + + /* we need to modify input if there is an explicit factor or input is not in the target range */ + if (facttarget || (targetdur < mintarget) || (maxtarget < targetdur)) { + /* make sure we are in the limits */ + if (targetdur < mintarget) { + targetdur = mintarget; + } else if (maxtarget < targetdur) { + targetdur = maxtarget; + } + /* perform modification */ + if (NULL == weight) { + transDurUniform(frame_duration_exp,array_length,inout,inputdur,targetdur,dur_rest); + } else { + transDurWeighted(frame_duration_exp,array_length,inout,weight,inputdur,targetdur,dur_rest); + } + } +} + + + +extern picoos_uint8 picodata_getPuTypeFromExtension(picoos_uchar * filename, picoos_bool input) +{ + if (input) { + if (picoos_has_extension(filename, PICODATA_PUTYPE_TOK_INPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_TOK; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_PR_INPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_PR; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_WA_INPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_WA; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_SA_INPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_SA; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_ACPH_INPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_ACPH; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_SPHO_INPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_SPHO; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_PAM_INPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_PAM; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_CEP_INPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_CEP; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_SIG_INPUT_EXTENSION) || + picoos_has_extension(filename, PICODATA_PUTYPE_WAV_INPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_SIG; + } + else { + return PICODATA_ITEMINFO2_CMD_TO_UNKNOWN; + } + } + else { + if (picoos_has_extension(filename, PICODATA_PUTYPE_TOK_OUTPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_TOK; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_PR_OUTPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_PR; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_WA_OUTPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_WA; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_SA_OUTPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_SA; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_ACPH_OUTPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_ACPH; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_SPHO_OUTPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_SPHO; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_PAM_OUTPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_PAM; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_CEP_OUTPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_CEP; + } + else if (picoos_has_extension(filename, PICODATA_PUTYPE_SIG_OUTPUT_EXTENSION) || + picoos_has_extension(filename, PICODATA_PUTYPE_WAV_OUTPUT_EXTENSION)) { + return PICODATA_ITEMINFO2_CMD_TO_SIG; + } + else { + return PICODATA_ITEMINFO2_CMD_TO_UNKNOWN; + } + } + return PICODATA_ITEMINFO2_CMD_TO_UNKNOWN; +} + + + + +/** + * + * @param transducer + * @param common + * @param xsampa_parser + * @param svoxpa_parser + * @param xsampa2svoxpa_mapper + * @param inputPhones + * @param alphabet + * @param outputPhoneIds + * @param maxOutputPhoneIds + * @return + */ +pico_status_t picodata_mapPAStrToPAIds(picotrns_SimpleTransducer transducer, + picoos_Common common, picokfst_FST xsampa_parser, + picokfst_FST svoxpa_parser, picokfst_FST xsampa2svoxpa_mapper, + picoos_uchar * inputPhones, picoos_uchar * alphabet, + picoos_uint8 * outputPhoneIds, picoos_int32 maxOutputPhoneIds) +{ + pico_status_t status = PICO_OK; + if (picoos_strcmp(alphabet, PICODATA_XSAMPA) == 0) { + if ((NULL != xsampa_parser) && (NULL != xsampa2svoxpa_mapper)) { + picotrns_stInitialize(transducer); + status = picotrns_stAddWithPlane(transducer, inputPhones, + PICOKFST_PLANE_ASCII); + if (PICO_OK != status) { + picoos_emRaiseWarning(common->em, status, NULL, + (picoos_char *) "phoneme sequence too long (%s)", + inputPhones); + } else { + status = picotrns_stTransduce(transducer, xsampa_parser); + if (PICO_OK != status) { + picoos_emRaiseWarning(common->em, status, NULL, + (picoos_char *) "not recognized as xsampa (%s)", + inputPhones); + } else { + status = picotrns_stTransduce(transducer, xsampa2svoxpa_mapper); + if (PICO_OK != status) { + picoos_emRaiseWarning(common->em, status, NULL, + (picoos_char *) "illeagal phoneme sequence (%s)", + inputPhones); + } else { + status = picotrns_stGetSymSequence(transducer, outputPhoneIds, + maxOutputPhoneIds); + } + } + } + return status; + } + } else if (picoos_strcmp(alphabet, PICODATA_SVOXPA) == 0) { + if ((NULL != svoxpa_parser)) { + picotrns_stInitialize(transducer); + status = picotrns_stAddWithPlane(transducer, inputPhones, + PICOKFST_PLANE_ASCII); + if (PICO_OK == status) { + status = picotrns_stTransduce(transducer, svoxpa_parser); + } + if (PICO_OK == status) { + status = picotrns_stGetSymSequence(transducer, outputPhoneIds, + maxOutputPhoneIds); + } + return status; + } + } + picoos_strlcpy(outputPhoneIds, (picoos_char *) "", maxOutputPhoneIds); + picoos_emRaiseWarning(common->em, PICO_EXC_NAME_ILLEGAL, NULL, + (picoos_char *) "alphabet not supported (%s)", alphabet); + return PICO_EXC_NAME_ILLEGAL; + +} + +#if defined (PICO_DEBUG) +/* *************************************************************** + * For Debugging only * + *****************************************************************/ + + +/* put string representation of 'itemtype' into 'str' (allocated size 'strsize') + * return 'str' */ +static picoos_char * data_itemtype_to_string(const picoos_uint8 itemtype, + picoos_char * str, picoos_uint16 strsize) +{ + picoos_char * tmpstr; + switch (itemtype) { + case PICODATA_ITEM_BOUND: + tmpstr = (picoos_char *)"BOUND"; + break; + case PICODATA_ITEM_FRAME_PAR: + tmpstr = (picoos_char *)"FRAME_PAR"; + break; + case PICODATA_ITEM_PHONE: + tmpstr = (picoos_char *)"PHONE"; + break; + case PICODATA_ITEM_CMD: + tmpstr = (picoos_char *)"CMD"; + break; + case PICODATA_ITEM_ERR: + tmpstr = (picoos_char *)"ERR"; + break; + case PICODATA_ITEM_FRAME: + tmpstr = (picoos_char *)"FRAME"; + break; + case PICODATA_ITEM_OTHER: + tmpstr = (picoos_char *)"OTHER"; + break; + case PICODATA_ITEM_PUNC: + tmpstr = (picoos_char *)"PUNC"; + break; + case PICODATA_ITEM_SYLLPHON: + tmpstr = (picoos_char *)"SYLLPHON"; + break; + case PICODATA_ITEM_WORDGRAPH: + tmpstr = (picoos_char *)"WORDGRAPH"; + break; + case PICODATA_ITEM_WORDINDEX: + tmpstr = (picoos_char *)"WORDINDEX"; + break; + case PICODATA_ITEM_WORDPHON: + tmpstr = (picoos_char *)"WORDPHON"; + break; + case PICODATA_ITEM_WSEQ_GRAPH: + tmpstr = (picoos_char *)"WSEQ_GRAPH"; + break; + default: + tmpstr = (picoos_char *)"UNKNOWN"; + break; + } + picopal_slprintf((picopal_char *) str, strsize, (picopal_char *)"%s", + tmpstr); + return str; +} + + +picoos_char * picodata_head_to_string(const picodata_itemhead_t *head, + picoos_char * str, picoos_uint16 strsize) +{ + picoos_uint16 typelen; + + if (NULL == head) { + picoos_strlcpy(str,(picoos_char *)"[head is NULL]",strsize); + } else { + data_itemtype_to_string(head->type, str, strsize); + typelen = picoos_strlen(str); + picopal_slprintf((picopal_char *) str+typelen, strsize-typelen, + (picopal_char *)"|%c|%c|%i", head->info1, head->info2, + head->len); + } + + return str; +} + +void picodata_info_item(const picoknow_KnowledgeBase kb, + const picoos_uint8 *pref6ch, + const picoos_uint8 *item, + const picoos_uint16 itemlenmax, + const picoos_char *filterfn) +{ +#define SA_USE_PHST 1 + picoos_uint16 i; + picoos_uint8 ch; + + if ((itemlenmax < 4) || (item == NULL)) { + PICODBG_INFO_MSG(("invalid item\n")); + } + + /* first 6 char used for prefix */ + PICODBG_INFO_MSG_F(filterfn, ("%6s(", pref6ch)); + + /* type */ + ch = item[0]; + if ((32 <= ch) && (ch < 127)) { + PICODBG_INFO_MSG_F(filterfn, ("'%c',", ch)); + } else { + PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); + } + /* info1 */ + ch = item[1]; + if ((32 <= ch) && (ch < 127)) + switch (item[0]) { + case PICODATA_ITEM_PUNC: + case PICODATA_ITEM_BOUND: + case PICODATA_ITEM_CMD: + case PICODATA_ITEM_TOKEN: + case PICODATA_ITEM_FRAME_PAR: + PICODBG_INFO_MSG_F(filterfn, ("'%c',", ch)); + break; + default: + PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); + } + else + PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); + + /* info2 */ + ch = item[2]; + if ((32 <= ch) && (ch < 127)) + switch (item[0]) { + case PICODATA_ITEM_PUNC: + case PICODATA_ITEM_BOUND: + case PICODATA_ITEM_CMD: + case PICODATA_ITEM_WORDPHON: + case PICODATA_ITEM_SYLLPHON: + PICODBG_INFO_MSG_F(filterfn, ("'%c',", ch)); + break; + default: + PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); + } + else + PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); + + /* len */ + ch = item[3]; + PICODBG_INFO_MSG_F(filterfn, ("%3d)", ch)); + + for (i = 0; i < ch; i++) { + if ((item[0] == PICODATA_ITEM_WSEQ_GRAPH) || + (item[0] == PICODATA_ITEM_TOKEN) || + (item[0] == PICODATA_ITEM_WORDGRAPH) || + ((item[0] == PICODATA_ITEM_CMD) && !((item[1] == PICODATA_ITEMINFO1_CMD_SPEED) || + (item[1] == PICODATA_ITEMINFO1_CMD_PITCH) || + (item[1] == PICODATA_ITEMINFO1_CMD_VOLUME) || + (item[1] == PICODATA_ITEMINFO1_CMD_SPELL) || + (item[1] == PICODATA_ITEMINFO1_CMD_SIL)))) { + PICODBG_INFO_MSG_F(filterfn, ("%c", item[4 + i])); + } else { + PICODBG_INFO_MSG_F(filterfn, ("%4d", item[4 + i])); + } + } + +#if defined (SA_USE_PHST) + { +#include "picokdbg.h" + picoos_uint8 j; + picokdbg_Dbg kdbg; + kdbg = picokdbg_getDbg(kb); + + if ((item[0] == PICODATA_ITEM_WORDPHON) || + (item[0] == PICODATA_ITEM_SYLLPHON) || + ((item[0] == PICODATA_ITEM_CMD) && (item[1] == PICODATA_ITEMINFO1_CMD_PHONEME))) { + if (picokdbg_getPhoneSym(kdbg, item[4])) { + PICODBG_INFO_MSG_F(filterfn, (" ")); + for (j = 0; j < item[3]; j++) { + PICODBG_INFO_MSG_F(filterfn, ("%s", + picokdbg_getPhoneSym(kdbg, item[4 + j]))); + } + } + } + } +#endif + + PICODBG_INFO_MSG_F(filterfn, ("\n")); +} + + +#endif /* PICO_DEBUG */ + +#ifdef __cplusplus +} +#endif + + +/* picodata.c end */ diff --git a/pico/lib/picodata.h b/pico/lib/picodata.h new file mode 100644 index 0000000..637a3ff --- /dev/null +++ b/pico/lib/picodata.h @@ -0,0 +1,643 @@ +/* + * 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 picodata.h + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +#ifndef PICODATA_H_ +#define PICODATA_H_ + +#include "picodefs.h" +#include "picoos.h" +#include "picotrns.h" +#include "picokfst.h" +#include "picorsrc.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* *************************************************************** + * Constants * + *****************************************************************/ + +#define PICODATA_MAX_ITEMS_PER_PHRASE 30 + +/** + * @addtogroup picodata + * Pico Data : Item Format \n + * + The item header is identical for all item types and PUs. Item types + that are not handled by a PU are copied. + + Item Header structure\n + --------------------- + - Byte Content + - 0x00 item type + - 0x01 item info 1 + - 0x02 item info 2 + - 0x03 item length in bytes (not including the header) + + depending on the item type/info, a specific subheader may follow + (included in length) +*/ + +/* item header fields (tmp.: use item functions below to acces header fields */ +#define PICODATA_ITEMIND_TYPE 0 +#define PICODATA_ITEMIND_INFO1 1 +#define PICODATA_ITEMIND_INFO2 2 +#define PICODATA_ITEMIND_LEN 3 + +/* *************************************************************** + * CharBuffer * + *****************************************************************/ +typedef struct picodata_char_buffer * picodata_CharBuffer; + +picodata_CharBuffer picodata_newCharBuffer(picoos_MemoryManager mm, + picoos_Common common, picoos_objsize_t size); + +void picodata_disposeCharBuffer(picoos_MemoryManager mm, + picodata_CharBuffer * this); + +/* should not be used for PUs but only for feeding the initial cb */ +pico_status_t picodata_cbPutCh(register picodata_CharBuffer this, picoos_char ch); + +/* should not be used for PUs other than first PU in the chain (picotok) */ +picoos_int16 picodata_cbGetCh(register picodata_CharBuffer this); + +/* reset cb (as if after newCharBuffer) */ +pico_status_t picodata_cbReset (register picodata_CharBuffer this); + +/* ** CharBuffer item functions, cf. below in items section ****/ + +/* *************************************************************** + * items * + *****************************************************************/ + +/* item header size */ +#define PICODATA_ITEM_HEADSIZE 4 + +typedef struct picodata_itemhead +{ + picoos_uint8 type; + picoos_uint8 info1; + picoos_uint8 info2; + picoos_uint8 len; +} picodata_itemhead_t; + + +/* -------------- System wide defines referred to by items -------- */ +/* ---- These maybe better stored in a knowledge module/resoruce*/ +#define PICODATA_ACC0 '\x30' /* 48 '0' */ +#define PICODATA_ACC1 '\x31' /* 49 '1' */ +#define PICODATA_ACC2 '\x32' /* 50 '2' */ +#define PICODATA_ACC3 '\x33' /* 51 '3' */ +#define PICODATA_ACC4 '\x34' /* 52 '4' */ + +/* reserved for future use: + * user-imposed Part-Of-Speech ids for user lexica and phoneme tags + * These values should be applied BEFORE POS-disambiguation. The POS lingware either assigns the same + * ids to corresponding internal unique or composed POS or else the POS-D will consider these values + * "default" */ +#define PICODATA_POS_XNPR 20 +#define PICODATA_POS_XN 21 +#define PICODATA_POS_XV 22 +#define PICODATA_POS_XA 23 +#define PICODATA_POS_XADV 24 +#define PICODATA_POS_XX 25 + +/* ------------------------- item types ---------------------------- */ +/* new item types, info1, info2 to be defined during PU development */ +/* make sure this stays in sync with "is_valid_itemtype" function */ +#define PICODATA_ITEM_WSEQ_GRAPH '\x73' /* 115, 's' */ +#define PICODATA_ITEM_TOKEN '\x74' /* 116 't' */ +#define PICODATA_ITEM_WORDGRAPH '\x67' /* 103 'g' */ +#define PICODATA_ITEM_WORDINDEX '\x69' /* 105 'i' */ +#define PICODATA_ITEM_WORDPHON '\x77' /* 119 'w' */ +#define PICODATA_ITEM_SYLLPHON '\x79' /* 121 'y' */ +#define PICODATA_ITEM_BOUND '\x62' /* 98 'b' */ +/* #define PICODATA_ITEM_BOUND_DUR '\x64' */ /* 100 'd' */ /* duration-constrained bound */ +#define PICODATA_ITEM_PUNC '\x70' /* 112 'p' */ +#define PICODATA_ITEM_CMD '\x63' /* 99 'c' */ +#define PICODATA_ITEM_PHONE '\x68' /* 104 'h' */ /*reserved for PAM*/ +#define PICODATA_ITEM_FRAME_PAR '\x6b' /* 107 'k' */ /*reserved for CEP*/ +#define PICODATA_ITEM_FRAME '\x66' /* 102 'f' */ /*reserved for SIG*/ +#define PICODATA_ITEM_OTHER '\x6f' /* 111 'o' */ +#define PICODATA_ITEM_ERR '\x00' /* 0 '^@' */ + +/* generic iteminfo1 */ +#define PICODATA_ITEMINFO1_ERR '\x00' /* 0 '^@' */ /* error state */ +#define PICODATA_ITEMINFO1_NA '\x01' /* 1 '^A' */ /* not applicable */ + +/* generic iteminfo2 */ +#define PICODATA_ITEMINFO2_ERR '\x00' /* 0 '^@' */ /* error state */ +#define PICODATA_ITEMINFO2_NA '\x01' /* 1 '^A' */ /* not applicable */ + +/* ------------------------- PUNC item type ---------------------------- */ +/* iteminfo1 */ +#define PICODATA_ITEMINFO1_PUNC_SENTEND '\x73' /* 115 's' */ +#define PICODATA_ITEMINFO1_PUNC_PHRASEEND '\x70' /* 112 'p' */ +#define PICODATA_ITEMINFO1_PUNC_FLUSH '\x66' /* 102 'f' */ +/* iteminfo2 */ +#define PICODATA_ITEMINFO2_PUNC_SENT_T '\x74' /* 116 't' */ +#define PICODATA_ITEMINFO2_PUNC_SENT_Q '\x71' /* 113 'q' */ +#define PICODATA_ITEMINFO2_PUNC_SENT_E '\x65' /* 101 'e' */ +#define PICODATA_ITEMINFO2_PUNC_PHRASE '\x70' /* 112 'p' */ +#define PICODATA_ITEMINFO2_PUNC_PHRASE_FORCED '\x66' /* 102 'f' */ +/* len for PUNC item is ALWAYS = 0 */ +/* ------------------------- BOUND item type ---------------------------- */ +/* iteminfo1 : phrase strength*/ +#define PICODATA_ITEMINFO1_BOUND_SBEG '\x62' /* 98 'b', at sentence begin */ +#define PICODATA_ITEMINFO1_BOUND_SEND '\x73' /* 115 's', at sentence end */ +#define PICODATA_ITEMINFO1_BOUND_TERM '\x74' /* 116 't', replaces a flush */ +#define PICODATA_ITEMINFO1_BOUND_PHR0 '\x30' /* 48 '0', no break, no item */ +#define PICODATA_ITEMINFO1_BOUND_PHR1 '\x31' /* 49 '1', pri. phrase bound. */ +#define PICODATA_ITEMINFO1_BOUND_PHR2 '\x32' /* 50 '2', short break */ +#define PICODATA_ITEMINFO1_BOUND_PHR3 '\x33' /* 51 '3', sec. phr. bound., no break*/ +/* iteminfo2 : phrase type*/ +#define PICODATA_ITEMINFO2_BOUNDTYPE_P '\x50' /* 80 'P' */ +#define PICODATA_ITEMINFO2_BOUNDTYPE_T '\x54' /* 84 'T' */ +#define PICODATA_ITEMINFO2_BOUNDTYPE_Q '\x51' /* 81 'Q' */ +#define PICODATA_ITEMINFO2_BOUNDTYPE_E '\x45' /* 69 'E' */ +/* len for BOUND item is ALWAYS = 0 */ +/* ------------------------- CMD item type ---------------------------- */ +/* iteminfo1 */ +#define PICODATA_ITEMINFO1_CMD_FLUSH 'f' /* 102 flush command (all PUs)*/ +#define PICODATA_ITEMINFO1_CMD_PLAY 'p' /* 112 play command : PU in info 2 will read items from file-->Filename in item content.*/ +#define PICODATA_ITEMINFO1_CMD_SAVE 's' /* 115 save command : PU in info 2 will save items to file-->Filename in item content.*/ +#define PICODATA_ITEMINFO1_CMD_UNSAVE 'u' /* 117 save command : PU in info 2 will stop saving items to file*/ +#define PICODATA_ITEMINFO1_CMD_PROSDOMAIN 'd' /* 100 prosody domain : domain type in info 2, domain name in item content */ +#define PICODATA_ITEMINFO1_CMD_SPELL 'e' /* 101 spell command : info 2 contains start/stop info, + spell type/pause len as little endian uint16 in item content */ +#define PICODATA_ITEMINFO1_CMD_IGNSIG 'i' /* ignore signal command : info 2 contains start/stop info */ +#define PICODATA_ITEMINFO1_CMD_PHONEME 'o' /* phoneme command : info 2 contains start/stop info, phonemes in item content */ +#define PICODATA_ITEMINFO1_CMD_IGNORE 'I' /* ignore text command : info 2 contains start/stop info */ +#define PICODATA_ITEMINFO1_CMD_SIL 'z' /* silence command : info 2 contains type of silence; + silence duration as little endian uint16 in item content */ +#define PICODATA_ITEMINFO1_CMD_CONTEXT 'c' /* context command : context name in item content */ +#define PICODATA_ITEMINFO1_CMD_VOICE 'v' /* context command : voice name in item content */ +#define PICODATA_ITEMINFO1_CMD_MARKER 'm' /* marker command : marker name in item content */ +#define PICODATA_ITEMINFO1_CMD_PITCH 'P' /* 80 pitch command : abs/rel info in info 2; pitch level as little endian + uint16 in item content; relative value is in promille */ +#define PICODATA_ITEMINFO1_CMD_SPEED 'R' /* 82 speed command : abs/rel info in info 2, speed level as little endian + uint16 in item content; elative value is in promille */ +#define PICODATA_ITEMINFO1_CMD_VOLUME 'V' /* 86 volume command : abs/rel info in info 2, volume level as little endian + uint16 in item content; relative value is in promille */ +#define PICODATA_ITEMINFO1_CMD_SPEAKER 'S' /* 83 speaker command : abs/rel info in info 2, speaker level as little endian + uint16 in item content; relative value is in promille */ + +/* iteminfo2 for PLAY/SAVE */ +#define PICODATA_ITEMINFO2_CMD_TO_TOK 't' /* CMD+PLAY/SAVE+TOKENISATION*/ +#define PICODATA_ITEMINFO2_CMD_TO_PR 'g' /* CMD+PLAY/SAVE+PREPROC*/ +#define PICODATA_ITEMINFO2_CMD_TO_WA 'w' /* CMD+PLAY/SAVE+WORDANA*/ +#define PICODATA_ITEMINFO2_CMD_TO_SA 'a' /* CMD+PLAY/SAVE+SENTANA*/ +#define PICODATA_ITEMINFO2_CMD_TO_ACPH 'h' /* CMD+PLAY/SAVE+ACCENTUATION&PHRASING*/ +#define PICODATA_ITEMINFO2_CMD_TO_SPHO 'p' /* CMD+PLAY/SAVE+ACCENTUATION&PHRASING*/ +#define PICODATA_ITEMINFO2_CMD_TO_PAM 'q' /* CMD+PLAY/SAVE+PHONETIC-ACOUSTIC MAPPING*/ +#define PICODATA_ITEMINFO2_CMD_TO_CEP 'c' /* CMD+PLAY/SAVE+CEP_SMOOTHER*/ +#define PICODATA_ITEMINFO2_CMD_TO_SIG 's' /* CMD+PLAY/SAVE+SIG_GEN */ + +#if 0 +#define PICODATA_ITEMINFO2_CMD_TO_FST 'f' /* CMD+PLAY/SAVE+FST for Syll and Phonotactic constraints*/ +#endif + +#define PICODATA_ITEMINFO2_CMD_TO_UNKNOWN 255 + +/* iteminfo2 for start/end commands */ +#define PICODATA_ITEMINFO2_CMD_START 's' +#define PICODATA_ITEMINFO2_CMD_END 'e' + +/* iteminfo2 for speed/pitch/volume commands */ +#define PICODATA_ITEMINFO2_CMD_ABSOLUTE 'a' +#define PICODATA_ITEMINFO2_CMD_RELATIVE 'r' + +/* len for CMD item could be >= 0 */ +/* ------------------------- TOKEN item type ---------------------------- */ +/* iteminfo1: simple token type : */ +#define PICODATA_ITEMINFO1_TOKTYPE_SPACE 'W' +#define PICODATA_ITEMINFO1_TOKTYPE_LETTERV 'V' +#define PICODATA_ITEMINFO1_TOKTYPE_LETTER 'L' +#define PICODATA_ITEMINFO1_TOKTYPE_DIGIT 'D' +#define PICODATA_ITEMINFO1_TOKTYPE_SEQ 'S' +#define PICODATA_ITEMINFO1_TOKTYPE_CHAR 'C' +#define PICODATA_ITEMINFO1_TOKTYPE_BEGIN 'B' +#define PICODATA_ITEMINFO1_TOKTYPE_END 'E' +#define PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED 'U' +/* iteminfo2 : token subtype */ +/* len for WORDTOK item is ALWAYS > 0, if len==0 an error should be raised */ + +/** + * @addtogroup picodata + * + * ------------------------- WORDGRAPH item type ---------------------------- + * - iteminfo1 : POS and multi-POS values defined in lingware + * - iteminfo2 : not applicable + * - len for WORDGRAPH item is ALWAYS > 0, if len==0 an error should be raised + * (currently picopr may produce empty WORDGRAPH that is eliminated by picowa) + * \n------------------------- WORDINDEX item type ---------------------------- + * - iteminfo1 : POS and multi-POS values defined in lingware + * - iteminfo2 : not applicable + * - len for WORDINDEX item is ALWAYS > 0, if len==0 an error should be raised + * \n------------------------- WORDPHON item type ---------------------------- + * - iteminfo1 : POS values defined in lingware + * - iteminfo2 : Uses PICODATA_ACC0 .. ACC4 + * -len WORDPHON item is ALWAYS > 0, if len==0 an error should be raised + * \n------------------------- SYLLPHON item type ---------------------------- + * - iteminfo1 : not applicable + * - iteminfo2 : Uses PICODATA_ACC0 .. ACC4 + * - len for SYLLPHON item is ALWAYS > 0, if len==0 an error should be raised + * \n------------------------- PHONE item type (PRODUCED BY PAM)----------------- + * - iteminfo1 : phonId : the phonetic identity of the phone + * - iteminfo2 : n_S_P_Phone : number of states per phoneme + * - len for PHON item is ALWAYS > 0, if len==0 an error should be raised + * \n------------------------- FRAME_PAR item type (PRODUCED BY CEP) -------- + * - iteminfo1 : format (float, fixed) + * - iteminfo2 : vector size + * - len for FRAME_PAR item is ALWAYS > 0, if len==0 an error should be raised + * \n------------------------- FRAME item type (PRODUCED BY SIG) ----------- + * - iteminfo1 : number of samples per frame + * - iteminfo2 : number of bytes per sample + * - len for FRAME item is ALWAYS > 0, if len==0 an error should be raised + * + */ +#define PICODATA_ITEMINFO1_FRAME_PAR_DATA_FORMAT_FIXED '\x78' /* 120 'x' fixed point */ +#define PICODATA_ITEMINFO1_FRAME_PAR_DATA_FORMAT_FLOAT '\x66' /* 102 'f' floating point */ + +/* *************************************************************** + * items: CharBuffer functions * + *****************************************************************/ + +/* gets a single item (head and content) from a CharBuffer in buf; + blenmax is the max length (in number of bytes) of buf; blen is + set to the number of bytes gotten in buf; return values: + PICO_OK <- one item gotten + PICO_EOF <- no item available, cb is empty + PICO_EXC_BUF_UNDERFLOW <- cb not empty, but no valid item + PICO_EXC_BUF_OVERFLOW <- buf not large enough +*/ +pico_status_t picodata_cbGetItem(register picodata_CharBuffer this, + picoos_uint8 *buf, const picoos_uint16 blenmax, + picoos_uint16 *blen); + +/* gets the speech data (without item head) from a CharBuffer in buf; + blenmax is the max length (in number of bytes) of buf; blen is + set to the number of bytes gotten in buf; return values: + PICO_OK <- speech data of one item gotten + PICO_EOF <- no item available, cb is empty + PICO_EXC_BUF_UNDERFLOW <- cb not empty, but no valid item + PICO_EXC_BUF_OVERFLOW <- buf not large enough +*/ +pico_status_t picodata_cbGetSpeechData(register picodata_CharBuffer this, + picoos_uint8 *buf, const picoos_uint16 blenmax, + picoos_uint16 *blen); + +/* puts a single item (head and content) to a CharBuffer; clenmax is + the max length (in number of bytes) accessible in content; clen is + set to the number of bytes put from content; return values: + PICO_OK <- one item put + PICO_EXC_BUF_UNDERFLOW <- no valid item in buf + PICO_EXC_BUF_OVERFLOW <- cb not large enough +*/ +pico_status_t picodata_cbPutItem(register picodata_CharBuffer this, + const picoos_uint8 *buf, const picoos_uint16 blenmax, + picoos_uint16 *blen); + +/* unsafe, just for measuring purposes */ +picoos_uint8 picodata_cbGetFrontItemType(register picodata_CharBuffer this); + +/* *************************************************************** + * items: support function * + *****************************************************************/ + +/* checks, whether item of type 'ch' is a valid item type */ +picoos_uint8 is_valid_itemtype(const picoos_uint8 ch); + +/* gets from buf a single item, values in head set and item content + copied to content; blenmax and clenmax are the max lengths (in + number of bytes) accessible in buf and content; clen is set to the + number of bytes gotten in content; return values: + PICO_OK <- all ok + PICO_EXC_BUF_UNDERFLOW <- blenmax problem, or no valid item + PICO_EXC_BUF_OVERFLOW <- overflow in content +*/ +pico_status_t picodata_get_itemparts_nowarn( + const picoos_uint8 *buf, const picoos_uint16 blenmax, + picodata_itemhead_t *head, picoos_uint8 *content, + const picoos_uint16 clenmax, picoos_uint16 *clen); + +/* gets from buf a single item, values in head set and item content + copied to content; blenmax and clenmax are the max lengths (in + number of bytes) accessible in buf and content; clen is set to the + number of bytes gotten in content; return values: + PICO_OK <- all ok + PICO_EXC_BUF_UNDERFLOW <- blenmax problem, or no valid item + PICO_EXC_BUF_OVERFLOW <- overflow in content +*/ +pico_status_t picodata_get_itemparts( + const picoos_uint8 *buf, const picoos_uint16 blenmax, + picodata_itemhead_t *head, picoos_uint8 *content, + const picoos_uint16 clenmax, picoos_uint16 *clen); + +/* puts a single item to buf; values in head and content copied to + buf; clenmax is the max length (in number of bytes) accessible in + content; blenmax is the max length (bytes) accessible in buf; blen + is set to the number of bytes put to buf; return values: + PICO_OK <- all ok + PICO_EXC_BUF_UNDERFLOW <- clenmax problem, or no valid item + PICO_EXC_BUF_OVERFLOW <- overflow in buf +*/ +pico_status_t picodata_put_itemparts(const picodata_itemhead_t *head, + const picoos_uint8 *content, const picoos_uint16 clenmax, + picoos_uint8 *buf, const picoos_uint16 blenmax, picoos_uint16 *blen); + +/* gets from buf info of a single item, values in head are set and + content is set to the start of content in buf (not copied!); + content is set to NULL if the content length is 0; blenmax is the + max lengths (in number of bytes) accessible in buf; return values: + PICO_OK <- all ok + PICO_EXC_BUF_UNDERFLOW <- blenmax problem, or no valid item +*/ +pico_status_t picodata_get_iteminfo( + picoos_uint8 *buf, const picoos_uint16 blenmax, + picodata_itemhead_t *head, picoos_uint8 **content); + +/* copies the item in inbuf to outbuf after first checking if there is + a valid item in inbuf; inlenmax and outlenmax are the max length + (in number of byte) accessible in the buffers); in *numb the total + number of bytes copied to outbuf (incl. header) is returned; return + values: + PICO_OK <- item copied + PICO_EXC_BUF_OVERFLOW <- overflow in outbuf + PICO_ERR_OTHER <- no valid item in inbuf +*/ +pico_status_t picodata_copy_item(const picoos_uint8 *inbuf, + const picoos_uint16 inlenmax, picoos_uint8 *outbuf, + const picoos_uint16 outlenmax, picoos_uint16 *numb); + +/* sets the info1 field in the header contained in the item in buf; + return values: + PICO_OK <- all ok + PICO_EXC_BUF_UNDERFLOW <- underflow in buf +*/ +pico_status_t picodata_set_iteminfo1(picoos_uint8 *buf, + const picoos_uint16 blenmax, const picoos_uint8 info); + +/* sets the info2 field in the header contained in the item in buf; + return values: + PICO_OK <- all ok + PICO_EXC_BUF_UNDERFLOW <- underflow in buf +*/ +pico_status_t picodata_set_iteminfo2(picoos_uint8 *buf, + const picoos_uint16 blenmax, const picoos_uint8 info); + +/* sets the len field in the header contained in the item in buf; + return values: + PICO_OK <- all ok + PICO_EXC_BUF_UNDERFLOW <- underflow in buf +*/ +pico_status_t picodata_set_itemlen(picoos_uint8 *buf, + const picoos_uint16 blenmax, const picoos_uint8 len); + +/* check item validity and return TRUE if valid; return FALSE if + invalid; ilenmax is the max index to be used in item +*/ +picoos_uint8 picodata_is_valid_item(const picoos_uint8 *item, + const picoos_uint16 ilenmax); + +/* return TRUE if head is a valid item head, FALSE otherwise */ +picoos_uint8 picodata_is_valid_itemhead(const picodata_itemhead_t *head); + + +/* *************************************************************** + * ProcessingUnit * + *****************************************************************/ +/* public */ + +#define PICODATA_MAX_ITEMSIZE (picoos_uint16) (PICODATA_ITEM_HEADSIZE + 256) + +/* different buffer sizes per processing unit */ +#define PICODATA_BUFSIZE_DEFAULT (picoos_uint16) PICODATA_MAX_ITEMSIZE +#define PICODATA_BUFSIZE_TEXT (picoos_uint16) 1 * PICODATA_BUFSIZE_DEFAULT +#define PICODATA_BUFSIZE_TOK (picoos_uint16) 2 * PICODATA_BUFSIZE_DEFAULT +#define PICODATA_BUFSIZE_PR (picoos_uint16) 2 * PICODATA_BUFSIZE_DEFAULT +#define PICODATA_BUFSIZE_WA (picoos_uint16) 2 * PICODATA_BUFSIZE_DEFAULT +#define PICODATA_BUFSIZE_SA (picoos_uint16) 2 * PICODATA_BUFSIZE_DEFAULT +#define PICODATA_BUFSIZE_ACPH (picoos_uint16) 2 * PICODATA_BUFSIZE_DEFAULT +#define PICODATA_BUFSIZE_SPHO (picoos_uint16) 4 * PICODATA_BUFSIZE_DEFAULT +#define PICODATA_BUFSIZE_PAM (picoos_uint16) 4 * PICODATA_BUFSIZE_DEFAULT +#define PICODATA_BUFSIZE_CEP (picoos_uint16) 16 * PICODATA_BUFSIZE_DEFAULT +#define PICODATA_BUFSIZE_SIG (picoos_uint16) 16 * PICODATA_BUFSIZE_DEFAULT +#define PICODATA_BUFSIZE_SINK (picoos_uint16) 1 * PICODATA_BUFSIZE_DEFAULT + +/* different types of processing units */ +typedef enum picodata_putype { + PICODATA_PUTYPE_TEXT, /* text */ + PICODATA_PUTYPE_TOK, /* tokenizer output */ + PICODATA_PUTYPE_PR, /* preprocessor output */ + PICODATA_PUTYPE_WA, /* word analysis */ + PICODATA_PUTYPE_SA, /* sentence analysis */ + PICODATA_PUTYPE_ACPH, /* accentuation and phrasing */ + PICODATA_PUTYPE_SPHO, /* sentence phonology (textana postproc) */ + PICODATA_PUTYPE_PAM, /* phonetics to acoustics mapper processing unit */ + PICODATA_PUTYPE_CEP, /* cepstral smoothing processing unit */ + PICODATA_PUTYPE_SIG, /* signal generation processing unit*/ + PICODATA_PUTYPE_SINK /* item sink unit*/ +} picodata_putype_t; + +picoos_uint16 picodata_get_default_buf_size (picodata_putype_t puType); + +/* result values returned from the pu->puStep() methode */ +typedef enum picodata_step_result { + PICODATA_PU_ERROR, + /* PICODATA_PU_EMPTY, *//* reserved (no internal data to be processed) */ + PICODATA_PU_IDLE, /* need more input to process internal data */ + PICODATA_PU_BUSY, /* processing internal data */ + PICODATA_PU_ATOMIC, /* same as pu_busy, but wants to get next time slot (while in an "atomar" operation) */ + PICODATA_PU_OUT_FULL /* can't proceed because output is full. (next time slot to be assigned to pu's output's consumer) */ +} picodata_step_result_t; + +typedef struct picodata_processing_unit * picodata_ProcessingUnit; + +picodata_ProcessingUnit picodata_newProcessingUnit( + picoos_MemoryManager mm, + picoos_Common common, + picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, + picorsrc_Voice voice); + +void picodata_disposeProcessingUnit( + picoos_MemoryManager mm, + picodata_ProcessingUnit * this); + +picodata_CharBuffer picodata_getCbIn(picodata_ProcessingUnit this); +picodata_CharBuffer picodata_getCbOut(picodata_ProcessingUnit this); +pico_status_t picodata_setCbIn(picodata_ProcessingUnit this, picodata_CharBuffer cbIn); +pico_status_t picodata_setCbOut(picodata_ProcessingUnit this, picodata_CharBuffer cbOut); + +/* protected */ +typedef pico_status_t (* picodata_puInitializeMethod) (register picodata_ProcessingUnit this); +typedef pico_status_t (* picodata_puTerminateMethod) (register picodata_ProcessingUnit this); +typedef picodata_step_result_t (* picodata_puStepMethod) (register picodata_ProcessingUnit this, picoos_int16 mode, picoos_uint16 * numBytesOutput); +typedef pico_status_t (* picodata_puSubDeallocateMethod) (register picodata_ProcessingUnit this, picoos_MemoryManager mm); + +typedef struct picodata_processing_unit +{ + /* public */ + picodata_puInitializeMethod initialize; + picodata_puStepMethod step; + picodata_puTerminateMethod terminate; + picorsrc_Voice voice; + + /* protected */ + picoos_Common common; + picodata_CharBuffer cbIn, cbOut; + picodata_puSubDeallocateMethod subDeallocate; + void * subObj; + +} picodata_processing_unit_t; + +/* currently, only wav input and output is supported */ +#define PICODATA_PUTYPE_TEXT_OUTPUT_EXTENSION (picoos_uchar*)".txt" +#define PICODATA_PUTYPE_TOK_INPUT_EXTENSION PICODATA_PUTYPE_TEXT_OUTPUT_EXTENSION +#define PICODATA_PUTYPE_TOK_OUTPUT_EXTENSION (picoos_uchar*)".tok" +#define PICODATA_PUTYPE_PR_INPUT_EXTENSION PICODATA_PUTYPE_TOK_OUTPUT_EXTENSION +#define PICODATA_PUTYPE_PR_OUTPUT_EXTENSION (picoos_uchar*)".pr" +#define PICODATA_PUTYPE_WA_INPUT_EXTENSION PICODATA_PUTYPE_PR_OUTPUT_EXTENSION +#define PICODATA_PUTYPE_WA_OUTPUT_EXTENSION (picoos_uchar*)".wa" +#define PICODATA_PUTYPE_SA_INPUT_EXTENSION PICODATA_PUTYPE_WA_OUTPUT_EXTENSION +#define PICODATA_PUTYPE_SA_OUTPUT_EXTENSION (picoos_uchar*)".sa" +#define PICODATA_PUTYPE_ACPH_INPUT_EXTENSION PICODATA_PUTYPE_SA_OUTPUT_EXTENSION +#define PICODATA_PUTYPE_ACPH_OUTPUT_EXTENSION (picoos_uchar*)".acph" +#define PICODATA_PUTYPE_SPHO_INPUT_EXTENSION PICODATA_PUTYPE_ACPH_OUTPUT_EXTENSION +#define PICODATA_PUTYPE_SPHO_OUTPUT_EXTENSION (picoos_uchar*)".spho" +#define PICODATA_PUTYPE_PAM_INPUT_EXTENSION PICODATA_PUTYPE_SPHO_OUTPUT_EXTENSION +#define PICODATA_PUTYPE_PAM_OUTPUT_EXTENSION (picoos_uchar*)".pam" +#define PICODATA_PUTYPE_CEP_INPUT_EXTENSION PICODATA_PUTYPE_PAM_OUTPUT_EXTENSION +#define PICODATA_PUTYPE_CEP_OUTPUT_EXTENSION (picoos_uchar*)".cep" +#define PICODATA_PUTYPE_SIG_INPUT_EXTENSION PICODATA_PUTYPE_CEP_OUTPUT_EXTENSION /*PP 11.7.08*/ +#define PICODATA_PUTYPE_SIG_OUTPUT_EXTENSION (picoos_uchar*)".sig" +#define PICODATA_PUTYPE_SINK_INPUT_EXTENSION PICODATA_PUTYPE_SIG_OUTPUT_EXTENSION + +/*wav input is for play wav files in sig */ +#define PICODATA_PUTYPE_WAV_INPUT_EXTENSION (picoos_uchar*)".wav" /*PP 11.7.08*/ + +/*wav output is for saving wav (binary) files in sig*/ +#define PICODATA_PUTYPE_WAV_OUTPUT_EXTENSION (picoos_uchar*)".wav" /*PP 14.7.08*/ + +/* *************************************************************** + * auxiliary routines * + *****************************************************************/ + +picoos_uint8 picodata_getPuTypeFromExtension(picoos_uchar * filename, picoos_bool input); + +#define PICODATA_XSAMPA (picoos_uchar *)"xsampa" +#define PICODATA_SAMPA (picoos_uchar *)"sampa" +#define PICODATA_SVOXPA (picoos_uchar *)"svoxpa" + +/*----------------------------------------------------------*/ +/** @brief maps an input phone string to its internal representation + * + * @param transducer initialized SimpleTransducer + * @param xsampa_parser fst converting xsampa char input to xsampa ids + * @param svoxpa_parser + * @param xsampa2svoxpa_mapper + * @param inputPhones input phone string in alphabet 'alphabet' + * @param alphabet input alphabet + * @retval outputPhoneIds output phone string in internal representation + * @param maxOutputPhoneIds + * @return PICO_OK=mapping done, PICO_ERR_OTHER:unknown alphabet, unknown phones + */ +/*---------------------------------------------------------*/ +pico_status_t picodata_mapPAStrToPAIds( + picotrns_SimpleTransducer transducer, + picoos_Common common, + picokfst_FST xsampa_parser, + picokfst_FST svoxpa_parser, + picokfst_FST xsampa2svoxpa_mapper, + picoos_uchar * inputPhones, + picoos_uchar * alphabet, + picoos_uint8 * outputPhoneIds, + picoos_int32 maxOutputPhoneIds); + +/* number of binary digits after the comma for fixed-point calculation */ +#define PICODATA_PRECISION 10 +/* constant 0.5 in PICODATA_PRECISION */ +#define PICODATA_PREC_HALF 512 + +void picodata_transformDurations( + picoos_uint8 frame_duration_exp, + picoos_int8 array_length, + picoos_uint8 * inout, + const picoos_uint16 * weight, /* integer weights */ + picoos_int16 mintarget, /* minimum target duration in ms */ + picoos_int16 maxtarget, /* maximum target duration in ms */ + picoos_int16 facttarget, /* factor to be multiplied with original length to get the target + the factor is fixed-point with precision PRECISION, i.e. + the factor as float would be facttarget / PRECISION_FACT + if factor is 0, only min/max are considered */ + picoos_int16 * dur_rest /* in/out, rest in ms */ + ); + + + +/* *************************************************************** + * For Debugging only * + *****************************************************************/ + +#if defined (PICO_DEBUG) + +/* convert (pretty print) item head 'head' and put output in 'str', + strsize is the maximum length of 'str' in bytes */ +picoos_char * picodata_head_to_string(const picodata_itemhead_t *head, + picoos_char * str, picoos_uint16 strsize); + +/* put 'pref6ch' (max. 6 char prefix) and a pretty print output of + 'item' in 'str', strlenmax is the maximum length of 'str' in + bytes */ +void picodata_info_item(const picoknow_KnowledgeBase kb, + const picoos_uint8 *pref6ch, + const picoos_uint8 *item, + const picoos_uint16 itemlenmax, + const picoos_char *filterfn); + + +#define PICODATA_INFO_ITEM(kb, pref, item, itemlenmax) \ + PICODBG_INFO_CTX(); \ + picodata_info_item(kb, pref, item, itemlenmax, (picoos_char *)__FILE__) + + + +#else + +#define PICODATA_INFO_ITEM(kb, pref, item, itemlenmax) + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /*PICODATA_H_*/ diff --git a/pico/lib/picodbg.c b/pico/lib/picodbg.c new file mode 100644 index 0000000..8fa753b --- /dev/null +++ b/pico/lib/picodbg.c @@ -0,0 +1,438 @@ +/* + * 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 picodbg.c + * + * Provides functions and macros to debug the Pico system and to trace + * the execution of its code. + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + */ + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +#if defined(PICO_DEBUG) + +/* Two variants of colored console output are implemented: + COLOR_MODE_WINDOWS + uses the Windows API function SetConsoleTextAttribute + COLOR_MODE_ANSI + uses ANSI escape codes */ +#if defined(_WIN32) +#define COLOR_MODE_WINDOWS +#else +#define COLOR_MODE_ANSI +#endif + + +#include +#include + +#include +#include + +#include "picodbg.h" + + +/* Maximum length of a formatted tracing message */ +#define MAX_MESSAGE_LEN 999 + +/* Maximum length of contextual information */ +#define MAX_CONTEXT_LEN 499 + +/* Maximum length of filename filter */ +#define MAX_FILTERFN_LEN 16 + +/* Delimiter used in debug messages */ +#define MSG_DELIM "|" + +/* Standard output file for debug messages */ +#define STDDBG stdout /* or stderr */ + +/* Default setup */ +#define PICODBG_DEFAULT_LEVEL PICODBG_LOG_LEVEL_WARN +#define PICODBG_DEFAULT_FILTERFN "" +#define PICODBG_DEFAULT_FORMAT \ + (PICODBG_SHOW_LEVEL | PICODBG_SHOW_SRCNAME | PICODBG_SHOW_FUNCTION) +#define PICODBG_DEFAULT_COLOR 1 + + +/* Current log level */ +static int logLevel = PICODBG_DEFAULT_LEVEL; + +/* Current log filter (filename) */ +static char logFilterFN[MAX_FILTERFN_LEN + 1]; + +/* Current log file or NULL if no log file is set */ +static FILE *logFile = NULL; + +/* Current output format */ +static int logFormat = PICODBG_DEFAULT_FORMAT; + +/* Color mode for console output (0 : disable colors, != 0 : enable colors */ +static int optColor = 0; + +/* Buffer for context information */ +static char ctxbuf[MAX_CONTEXT_LEN + 1]; + +/* Buffer to format tracing messages */ +static char msgbuf[MAX_MESSAGE_LEN + 1]; + + +/* *** Support for colored text output to console *****/ + + +/* Console text colors */ +enum color_t { + /* order matches Windows color codes */ + ColorBlack, + ColorBlue, + ColorGreen, + ColorCyan, + ColorRed, + ColorPurple, + ColorBrown, + ColorLightGray, + ColorDarkGray, + ColorLightBlue, + ColorLightGreen, + ColorLightCyan, + ColorLightRed, + ColorLightPurple, + ColorYellow, + ColorWhite +}; + + +static enum color_t picodbg_getLevelColor(int level) +{ + switch (level) { + case PICODBG_LOG_LEVEL_ERROR: return ColorLightRed; + case PICODBG_LOG_LEVEL_WARN : return ColorYellow; + case PICODBG_LOG_LEVEL_INFO : return ColorGreen; + case PICODBG_LOG_LEVEL_DEBUG: return ColorLightGray; + case PICODBG_LOG_LEVEL_TRACE: return ColorDarkGray; + } + return ColorWhite; +} + + +#if defined(COLOR_MODE_WINDOWS) + +#define WIN32_LEAN_AND_MEAN +#include + +static int picodbg_setTextAttr(FILE *stream, int attr) +{ + HANDLE hConsole; + + if (stream == stdout) { + hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + } else if (stream == stderr) { + hConsole = GetStdHandle(STD_ERROR_HANDLE); + } else { + hConsole = INVALID_HANDLE_VALUE; + } + + if (hConsole != INVALID_HANDLE_VALUE) { + /* do nothing if console output is redirected to a file */ + if (GetFileType(hConsole) == FILE_TYPE_CHAR) { + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(hConsole, &csbi); + SetConsoleTextAttribute(hConsole, (WORD) attr); + return (int) csbi.wAttributes; + } + } + + return 0; +} + +#elif defined(COLOR_MODE_ANSI) + +static int picodbg_setTextAttr(FILE *stream, int attr) +{ + const char *c = ""; + + if (attr == -1) { + c = "0"; + } else switch (attr) { + case ColorBlack: c = "0;30"; break; + case ColorRed: c = "0;31"; break; + case ColorGreen: c = "0;32"; break; + case ColorBrown: c = "0;33"; break; + case ColorBlue: c = "0;34"; break; + case ColorPurple: c = "0;35"; break; + case ColorCyan: c = "0;36"; break; + case ColorLightGray: c = "0;37"; break; + case ColorDarkGray: c = "1;30"; break; + case ColorLightRed: c = "1;31"; break; + case ColorLightGreen: c = "1;32"; break; + case ColorYellow: c = "1;33"; break; + case ColorLightBlue: c = "1;34"; break; + case ColorLightPurple: c = "1;35"; break; + case ColorLightCyan: c = "1;36"; break; + case ColorWhite: c = "1;37"; break; + } + + fprintf(stream, "\x1b[%sm", c); + return -1; +} + +#else + +static int picodbg_setTextAttr(FILE *stream, int attr) +{ + /* avoid 'unreferenced formal parameter' */ + (void) stream; + (void) attr; + return 0; +} + +#endif + + +/* *** Auxiliary routines *****/ + + +static const char *picodbg_fileTitle(const char *file) +{ + const char *name = file, *str = file; + + /* try to extract file name without path in a platform independent + way, i.e., skip all chars preceding path separator chars like + '/' (Unix, MacOSX), '\' (Windows, DOS), and ':' (MacOS9) */ + while (*str) { + if ((*str == '\\') || (*str == '/') || (*str == ':')) { + name = str + 1; + } + str++; + } + + return name; +} + + +static void picodbg_logToStream(int level, int donewline, + const char *context, const char *msg) +{ + int oldAttr = 0; + + if (optColor) { + oldAttr = picodbg_setTextAttr(STDDBG, picodbg_getLevelColor(level)); + } + + fprintf(STDDBG, "%s%s", context, msg); + if (donewline) fprintf(STDDBG, "\n"); + if (logFile != NULL) { + fprintf(logFile, "%s%s", context, msg); + if (donewline) fprintf(logFile, "\n"); + } + + if (optColor) { + picodbg_setTextAttr(STDDBG, oldAttr); + } +} + + +/* *** Exported routines *****/ + + +void picodbg_initialize(int level) +{ + logLevel = level; + strcpy(logFilterFN, PICODBG_DEFAULT_FILTERFN); + logFile = NULL; + logFormat = PICODBG_DEFAULT_FORMAT; + optColor = PICODBG_DEFAULT_COLOR; + PICODBG_ASSERT_RANGE(level, 0, PICODBG_LOG_LEVEL_TRACE); +} + + +void picodbg_terminate() +{ + if (logFile != NULL) { + fclose(logFile); + } + + logLevel = 0; + logFile = NULL; +} + + +void picodbg_setLogLevel(int level) +{ + PICODBG_ASSERT_RANGE(level, 0, PICODBG_LOG_LEVEL_TRACE); + logLevel = level; +} + + +void picodbg_setLogFilterFN(const char *name) +{ + strcpy(logFilterFN, name); +} + + +void picodbg_setLogFile(const char *name) +{ + if (logFile != NULL) { + fclose(logFile); + } + + if ((name != NULL) && (strlen(name) > 0)) { + logFile = fopen(name, "wt"); + } else { + logFile = NULL; + } +} + + +void picodbg_enableColors(int flag) +{ + optColor = (flag != 0); +} + + +void picodbg_setOutputFormat(unsigned int format) +{ + logFormat = format; +} + + +const char *picodbg_varargs(const char *format, ...) +{ + int len; + + va_list argptr; + va_start(argptr, format); + + len = vsprintf(msgbuf, format, argptr); + PICODBG_ASSERT_RANGE(len, 0, MAX_MESSAGE_LEN); + + return msgbuf; +} + + +void picodbg_log(int level, int donewline, const char *file, int line, + const char *func, const char *msg) +{ + char cb[MAX_CONTEXT_LEN + 1]; + + PICODBG_ASSERT_RANGE(level, 0, PICODBG_LOG_LEVEL_TRACE); + + if ((level <= logLevel) && + ((strlen(logFilterFN) == 0) || !strcmp(logFilterFN, picodbg_fileTitle(file)))) { + /* compose output format string */ + strcpy(ctxbuf, "*** "); + if (logFormat & PICODBG_SHOW_LEVEL) { + switch (level) { + case PICODBG_LOG_LEVEL_ERROR: + strcat(ctxbuf, "error" MSG_DELIM); + break; + case PICODBG_LOG_LEVEL_WARN: + strcat(ctxbuf, "warn " MSG_DELIM); + break; + case PICODBG_LOG_LEVEL_INFO: + strcat(ctxbuf, "info " MSG_DELIM); + break; + case PICODBG_LOG_LEVEL_DEBUG: + strcat(ctxbuf, "debug" MSG_DELIM); + break; + case PICODBG_LOG_LEVEL_TRACE: + strcat(ctxbuf, "trace" MSG_DELIM); + break; + default: + break; + } + } + if (logFormat & PICODBG_SHOW_DATE) { + /* nyi */ + } + if (logFormat & PICODBG_SHOW_TIME) { + /* nyi */ + } + if (logFormat & PICODBG_SHOW_SRCNAME) { + sprintf(cb, "%-10s", picodbg_fileTitle(file)); + strcat(ctxbuf, cb); + if (logFormat & PICODBG_SHOW_SRCLINE) { + sprintf(cb, "(%d)", line); + strcat(ctxbuf, cb); + } + strcat(ctxbuf, MSG_DELIM); + } + if (logFormat & PICODBG_SHOW_FUNCTION) { + if (strlen(func) > 0) { + sprintf(cb, "%-18s", func); + strcat(ctxbuf, cb); + strcat(ctxbuf, MSG_DELIM); + } + } + + picodbg_logToStream(level, donewline, ctxbuf, msg); + } +} + + +void picodbg_log_msg(int level, const char *file, const char *msg) +{ + PICODBG_ASSERT_RANGE(level, 0, PICODBG_LOG_LEVEL_TRACE); + + if ((level <= logLevel) && + ((strlen(logFilterFN) == 0) || !strcmp(logFilterFN, picodbg_fileTitle(file)))) { + picodbg_logToStream(level, 0, "", msg); + } +} + + +void picodbg_assert(const char *file, int line, const char *func, const char *expr) +{ + if (strlen(func) > 0) { + fprintf(STDDBG, "assertion failed: %s, file %s, function %s, line %d", + expr, picodbg_fileTitle(file), func, line); + } else { + fprintf(STDDBG, "assertion failed: %s, file %s, line %d", + expr, picodbg_fileTitle(file), line); + } + picodbg_terminate(); + abort(); +} + + +#else + +/* To prevent warning about "translation unit is empty" when + diagnostic output is disabled. */ +static void picodbg_dummy(void) { + picodbg_dummy(); +} + +#endif /* defined(PICO_DEBUG) */ + +#ifdef __cplusplus +} +#endif + + +/* end */ diff --git a/pico/lib/picodbg.h b/pico/lib/picodbg.h new file mode 100644 index 0000000..490d3b5 --- /dev/null +++ b/pico/lib/picodbg.h @@ -0,0 +1,311 @@ +/* + * 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 picodbg.h + * + * Provides functions and macros to debug the Pico system and to trace + * the execution of its code. + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + */ + +/** + * @addtogroup picodbg + * ---------------------------------------------------\n + * Pico Debug Support \n + * ---------------------------------------------------\n + * GENERAL REMARKS + * --------------- + * This module provides a set of macros to help debug the Pico system. + * The usage of macros allows for completely removing debug code from + * the binaries delivered to customers. To enable diagnostic output + * the preprocessor symbol PICO_DEBUG has to be defined. + * + * By using global variables (to store the current log level etc.) + * this module violates a basic Pico design principle! + * + * Justification:\n + * - going without global data would reduce the functionality + * of this module considerably (e.g., log level could not be + * changed at runtime etc.) + * - at the moment, the only known system interdicting global + * variables is Symbian; but even there global variables are + * possible by using thread-local storage + * - allocating global data on the heap would require to pass + * a handle to this memory block to all routines of this + * module which in turn implies that _every_ function in the + * Pico system would require a pointer to some global data; + * obviously, this would be very awkward + * + * Furthermore, this module uses the non-standardized but handy + * __FUNCTION__ macro. It expands to the name of the enclosing + * function. For compilers not supporting this macro simply + * define __FUNCTION__ as an empty string. + * + * + * INITIALIZATION/TERMINATION\n + * --------------------------\n + * Before using any debug macros, this module has to be initialized + * by calling PICODBG_INITIALIZE(). If the routines are not needed + * anymore, PICODBG_TERMINATE() has to be called to terminate the + * module (e.g., to close the log file). + * + * + * TRACING\n + * -------\n + * Each tracing message is associated with a log level which describes + * its severity. The following levels are supported: + * - Trace - Very detailed log messages, potentially of a high + * frequency and volume + * - Debug - Less detailed and/or less frequent debugging messages + * - Info - Informational messages + * - Warn - Warnings which don't appear to the Pico user + * - Error - Error messages + * + * Tracing messages can use the well-known printf format specification. + * But because variadic macros (macros with a variable no. arguments) + * are not commonly supported by compilers a little trick is used + * which requires the format string and its arguments to be enclosed + * in double parenthesis: + * + * - PICODBG_INFO(("hello, world!")); + * - PICODBG_TRACE(("argc=%d", argc)); + * ... + * + * Each tracing message is expected to be a single line of text. Some + * contextual information (e.g., log level, time and date, source file + * and line number) and a newline are automatically added. The output + * format can be customized by a call to PICODBG_SET_OUTPUT_FORMAT(). + * + * Sample output: + * - *** info|2008-04-03|14:51:36|dbgdemo.c(15)|hello world + * - *** trace|2008-04-03|14:51:36|dbgdemo.c(16)|argc=2 + * - ... + * + * To compose a tracing message line consisting of, e.g. the elements + * of an array, on the Info level two additional macros shown in the + * following example are provided: + * + * PICODBG_INFO_CTX();\n + * for (i = 0; i < len; i++)\n + * ...some calc with arr and i\n + * PICODBG_INFO_MSG((" %d", arr[i]));\n + * }\n + * PICODBG_INFO_MSG(("\n"));\n + * + * Colored output of tracing messages helps to capture severe problems + * quickly. This feature is supported on the Windows platform and on + * platforms supporting ANSI escape codes. PICODBG_ENABLE_COLORS() lets + * you turn on and off colored output. + * + * + * FILTERING\n + * ---------\n + * By calling PICODBG_SET_LOG_LEVEL() the log level may be changed at + * any time to increase/decrease the amount of debugging output. + * + * By calling PICODBG_SET_LOG_FILTERFN() the log filter may be changed + * at any time to change the source file name being used as filter for + * log messages (ie. only tracing info of the specified file will be + * logged). To disable the file name based filter set the filter file + * name to an empty string. + * + * Future version of this module might provide further filtering + * possibilities (e.g., filtering based on function names * etc.). + * + * + * LOGGING\n + * -------\n + * By default, tracing messages are output to the console (stderr). + * This allows for separating diagnostic output from other console + * output to stdout. In addition, tracing messages may be saved to + * a file by calling PICODBG_SET_LOG_FILE(). + * Currently, file output is the only additional output target; but + * on embedded systems, more output targets may be required (e.g., + * sending output to a serial port or over the network). + * + * + * ASSERTIONS\n + * ----------\n + * To support the 'design/programming by contract' paradigm, this + * module also provides assertions. PICODBG_ASSERT(expr) evualuates + * an expression and, when the result is false, prints a diagnostic + * message and aborts the program. + * + * + * FUTURE EXTENSIONS\n + * -----------------\n + * - advanced tracing functions to dump complex data + * - debug memory allocation that can be used to assist in + * finding memory problems + */ + + +#if !defined(__PICODBG_H__) +#define __PICODBG_H__ + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* Not all compilers support the __FUNCTION__ macro */ +#if !defined(__FUNCTION__) && !defined(__GNUC__) +#define __FUNCTION__ "" +#endif + + +/* Log levels sorted by severity */ +#define PICODBG_LOG_LEVEL_ERROR 1 +#define PICODBG_LOG_LEVEL_WARN 2 +#define PICODBG_LOG_LEVEL_INFO 3 +#define PICODBG_LOG_LEVEL_DEBUG 4 +#define PICODBG_LOG_LEVEL_TRACE 5 + +/* Output format flags */ +#define PICODBG_SHOW_LEVEL 0x0001 +#define PICODBG_SHOW_DATE 0x0002 +#define PICODBG_SHOW_TIME 0x0004 +#define PICODBG_SHOW_SRCNAME 0x0008 +#define PICODBG_SHOW_SRCLINE 0x0010 +#define PICODBG_SHOW_SRCALL (PICODBG_SHOW_SRCNAME | PICODBG_SHOW_SRCLINE) +#define PICODBG_SHOW_FUNCTION 0x0020 +#define PICODBG_SHOW_POS (PICODBG_SHOW_SRCALL | PICODBG_SHOW_FUNCTION) + +/* definition of PICO_DEBUG enables debugging code */ +#if defined(PICO_DEBUG) + +#define PICODBG_INITIALIZE(level) \ + picodbg_initialize(level) + +#define PICODBG_TERMINATE() \ + picodbg_terminate() + +#define PICODBG_SET_LOG_LEVEL(level) \ + picodbg_setLogLevel(level) + +#define PICODBG_SET_LOG_FILTERFN(name) \ + picodbg_setLogFilterFN(name) + +#define PICODBG_SET_LOG_FILE(name) \ + picodbg_setLogFile(name) + +#define PICODBG_ENABLE_COLORS(flag) \ + picodbg_enableColors(flag) + +#define PICODBG_SET_OUTPUT_FORMAT(format) \ + picodbg_setOutputFormat(format) + + +#define PICODBG_ASSERT(expr) \ + for (;!(expr);picodbg_assert(__FILE__, __LINE__, __FUNCTION__, #expr)) + +#define PICODBG_ASSERT_RANGE(val, min, max) \ + PICODBG_ASSERT(((val) >= (min)) && ((val) <= (max))) + + +#define PICODBG_LOG(level, msg) \ + picodbg_log(level, 1, __FILE__, __LINE__, __FUNCTION__, picodbg_varargs msg) + +#define PICODBG_ERROR(msg) \ + PICODBG_LOG(PICODBG_LOG_LEVEL_ERROR, msg) + +#define PICODBG_WARN(msg) \ + PICODBG_LOG(PICODBG_LOG_LEVEL_WARN, msg) + +#define PICODBG_INFO(msg) \ + PICODBG_LOG(PICODBG_LOG_LEVEL_INFO, msg) + +#define PICODBG_DEBUG(msg) \ + PICODBG_LOG(PICODBG_LOG_LEVEL_DEBUG, msg) + +#define PICODBG_TRACE(msg) \ + PICODBG_LOG(PICODBG_LOG_LEVEL_TRACE, msg) + + +#define PICODBG_INFO_CTX() \ + picodbg_log(PICODBG_LOG_LEVEL_INFO, 0, __FILE__, __LINE__, __FUNCTION__, "") + +#define PICODBG_INFO_MSG(msg) \ + picodbg_log_msg(PICODBG_LOG_LEVEL_INFO, __FILE__, picodbg_varargs msg) + +#define PICODBG_INFO_MSG_F(filterfn, msg) \ + picodbg_log_msg(PICODBG_LOG_LEVEL_INFO, (const char *)filterfn, picodbg_varargs msg) + + + +/* helper routines; should NOT be used directly! */ + +void picodbg_initialize(int level); +void picodbg_terminate(); + +void picodbg_setLogLevel(int level); +void picodbg_setLogFilterFN(const char *name); +void picodbg_setLogFile(const char *name); +void picodbg_enableColors(int flag); +void picodbg_setOutputFormat(unsigned int format); + +const char *picodbg_varargs(const char *format, ...); + +void picodbg_log(int level, int donewline, const char *file, int line, + const char *func, const char *msg); +void picodbg_assert(const char *file, int line, const char *func, + const char *expr); + +void picodbg_log_msg(int level, const char *file, const char *msg); + + +#else /* release version; omit debugging code */ + +#define PICODBG_INITIALIZE(level) +#define PICODBG_TERMINATE() +#define PICODBG_SET_LOG_LEVEL(level) +#define PICODBG_SET_LOG_FILTERFN(name) +#define PICODBG_SET_LOG_FILE(name) +#define PICODBG_ENABLE_COLORS(flag) +#define PICODBG_SET_OUTPUT_FORMAT(format) + +#define PICODBG_ASSERT(expr) +#define PICODBG_ASSERT_RANGE(val, min, max) + +#define PICODBG_LOG(level, msg) +#define PICODBG_ERROR(msg) +#define PICODBG_WARN(msg) +#define PICODBG_INFO(msg) +#define PICODBG_DEBUG(msg) +#define PICODBG_TRACE(msg) + +#define PICODBG_INFO_CTX() +#define PICODBG_INFO_MSG(msg) +#define PICODBG_INFO_MSG_F(filterfn, msg) + + +#endif /* defined(PICO_DEBUG) */ + +#ifdef __cplusplus +} +#endif + + +#endif /* !defined(__PICODBG_H__) */ diff --git a/pico/lib/picodefs.h b/pico/lib/picodefs.h new file mode 100644 index 0000000..6613e84 --- /dev/null +++ b/pico/lib/picodefs.h @@ -0,0 +1,173 @@ +/* + * 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 picodefs.h + * + * SVOX Pico definitions + * (SVOX Pico version 1.0 and later) + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + */ + + +#ifndef PICODEFS_H_ +#define PICODEFS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* ********************************************************************/ +/* SVOX Pico limits */ +/* ********************************************************************/ +/* maximum size of a voice name, including the terminating null + character */ +#define PICO_MAX_VOICE_NAME_SIZE 32 + +/* maximum size of a resource name, incl. the terminating null + character */ +#define PICO_MAX_RESOURCE_NAME_SIZE 32 + +/* maximum size of a data path name, incl. the terminating null + character */ +#define PICO_MAX_DATAPATH_NAME_SIZE 128 + +/* maximum size of a file name, incl. the terminating null + character */ +#define PICO_MAX_FILE_NAME_SIZE 64 + +/* maximum number of resources */ +#define PICO_MAX_NUM_RESOURCES 64 + +/* maximum number of voice definitions */ +#define PICO_MAX_NUM_VOICE_DEFINITIONS 64 + +/* maximum number of resources per voice */ +#define PICO_MAX_NUM_RSRC_PER_VOICE 16 + +/* maximum length of foreign header prepended to PICO resource files + (header length must be a multiple of 4 bytes) */ +#define PICO_MAX_FOREIGN_HEADER_LEN 64 + + + +/* ********************************************************************/ +/* SVOX PICO status codes */ +/* ********************************************************************/ + +typedef signed int pico_Status; + + +/* Okay ***************************************************************/ +/* functions return PICO_OK if all is okay */ + +#define PICO_OK (pico_Status) 0 + + +/* Exceptions and error codes *****************************************/ + +/* in case of exceptional events and errors (e.g. unexpected user + input) that disrupt the normal flow of operation, PICO_EXC_* or + PICO_ERR_* are returned. */ + +#define PICO_EXC_NUMBER_FORMAT (pico_Status) -10 +#define PICO_EXC_MAX_NUM_EXCEED (pico_Status) -11 +#define PICO_EXC_NAME_CONFLICT (pico_Status) -12 +#define PICO_EXC_NAME_UNDEFINED (pico_Status) -13 +#define PICO_EXC_NAME_ILLEGAL (pico_Status) -14 + +/* buffer interaction */ +#define PICO_EXC_BUF_OVERFLOW (pico_Status) -20 +#define PICO_EXC_BUF_UNDERFLOW (pico_Status) -21 +#define PICO_EXC_BUF_IGNORE (pico_Status) -22 + +/* internal memory handling */ +#define PICO_EXC_OUT_OF_MEM (pico_Status) -30 + +/* files */ +#define PICO_EXC_CANT_OPEN_FILE (pico_Status) -40 +#define PICO_EXC_UNEXPECTED_FILE_TYPE (pico_Status) -41 +#define PICO_EXC_FILE_CORRUPT (pico_Status) -42 +#define PICO_EXC_FILE_NOT_FOUND (pico_Status) -43 + +/* resources */ +#define PICO_EXC_RESOURCE_BUSY (pico_Status) -50 +#define PICO_EXC_RESOURCE_MISSING (pico_Status) -51 + +/* knowledge bases */ +#define PICO_EXC_KB_MISSING (pico_Status) -60 + +/* runtime exceptions */ +#define PICO_ERR_NULLPTR_ACCESS (pico_Status) -100 +#define PICO_ERR_INVALID_HANDLE (pico_Status) -101 +#define PICO_ERR_INVALID_ARGUMENT (pico_Status) -102 +#define PICO_ERR_INDEX_OUT_OF_RANGE (pico_Status) -103 + +/* other errors ("external" errors, e.g. hardware failure). */ +#define PICO_ERR_OTHER (pico_Status) -999 + + +/* Warnings ***********************************************************/ + +/* general */ +#define PICO_WARN_INCOMPLETE (pico_Status) 10 +#define PICO_WARN_FALLBACK (pico_Status) 11 +#define PICO_WARN_OTHER (pico_Status) 19 + +/* resources */ +#define PICO_WARN_KB_OVERWRITE (pico_Status) 50 +#define PICO_WARN_RESOURCE_DOUBLE_LOAD (pico_Status) 51 + +/* classifiers */ +#define PICO_WARN_INVECTOR (pico_Status) 60 +#define PICO_WARN_CLASSIFICATION (pico_Status) 61 +#define PICO_WARN_OUTVECTOR (pico_Status) 62 + +/* processing units */ +#define PICO_WARN_PU_IRREG_ITEM (pico_Status) 70 +#define PICO_WARN_PU_DISCARD_BUF (pico_Status) 71 + + + +/* ********************************************************************/ +/* Engine getData return values */ +/* ********************************************************************/ + +#define PICO_STEP_IDLE (pico_Status) 200 +#define PICO_STEP_BUSY (pico_Status) 201 + +#define PICO_STEP_ERROR (pico_Status) -200 + + + +/* ********************************************************************/ +/* Engine getData outDataType values */ +/* ********************************************************************/ + +/* 16 bit PCM samples, native endianness of platform */ +#define PICO_DATA_PCM_16BIT (pico_Int16) 1 + +#ifdef __cplusplus +} +#endif + + +#endif /*PICODEFS_H_*/ diff --git a/pico/lib/picodsp.h b/pico/lib/picodsp.h new file mode 100644 index 0000000..67457f8 --- /dev/null +++ b/pico/lib/picodsp.h @@ -0,0 +1,112 @@ +/* + * 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 picodsp.h + * + * Include file for DSP related data types and constants in Pico + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#ifndef PICODSP_H_ +#define PICODSP_H_ + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/*----------------------------CONSTANTS ----------------------*/ +/*Normalization factors used at the start and at the end of the sig*/ +#define PICODSP_START_FLOAT_NORM 0.41f +#define PICODSP_ENVSPEC_K1 0.5f +#define PICODSP_ENVSPEC_K2 2 +#define PICODSP_GETEXC_K1 1024 +#define PICODSP_FIXRESP_NORM 4096.0f +#define PICODSP_END_FLOAT_NORM 1.5f*16.0f +#define PICODSP_FIX_SCALE1 0x4000000 +#define PICODSP_FIX_SCALE2 0x4000 +#define PICODSP_SHIFT_FACT1 10 +#define PICODSP_SHIFT_FACT2 16 +#define PICODSP_SHIFT_FACT3 12 +#define PICODSP_SHIFT_FACT4 1 +#define PICODSP_SHIFT_FACT5 18 +#define PICODSP_SHIFT_FACT6 9 +#define PICOSIG_NORM1 9.14f /100.0f /*normalization factor*/ +#define PICOSIG_MAXAMP (32767) +#define PICOSIG_MINAMP (-32768) +#define PICODSP_M_PI 3.14159265358979323846 +#define PICODSP_MAX_EX 32 +#define PICODSP_WGT_SHIFT (0x20000000) +#define PICODSP_N_RAND_TABLE (760) +#define PICODSP_COS_TABLE_LEN (512) +#define PICODSP_COS_TABLE_LEN2 (1024) +#define PICODSP_COS_TABLE_LEN4 (2048) +#define PICODSP_PI_SHIFT (4) /* -log2(PICODSP_COS_TABLE_LEN2/0x4000) */ + +#define PICODSP_V_CUTOFF_FREQ 4500 +#define PICODSP_UV_CUTOFF_FREQ 300 +#define PICODSP_SAMP_FREQ 16000 +#define PICODSP_FREQ_WARP_FACT 0.42f + +/*----------------------------CEP/PHASE CONSTANTS----------------------------*/ +#define PICODSP_CEPORDER 25 +#define PICODSP_PHASEORDER 72 +#define CEPST_BUFF_SIZE 3 +#define PHASE_BUFF_SIZE 5 +/*----------------------------FFT CONSTANTS----------------------------*/ +#define PICODSP_FFTSIZE (256) + +#define PICODSP_H_FFTSIZE (PICODSP_FFTSIZE/2) + +#define PICODSP_DISPLACE PICODSP_FFTSIZE/4 + +#define PICODSP_H_FFTSIZE (PICODSP_FFTSIZE/2) +#define PICODSP_HFFTSIZE_P1 (PICODSP_H_FFTSIZE+1) + +#define FAST_DEVICE(aCount, aAction) \ +{ \ + int count_ = (aCount); \ + int times_ = (count_ + 7) >> 3; \ + switch (count_ & 7){ \ + case 0: do { aAction; \ + case 7: aAction; \ + case 6: aAction; \ + case 5: aAction; \ + case 4: aAction; \ + case 3: aAction; \ + case 2: aAction; \ + case 1: aAction; \ + } while (--times_ > 0); \ +} \ +} +/*------------------------------------------------------------------------------------------ + Fast Exp Approximation now remapped to a function in picoos + -----------------------------------------------------------------------------------------*/ +#define EXP(y) picoos_quick_exp(y) + +#ifdef __cplusplus +} +#endif + +#endif /*PICODSP_H_*/ diff --git a/pico/lib/picoextapi.c b/pico/lib/picoextapi.c new file mode 100644 index 0000000..4c5d30c --- /dev/null +++ b/pico/lib/picoextapi.c @@ -0,0 +1,228 @@ +/* + * 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 picoextapi.c + * + * API extension for development use + * + * 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 "picoctrl.h" +#include "picodbg.h" +#include "picoapi.h" +#include "picoextapi.h" +#include "picoapid.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/* this is not used anymore. For the picosh banner, set + * progv.progVers in picosh.c instead. */ +#define PICO_VERSION_INFO (picoos_char *)"invalid" + + +extern pico_Status pico_initialize_priv( + void *memory, + const pico_Uint32 size, + pico_Int16 enableMemProt, + pico_System *system); + + +/* System initialization and termination functions ****************************/ + + +PICO_FUNC picoext_initialize( + void *memory, + const pico_Uint32 size, + pico_Int16 enableMemProt, + pico_System *outSystem + ) +{ + return pico_initialize_priv(memory, size, enableMemProt, outSystem); +} + + +/* System and lingware inspection functions ***********************************/ + +/* @todo : not supported yet */ +PICO_FUNC picoext_getVersionInfo( + pico_Retstring outInfo, + const pico_Int16 outInfoMaxLen + ) +{ + if (outInfo == NULL) { + return PICO_ERR_NULLPTR_ACCESS; + } + picoos_strlcpy((picoos_char *) outInfo, PICO_VERSION_INFO, outInfoMaxLen); + return PICO_OK; +} + + +/* Debugging/testing support functions *****************************************/ + + +PICO_FUNC picoext_setTraceLevel( + pico_System system, + pico_Int32 level + ) +{ + if (NULL == system) { + return PICO_ERR_NULLPTR_ACCESS; + } + if (level < 0) { + level = 0; + } + if (level > PICODBG_LOG_LEVEL_TRACE) { + level = PICODBG_LOG_LEVEL_TRACE; + } + PICODBG_SET_LOG_LEVEL(level); + return PICO_OK; +} + + +PICO_FUNC picoext_setTraceFilterFN( + pico_System system, + const pico_Char *name + ) +{ + + if (NULL == system) { + return PICO_ERR_NULLPTR_ACCESS; + } + name = name; /*PP 13.10.08 : fix warning "var not used in this function"*/ + PICODBG_SET_LOG_FILTERFN((const char *)name); + return PICO_OK; +} + + +PICO_FUNC picoext_setLogFile( + pico_System system, + const pico_Char *name + ) +{ + if (NULL == system) { + return PICO_ERR_NULLPTR_ACCESS; + } + name = name; /*PP 13.10.08 : fix warning "var not used in this function"*/ + PICODBG_SET_LOG_FILE((const char *) name); + return PICO_OK; +} + + +/* Memory usage ***************************************************************/ + + +pico_Status getMemUsage( + picoos_Common common, + picoos_bool resetIncremental, + picoos_int32 *usedBytes, + picoos_int32 *incrUsedBytes, + picoos_int32 *maxUsedBytes + ) +{ + pico_Status status = PICO_OK; + + if (common == NULL) { + status = PICO_ERR_NULLPTR_ACCESS; + } else { + picoos_emReset(common->em); + picoos_getMemUsage(common->mm, resetIncremental, usedBytes, incrUsedBytes, maxUsedBytes); + status = picoos_emGetExceptionCode(common->em); + } + + return status; +} + + +PICO_FUNC picoext_getSystemMemUsage( + pico_System system, + pico_Int16 resetIncremental, + pico_Int32 *outUsedBytes, + pico_Int32 *outIncrUsedBytes, + pico_Int32 *outMaxUsedBytes + ) +{ + pico_Status status = PICO_OK; + + if (!is_valid_system_handle(system)) { + status = PICO_ERR_INVALID_HANDLE; + } else if ((outUsedBytes == NULL) || (outIncrUsedBytes == NULL) || (outMaxUsedBytes == NULL)) { + status = PICO_ERR_NULLPTR_ACCESS; + } else { + picoos_Common common = pico_sysGetCommon(system); + status = getMemUsage(common, resetIncremental != 0, outUsedBytes, outIncrUsedBytes, outMaxUsedBytes); + } + + return status; +} + + +PICO_FUNC picoext_getEngineMemUsage( + pico_Engine engine, + pico_Int16 resetIncremental, + pico_Int32 *outUsedBytes, + pico_Int32 *outIncrUsedBytes, + pico_Int32 *outMaxUsedBytes + ) +{ + pico_Status status = PICO_OK; + + if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) { + status = PICO_ERR_INVALID_HANDLE; + } else if ((outUsedBytes == NULL) || (outIncrUsedBytes == NULL) || (outMaxUsedBytes == NULL)) { + status = PICO_ERR_NULLPTR_ACCESS; + } else { + picoos_Common common = picoctrl_engGetCommon((picoctrl_Engine) engine); + status = getMemUsage(common, resetIncremental != 0, outUsedBytes, outIncrUsedBytes, outMaxUsedBytes); + } + + return status; +} + +PICO_FUNC picoext_getLastScheduledPU( + pico_Engine engine + ) +{ + pico_Status status = PICO_OK; + status = picoctrl_getLastScheduledPU((picoctrl_Engine) engine); + return status; +} + +PICO_FUNC picoext_getLastProducedItemType( + pico_Engine engine + ) +{ + pico_Status status = PICO_OK; + status = picoctrl_getLastProducedItemType((picoctrl_Engine) engine); + return status; +} + +#ifdef __cplusplus +} +#endif + +/* end */ diff --git a/pico/lib/picoextapi.h b/pico/lib/picoextapi.h new file mode 100644 index 0000000..1768394 --- /dev/null +++ b/pico/lib/picoextapi.h @@ -0,0 +1,163 @@ +/* + * 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 picoextapi.h + * + * API extensions for development use + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#ifndef PICOEXTAPI_H_ +#define PICOEXTAPI_H_ + +#include "picodefs.h" +#include "picodbg.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* ****************************************************************************/ +/* Things that might be added to picoapi later but should not appear there */ +/* for the time being */ +/* ****************************************************************************/ + +/* String type for Unicode text input *****************************************/ + +/* Unicode encodings supported by PICO. */ + +#define PICO_STRENC_UTF8 0 +#define PICO_STRENC_UTF16 1 + +/* An UTF-8 string must point to a byte array, terminated by a null character + ('\0'). An UTF-16 string must point to a contiguous array of 16-bit units + (in native byte ordering), terminated by a 0. */ + +typedef char *PICO_STRING_UTF8; +typedef pico_Uint16 *PICO_STRING_UTF16; + +/* Generic pointer to a Unicode string, encoded either as UTF-8 or UTF-16. + The application must make sure that for each 'PICO_STRING_PTR' it provides + an argument of type 'PICO_STRING_UTF8' or 'PICO_STRING_UTF16' (or of a type + compatible to one of these types). */ + +typedef void *PICO_STRING_PTR; + + +/* ****************************************************************************/ +/* System-level API functions */ +/* ****************************************************************************/ + +/* System initialization and termination functions ****************************/ + +/* Same as pico_initialize, but allows to enable memory protection + functionality for testing purposes (enableMemProt != 0). */ + +PICO_FUNC picoext_initialize( + void *memory, + const pico_Uint32 size, + pico_Int16 enableMemProt, + pico_System *outSystem + ); + + +/* System and lingware inspection functions ***********************************/ + +/* Returns version information of the current Pico engine. */ + +PICO_FUNC picoext_getVersionInfo( + pico_Retstring outInfo, + const pico_Int16 outInfoMaxLen + ); + +/* Returns unique resource name */ + +/* +PICO_FUNC picoext_getResourceName( + pico_Resource resource, + pico_Retstring outInfo + ); +*/ + +/* Debugging/testing support functions *****************************************/ + +/* Sets tracing level. Increasing amounts of information is displayed + at each level. */ + +PICO_FUNC picoext_setTraceLevel( + pico_System system, + pico_Int32 level + ); + +/* Sets trace filtering. Limits tracing output to tracing information + resulting from the source file name being filtered. */ + +PICO_FUNC picoext_setTraceFilterFN( + pico_System system, + const pico_Char *name + ); + +/* Enables logging of debug output to log file 'name'. If 'name' is NULL + or an empty string, logging is disabled. */ + +PICO_FUNC picoext_setLogFile( + pico_System system, + const pico_Char *name + ); + + +/* Memory usage ***************************************************************/ + +PICO_FUNC picoext_getSystemMemUsage( + pico_System system, + pico_Int16 resetIncremental, + pico_Int32 *outUsedBytes, + pico_Int32 *outIncrUsedBytes, + pico_Int32 *outMaxUsedBytes + ); + +PICO_FUNC picoext_getEngineMemUsage( + pico_Engine engine, + pico_Int16 resetIncremental, + pico_Int32 *outUsedBytes, + pico_Int32 *outIncrUsedBytes, + pico_Int32 *outMaxUsedBytes + ); + +PICO_FUNC picoext_getLastScheduledPU( + pico_Engine engine + ); + +PICO_FUNC picoext_getLastProducedItemType( + pico_Engine engine + ); + +#ifdef __cplusplus +} +#endif + + +#endif /* PICOEXTAPI_H_ */ diff --git a/pico/lib/picofftsg.c b/pico/lib/picofftsg.c new file mode 100644 index 0000000..dcca018 --- /dev/null +++ b/pico/lib/picofftsg.c @@ -0,0 +1,3274 @@ +/* + * 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 picofftsg.c + * + * FFT/DCT related data types, constants and functions in Pico + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * +*/ + +#include "picoos.h" +#include "picofftsg.h" +#include "picodbg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup picofft + * ---------------------------------------------------\n + * Fast Fourier/Cosine/Sine Transform \n + * Adapted from http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html (Copyright Takuya OOURA, 1996-2001)\n + * ---------------------------------------------------\n + + Overall features + - dimension :one + - data length :power of 2 + - decimation :frequency + - radix :split-radix + - data :inplace + - table :not use + + functions + - cdft: Complex Discrete Fourier Transform + - rdft: Real Discrete Fourier Transform + - ddct: Discrete Cosine Transform + - ddst: Discrete Sine Transform + - dfct: Cosine Transform of RDFT (Real Symmetric DFT) + - dfst: Sine Transform of RDFT (Real Anti-symmetric DFT) + + function prototypes + - void cdft(picoos_int32, picoos_int32, PICOFFTSG_FFTTYPE *); + - void rdft(picoos_int32, picoos_int32, PICOFFTSG_FFTTYPE *); + - void ddct(picoos_int32, picoos_int32, PICOFFTSG_FFTTYPE *); + - void ddst(picoos_int32, picoos_int32, PICOFFTSG_FFTTYPE *); + - void dfct(picoos_int32, PICOFFTSG_FFTTYPE *); + - void dfst(picoos_int32, PICOFFTSG_FFTTYPE *); + + Complex DFT (Discrete Fourier Transform) + + [definition] + - + - X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k + - X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k + - cdft(2*n, 1, a); + - + - cdft(2*n, -1, a); + + [parameters] + - 2*n :data length (picoos_int32) + - n >= 1, n = power of 2 + - a[0...2*n-1] :input/output data (PICOFFTSG_FFTTYPE *) + - input data + - a[2*j] = Re(x[j]), + - a[2*j+1] = Im(x[j]), 0<=j Real DFT / Inverse of Real DFT + + [definition] + - RDFT + - R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2 + - I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0 IRDFT (excluding scale) + - a[k] = (R[0] + R[n/2]*cos(pi*k))/2 + + - sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) + + - sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k + - rdft(n, 1, a); + - + - rdft(n, -1, a); + + [parameters] + - n :data length (picoos_int32) + - n >= 2, n = power of 2 + - a[0...n-1] :input/output data (PICOFFTSG_FFTTYPE *) + - + - output data + - a[2*k] = R[k], 0<=k + - input data + - a[2*j] = R[j], 0<=j DCT (Discrete Cosine Transform) / Inverse of DCT + + [definition] + - IDCT (excluding scale) + - C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k DCT + - C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k + - ddct(n, 1, a); + - + - ddct(n, -1, a); + + [parameters] + - n :data length (picoos_int32) + - n >= 2, n = power of 2 + - a[0...n-1] :input/output data (PICOFFTSG_FFTTYPE *) + - output data + - a[k] = C[k], 0<=k DST (Discrete Sine Transform) / Inverse of DST + + [definition] + - IDST (excluding scale) + - S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k DST + - S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0 + - ddst(n, 1, a); + - + - ddst(n, -1, a); + + [parameters] + - n :data length (picoos_int32) + - n >= 2, n = power of 2 + - a[0...n-1] :input/output data (PICOFFTSG_FFTTYPE *) + - + - input data + - a[j] = A[j], 0 + - output data + - a[k] = S[k], 0 Cosine Transform of RDFT (Real Symmetric DFT) + + [definition] + - C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n + + [usage] + - dfct(n, a); + + [parameters] + - n :data length - 1 (picoos_int32) + - n >= 2, n = power of 2 + - a[0...n] :input/output data (PICOFFTSG_FFTTYPE *) + + - output data + - a[k] = C[k], 0<=k<=n + + [remark] + - Inverse of a[0] *= 0.5; a[n] *= 0.5; dfct(n, a); is + - a[0] *= 0.5; + - a[n] *= 0.5; + - dfct(n, a); + - for (j = 0; j <= n; j++) { + - a[j] *= 2.0 / n; + - } + + Sine Transform of RDFT (Real Anti-symmetric DFT) + + [definition] + - S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0= 2, n = power of 2 + - a[0...n-1] :input/output data (PICOFFTSG_FFTTYPE *) + - output data + - a[k] = S[k], 0=POW17?(x>=POW25?(x>=POW29?(x>=POW31?31:(x>=POW30?30:29)):(x>=POW27?(x>=POW28?28:27):(x>=POW26?26:25))):(x>=POW21?(x>=POW23?(x>=POW24?24:23):(x>=POW22?22:21)):(x>=POW19?(x>=POW20?20:19):(x>=POW18?18:17)))):(x>=POW9?(x>=POW13?(x>=POW15?(x>=POW16?16:15):(x>=POW14?14:13)):(x>=POW11?(x>=POW12?12:11):(x>=POW10?10:9))):(x>=POW5?(x>=POW7?(x>=POW8?8:7):(x>=POW6?6:5)):(x>=POW3?(x>=POW4?4:3):(x>=POW2?2:1)))))) +#define picofftsg_highestBit(x) (x==0?0:(x<0?(zz=-x,(zz>=POW17?(zz>=POW25?(zz>=POW29?(zz>=POW31?31:(zz>=POW30?30:29)):(zz>=POW27?(zz>=POW28?28:27):(zz>=POW26?26:25))):(zz>=POW21?(zz>=POW23?(zz>=POW24?24:23):(zz>=POW22?22:21)):(zz>=POW19?(zz>=POW20?20:19):(zz>=POW18?18:17)))):(zz>=POW9?(zz>=POW13?(zz>=POW15?(zz>=POW16?16:15):(zz>=POW14?14:13)):(zz>=POW11?(zz>=POW12?12:11):(zz>=POW10?10:9))):(zz>=POW5?(zz>=POW7?(zz>=POW8?8:7):(zz>=POW6?6:5)):(zz>=POW3?(zz>=POW4?4:3):(zz>=POW2?2:1)))))):(x>=POW17?(x>=POW25?(x>=POW29?(x>=POW31?31:(x>=POW30?30:29)):(x>=POW27?(x>=POW28?28:27):(x>=POW26?26:25))):(x>=POW21?(x>=POW23?(x>=POW24?24:23):(x>=POW22?22:21)):(x>=POW19?(x>=POW20?20:19):(x>=POW18?18:17)))):(x>=POW9?(x>=POW13?(x>=POW15?(x>=POW16?16:15):(x>=POW14?14:13)):(x>=POW11?(x>=POW12?12:11):(x>=POW10?10:9))):(x>=POW5?(x>=POW7?(x>=POW8?8:7):(x>=POW6?6:5)):(x>=POW3?(x>=POW4?4:3):(x>=POW2?2:1))))))) +#define Mult_W_W picofftsg_mult_w_w + + +/* ***********************************************************************************************/ +/* forward declarations */ +/* ***********************************************************************************************/ +static PICOFFTSG_FFTTYPE picofftsg_mult_w_w(PICOFFTSG_FFTTYPE x1, PICOFFTSG_FFTTYPE y1); +static PICOFFTSG_FFTTYPE picofftsg_mult_w_a(PICOFFTSG_FFTTYPE x1, PICOFFTSG_FFTTYPE y1); + + +static void cftfsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void cftbsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void rftfsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void rftbsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); + +static void cftfsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void cftbsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void rftfsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void rftbsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void dctsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void dctsub4(picoos_int32 n, PICOFFTSG_FFTTYPE *a); + +static void ddct(picoos_int32 n, picoos_int32 isgn, PICOFFTSG_FFTTYPE *a); +static void bitrv1(picoos_int32 n, PICOFFTSG_FFTTYPE *a); + +static void bitrv2(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void bitrv216(PICOFFTSG_FFTTYPE *a); +static void bitrv208(PICOFFTSG_FFTTYPE *a); +static void cftmdl1(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void cftrec4(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void cftleaf(picoos_int32 n, picoos_int32 isplt, PICOFFTSG_FFTTYPE *a); +static void cftfx41(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void cftf161(PICOFFTSG_FFTTYPE *a); +static void cftf081(PICOFFTSG_FFTTYPE *a); +static void cftf040(PICOFFTSG_FFTTYPE *a); +static void cftx020(PICOFFTSG_FFTTYPE *a); + +void bitrv2conj(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +void bitrv216neg(PICOFFTSG_FFTTYPE *a); +void bitrv208neg(PICOFFTSG_FFTTYPE *a); +void cftb1st(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +void cftrec4(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +void cftleaf(picoos_int32 n, picoos_int32 isplt, PICOFFTSG_FFTTYPE *a); +void cftfx41(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +void cftf161(PICOFFTSG_FFTTYPE *a); +void cftf081(PICOFFTSG_FFTTYPE *a); +void cftb040(PICOFFTSG_FFTTYPE *a); +void cftx020(PICOFFTSG_FFTTYPE *a); + +static picoos_int32 cfttree(picoos_int32 n, picoos_int32 j, picoos_int32 k, PICOFFTSG_FFTTYPE *a); +static void cftleaf(picoos_int32 n, picoos_int32 isplt, PICOFFTSG_FFTTYPE *a); +static void cftmdl1(picoos_int32 n, PICOFFTSG_FFTTYPE *a); + +static void cftmdl1(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void cftmdl2(picoos_int32 n, PICOFFTSG_FFTTYPE *a); + +static void cftmdl1(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void cftmdl2(picoos_int32 n, PICOFFTSG_FFTTYPE *a); +static void cftf161(PICOFFTSG_FFTTYPE *a); +static void cftf162(PICOFFTSG_FFTTYPE *a); +static void cftf081(PICOFFTSG_FFTTYPE *a); +static void cftf082(PICOFFTSG_FFTTYPE *a); + +static void cftf161(PICOFFTSG_FFTTYPE *a); +static void cftf162(PICOFFTSG_FFTTYPE *a); +static void cftf081(PICOFFTSG_FFTTYPE *a); +static void cftf082(PICOFFTSG_FFTTYPE *a); + +/* ***********************************************************************************************/ +/* Exported functions */ +/* ***********************************************************************************************/ +void rdft(picoos_int32 n, picoos_int32 isgn, PICOFFTSG_FFTTYPE *a) +{ + PICOFFTSG_FFTTYPE xi; + + if (isgn >= 0) { + if (n > 4) { + cftfsub(n, a); + rftfsub(n, a); + } else if (n == 4) { + cftfsub(n, a); + } + xi = a[0] - a[1]; + a[0] += a[1]; + a[1] = xi; + } else { + a[1] = (a[0] - a[1]) / 2; + a[0] -= a[1]; + if (n > 4) { + rftbsub(n, a); + cftbsub(n, a); + } else if (n == 4) { + cftbsub(n, a); + } + } + +} + + +picoos_single norm_result(picoos_int32 m2, PICOFFTSG_FFTTYPE *tmpX, PICOFFTSG_FFTTYPE *norm_window) +{ + picoos_int16 nI; + PICOFFTSG_FFTTYPE a,b, E; + + E = (picoos_int32)0; + for (nI=0; nI>18) * ((tmpX[nI]>0) ? tmpX[nI]>>11 : -((-tmpX[nI])>>11)); + tmpX[nI] = a; + b = (a>=0?a:-a) >> 18; + E += (b*b); + } + + if (E>0) { + return (picoos_single)sqrt((double)E/16.0)/m2; + } + else { + return 0.0; + } +} + +void ddct(picoos_int32 n, picoos_int32 isgn, PICOFFTSG_FFTTYPE *a) +{ + picoos_int32 j; + PICOFFTSG_FFTTYPE xr; + + if (isgn < 0) { + xr = a[n - 1]; + for (j = n - 2; j >= 2; j -= 2) { + a[j + 1] = a[j] - a[j - 1]; + a[j] += a[j - 1]; + } + a[1] = a[0] - xr; + a[0] += xr; + if (n > 4) { + rftbsub(n, a); + cftbsub(n, a); + } else if (n == 4) { + cftbsub(n, a); + } + } + if (n > 4) { + dctsub(n, a); + } else { + dctsub4(n, a); + } + if (isgn >= 0) { + if (n > 4) { + cftfsub(n, a); + rftfsub(n, a); + } else if (n == 4) { + cftfsub(n, a); + } + + + xr = a[0] - a[1]; + a[0] += a[1]; + for (j = 2; j < n; j += 2) { + a[j - 1] = a[j] - a[j + 1]; + a[j] += a[j + 1]; + } + a[n - 1] = xr; + } +} + +void dfct_nmf(picoos_int32 n, picoos_int32 *a) +{ + picoos_int32 j, k, m, mh; + PICOFFTSG_FFTTYPE xr, xi, yr, yi, an; + PICOFFTSG_FFTTYPE *aj, *ak, *amj, *amk; + + m = n >> 1; + for (j = 0; j < m; j++) { + k = n - j; + xr = a[j] + a[k]; + a[j] -= a[k]; + a[k] = xr; + } + an = a[n]; + while (m >= 2) { + ddct(m, 1, a); + if (m > 2) { + bitrv1(m, a); + } + mh = m >> 1; + xi = a[m]; + a[m] = a[0]; + a[0] = an - xi; + an += xi; + k = m-1; + aj = a + 1; ak = a + k; amj = aj + m; amk = ak + m; + for (j = 1; j < mh; j++, aj++, ak--, amj++, amk--) { + xr = *amk; + xi = *amj; + yr = *aj; + yi = *ak; + *amj = yr; + *amk = yi; + *aj = xr - xi; + *ak = xr + xi; + } + xr = *aj; + *aj = *amj; + *amj = xr; + + m = mh; + } + + xi = a[1]; + a[1] = a[0]; + a[0] = an + xi; + a[n] = an - xi; + if (n > 2) { + bitrv1(n, a); + } + +} + +/* ***********************************************************************************************/ +/* internal routines */ +/* ***********************************************************************************************/ +/* + mult two numbers which are guaranteed to be in the range -1..1 + shift right as little as possible before mult, and the rest after the mult + Also, shift bigger number more - lose less accuracy + */ +static PICOFFTSG_FFTTYPE picofftsg_mult_w_w(PICOFFTSG_FFTTYPE x1, PICOFFTSG_FFTTYPE y1) +{ + PICOFFTSG_FFTTYPE x, y; + x = x1>=0 ? x1>>15 : -((-x1)>>15); + y = y1>=0 ? y1>>14 : -((-y1)>>14); + return x * y; +} + +static PICOFFTSG_FFTTYPE picofftsg_mult_w_a(PICOFFTSG_FFTTYPE x1, PICOFFTSG_FFTTYPE y1) +{ + PICOFFTSG_FFTTYPE x, y; + + + x = x1>=0 ? x1>>15 : -((-x1)>>15); + y = y1>=0 ? y1>>14 : -((-y1)>>14); + return x * y; +} + +static void cftfsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a) +{ + + if (n > 8) { + if (n > 32) { + cftmdl1(n, a); + if (n > 512) { + cftrec4(n, a); + } else if (n > 128) { + cftleaf(n, 1, a); + } else { + cftfx41(n, a); + } + bitrv2(n, a); + } else if (n == 32) { + cftf161(a); + bitrv216(a); + } else { + cftf081(a); + bitrv208(a); + } + } else if (n == 8) { + cftf040(a); + } else if (n == 4) { + cftx020(a); + } +} + + +void cftbsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a) +{ + if (n > 8) { + if (n > 32) { + cftb1st(n, a); + if (n > 512) { + cftrec4(n, a); + } else if (n > 128) { + cftleaf(n, 1, a); + } else { + cftfx41(n, a); + } + bitrv2conj(n, a); + } else if (n == 32) { + cftf161(a); + bitrv216neg(a); + } else { + cftf081(a); + bitrv208neg(a); + } + } else if (n == 8) { + cftb040(a); + } else if (n == 4) { + cftx020(a); + } +} + +/* **************************************************************************************************/ + +/* **************************************************************************************************/ +void bitrv2(picoos_int32 n, PICOFFTSG_FFTTYPE *a) +{ + picoos_int32 j0, k0, j1, k1, l, m, i, j, k, nh, m2; + PICOFFTSG_FFTTYPE xr, xi, yr, yi; + + m = 4; + for (l = n >> 2; l > 8; l >>= 2) { + m <<= 1; + } + m2 = m + m; + nh = n >> 1; + if (l == 8) { + j0 = 0; + for (k0 = 0; k0 < m; k0 += 4) { + k = k0; + for (j = j0; j < j0 + k0; j += 4) { + xr = a[j]; + xi = a[j + 1]; + yr = a[k]; + yi = a[k + 1]; + a[j] = yr; + a[j + 1] = yi; + a[k] = xr; + a[k + 1] = xi; + j1 = j + m; + k1 = k + m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 -= m; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 += m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nh; + k1 += 2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 -= m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 += m; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 -= m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += 2; + k1 += nh; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 += m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 -= m; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 += m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nh; + k1 -= 2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 -= m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 += m; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 -= m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + for (i = nh >> 1; i > (k ^= i); i >>= 1) { + /* Avoid warning*/ + }; + } + k1 = j0 + k0; + j1 = k1 + 2; + k1 += nh; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 += m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 -= m; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= 2; + k1 -= nh; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nh + 2; + k1 += nh + 2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nh - m; + k1 += m2 - 2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + for (i = nh >> 1; i > (j0 ^= i); i >>= 1) { + /* Avoid warning */ + } + } + } else { + j0 = 0; + for (k0 = 0; k0 < m; k0 += 4) { + k = k0; + for (j = j0; j < j0 + k0; j += 4) { + xr = a[j]; + xi = a[j + 1]; + yr = a[k]; + yi = a[k + 1]; + a[j] = yr; + a[j + 1] = yi; + a[k] = xr; + a[k + 1] = xi; + j1 = j + m; + k1 = k + m; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nh; + k1 += 2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 -= m; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += 2; + k1 += nh; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 += m; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nh; + k1 -= 2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 -= m; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + for (i = nh >> 1; i > (k ^= i); i >>= 1){ + /* Avoid warning */ + } + } + k1 = j0 + k0; + j1 = k1 + 2; + k1 += nh; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 += m; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + for (i = nh >> 1; i > (j0 ^= i); i >>= 1){ + /* Avoid warning */ + } + } + } +} + + +void bitrv2conj(picoos_int32 n, PICOFFTSG_FFTTYPE *a) +{ + picoos_int32 j0, k0, j1, k1, l, m, i, j, k, nh, m2; + PICOFFTSG_FFTTYPE xr, xi, yr, yi; + + + m = 4; + for (l = n >> 2; l > 8; l >>= 2) { + m <<= 1; + } + m2 = m + m; + nh = n >> 1; + if (l == 8) { + j0 = 0; + for (k0 = 0; k0 < m; k0 += 4) { + k = k0; + for (j = j0; j < j0 + k0; j += 4) { + xr = a[j]; + xi = -a[j + 1]; + yr = a[k]; + yi = -a[k + 1]; + a[j] = yr; + a[j + 1] = yi; + a[k] = xr; + a[k + 1] = xi; + j1 = j + m; + k1 = k + m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 -= m; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 += m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nh; + k1 += 2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 -= m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 += m; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 -= m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += 2; + k1 += nh; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 += m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 -= m; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 += m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nh; + k1 -= 2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 -= m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 += m; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 -= m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + for (i = nh >> 1; i > (k ^= i); i >>= 1) { + /* Avoid warning */ + } + } + k1 = j0 + k0; + j1 = k1 + 2; + k1 += nh; + a[j1 - 1] = -a[j1 - 1]; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + a[k1 + 3] = -a[k1 + 3]; + j1 += m; + k1 += m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 -= m; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= 2; + k1 -= nh; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nh + 2; + k1 += nh + 2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nh - m; + k1 += m2 - 2; + a[j1 - 1] = -a[j1 - 1]; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + a[k1 + 3] = -a[k1 + 3]; + for (i = nh >> 1; i > (j0 ^= i); i >>= 1) { /* Avoid warning*/ + + } + } + } else { + j0 = 0; + for (k0 = 0; k0 < m; k0 += 4) { + k = k0; + for (j = j0; j < j0 + k0; j += 4) { + xr = a[j]; + xi = -a[j + 1]; + yr = a[k]; + yi = -a[k + 1]; + a[j] = yr; + a[j + 1] = yi; + a[k] = xr; + a[k + 1] = xi; + j1 = j + m; + k1 = k + m; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += nh; + k1 += 2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 -= m; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += 2; + k1 += nh; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m; + k1 += m; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= nh; + k1 -= 2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 -= m; + k1 -= m; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + for (i = nh >> 1; i > (k ^= i); i >>= 1) { + /* Avoid warning*/ + } + } + k1 = j0 + k0; + j1 = k1 + 2; + k1 += nh; + a[j1 - 1] = -a[j1 - 1]; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + a[k1 + 3] = -a[k1 + 3]; + j1 += m; + k1 += m; + a[j1 - 1] = -a[j1 - 1]; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + a[k1 + 3] = -a[k1 + 3]; + for (i = nh >> 1; i > (j0 ^= i); i >>= 1) { + /* Avoid warning*/ + } + } + } +} + + +void bitrv216(PICOFFTSG_FFTTYPE *a) +{ + PICOFFTSG_FFTTYPE x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, + x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i, + x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i; + + x1r = a[2]; + x1i = a[3]; + x2r = a[4]; + x2i = a[5]; + x3r = a[6]; + x3i = a[7]; + x4r = a[8]; + x4i = a[9]; + x5r = a[10]; + x5i = a[11]; + x7r = a[14]; + x7i = a[15]; + x8r = a[16]; + x8i = a[17]; + x10r = a[20]; + x10i = a[21]; + x11r = a[22]; + x11i = a[23]; + x12r = a[24]; + x12i = a[25]; + x13r = a[26]; + x13i = a[27]; + x14r = a[28]; + x14i = a[29]; + a[2] = x8r; + a[3] = x8i; + a[4] = x4r; + a[5] = x4i; + a[6] = x12r; + a[7] = x12i; + a[8] = x2r; + a[9] = x2i; + a[10] = x10r; + a[11] = x10i; + a[14] = x14r; + a[15] = x14i; + a[16] = x1r; + a[17] = x1i; + a[20] = x5r; + a[21] = x5i; + a[22] = x13r; + a[23] = x13i; + a[24] = x3r; + a[25] = x3i; + a[26] = x11r; + a[27] = x11i; + a[28] = x7r; + a[29] = x7i; +} + + +void bitrv216neg(PICOFFTSG_FFTTYPE *a) +{ + PICOFFTSG_FFTTYPE x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, + x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i, + x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, + x13r, x13i, x14r, x14i, x15r, x15i; + + x1r = a[2]; + x1i = a[3]; + x2r = a[4]; + x2i = a[5]; + x3r = a[6]; + x3i = a[7]; + x4r = a[8]; + x4i = a[9]; + x5r = a[10]; + x5i = a[11]; + x6r = a[12]; + x6i = a[13]; + x7r = a[14]; + x7i = a[15]; + x8r = a[16]; + x8i = a[17]; + x9r = a[18]; + x9i = a[19]; + x10r = a[20]; + x10i = a[21]; + x11r = a[22]; + x11i = a[23]; + x12r = a[24]; + x12i = a[25]; + x13r = a[26]; + x13i = a[27]; + x14r = a[28]; + x14i = a[29]; + x15r = a[30]; + x15i = a[31]; + a[2] = x15r; + a[3] = x15i; + a[4] = x7r; + a[5] = x7i; + a[6] = x11r; + a[7] = x11i; + a[8] = x3r; + a[9] = x3i; + a[10] = x13r; + a[11] = x13i; + a[12] = x5r; + a[13] = x5i; + a[14] = x9r; + a[15] = x9i; + a[16] = x1r; + a[17] = x1i; + a[18] = x14r; + a[19] = x14i; + a[20] = x6r; + a[21] = x6i; + a[22] = x10r; + a[23] = x10i; + a[24] = x2r; + a[25] = x2i; + a[26] = x12r; + a[27] = x12i; + a[28] = x4r; + a[29] = x4i; + a[30] = x8r; + a[31] = x8i; +} + + +void bitrv208(PICOFFTSG_FFTTYPE *a) +{ + PICOFFTSG_FFTTYPE x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i; + + x1r = a[2]; + x1i = a[3]; + x3r = a[6]; + x3i = a[7]; + x4r = a[8]; + x4i = a[9]; + x6r = a[12]; + x6i = a[13]; + a[2] = x4r; + a[3] = x4i; + a[6] = x6r; + a[7] = x6i; + a[8] = x1r; + a[9] = x1i; + a[12] = x3r; + a[13] = x3i; +} + + +void bitrv208neg(PICOFFTSG_FFTTYPE *a) +{ + PICOFFTSG_FFTTYPE x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, + x5r, x5i, x6r, x6i, x7r, x7i; + + x1r = a[2]; + x1i = a[3]; + x2r = a[4]; + x2i = a[5]; + x3r = a[6]; + x3i = a[7]; + x4r = a[8]; + x4i = a[9]; + x5r = a[10]; + x5i = a[11]; + x6r = a[12]; + x6i = a[13]; + x7r = a[14]; + x7i = a[15]; + a[2] = x7r; + a[3] = x7i; + a[4] = x3r; + a[5] = x3i; + a[6] = x5r; + a[7] = x5i; + a[8] = x1r; + a[9] = x1i; + a[10] = x6r; + a[11] = x6i; + a[12] = x2r; + a[13] = x2i; + a[14] = x4r; + a[15] = x4i; +} + + +void bitrv1(picoos_int32 n, PICOFFTSG_FFTTYPE *a) +{ + picoos_int32 j0, k0, j1, k1, l, m, i, j, k, nh; + PICOFFTSG_FFTTYPE x; + nh = n >> 1; + x = a[1]; + a[1] = a[nh]; + a[nh] = x; + m = 2; + for (l = n >> 2; l > 2; l >>= 2) { + m <<= 1; + } + if (l == 2) { + j1 = m + 1; + k1 = m + nh; + x = a[j1]; + a[j1] = a[k1]; + a[k1] = x; + j0 = 0; + for (k0 = 2; k0 < m; k0 += 2) { + for (i = nh >> 1; i > (j0 ^= i); i >>= 1) { + /* Avoid warning*/ + } + k = k0; + for (j = j0; j < j0 + k0; j += 2) { + x = a[j]; + a[j] = a[k]; + a[k] = x; + j1 = j + m; + k1 = k + m; + x = a[j1]; + a[j1] = a[k1]; + a[k1] = x; + j1 += nh; + k1++; + x = a[j1]; + a[j1] = a[k1]; + a[k1] = x; + j1 -= m; + k1 -= m; + x = a[j1]; + a[j1] = a[k1]; + a[k1] = x; + j1++; + k1 += nh; + x = a[j1]; + a[j1] = a[k1]; + a[k1] = x; + j1 += m; + k1 += m; + x = a[j1]; + a[j1] = a[k1]; + a[k1] = x; + j1 -= nh; + k1--; + x = a[j1]; + a[j1] = a[k1]; + a[k1] = x; + j1 -= m; + k1 -= m; + x = a[j1]; + a[j1] = a[k1]; + a[k1] = x; + for (i = nh >> 1; i > (k ^= i); i >>= 1) { + /* Avoid warning*/ + } + } + k1 = j0 + k0; + j1 = k1 + 1; + k1 += nh; + x = a[j1]; + a[j1] = a[k1]; + a[k1] = x; + j1 += m; + k1 += m; + x = a[j1]; + a[j1] = a[k1]; + a[k1] = x; + } + } else { + j0 = 0; + for (k0 = 2; k0 < m; k0 += 2) { + for (i = nh >> 1; i > (j0 ^= i); i >>= 1) { + /* Avoid warning*/ + } + k = k0; + for (j = j0; j < j0 + k0; j += 2) { + x = a[j]; + a[j] = a[k]; + a[k] = x; + j1 = j + nh; + k1 = k + 1; + x = a[j1]; + a[j1] = a[k1]; + a[k1] = x; + j1++; + k1 += nh; + x = a[j1]; + a[j1] = a[k1]; + a[k1] = x; + j1 -= nh; + k1--; + x = a[j1]; + a[j1] = a[k1]; + a[k1] = x; + for (i = nh >> 1; i > (k ^= i); i >>= 1) { + /* Avoid warning*/ + } + } + k1 = j0 + k0; + j1 = k1 + 1; + k1 += nh; + x = a[j1]; + a[j1] = a[k1]; + a[k1] = x; + } + } +} + + +/* **************************************************************************************************/ + +/* **************************************************************************************************/ + +void cftb1st(picoos_int32 n, PICOFFTSG_FFTTYPE *a) +{ + picoos_int32 i, i0, j, j0, j1, j2, j3, m, mh; + PICOFFTSG_FFTTYPE wk1r, wk1i, wk3r, wk3i, + wd1r, wd1i, wd3r, wd3i, ss1, ss3; + PICOFFTSG_FFTTYPE x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + mh = n >> 3; + m = 2 * mh; + j1 = m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[0] + a[j2]; + x0i = -a[1] - a[j2 + 1]; + x1r = a[0] - a[j2]; + x1i = -a[1] + a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[0] = x0r + x2r; + a[1] = x0i - x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i + x2i; + a[j2] = x1r + x3i; + a[j2 + 1] = x1i + x3r; + a[j3] = x1r - x3i; + a[j3 + 1] = x1i - x3r; + wd1r = PICODSP_WGT_SHIFT; + wd1i = 0; + wd3r = PICODSP_WGT_SHIFT; + wd3i = 0; + + wk1r = (PICOFFTSG_FFTTYPE) (0.998795449734 *PICODSP_WGT_SHIFT); + wk1i = (PICOFFTSG_FFTTYPE) (0.049067676067 *PICODSP_WGT_SHIFT); + ss1 = (PICOFFTSG_FFTTYPE) (0.098135352135 *PICODSP_WGT_SHIFT); + wk3i = (PICOFFTSG_FFTTYPE) (-0.146730467677 *PICODSP_WGT_SHIFT); + wk3r = (PICOFFTSG_FFTTYPE) (0.989176511765 *PICODSP_WGT_SHIFT); + ss3 = (PICOFFTSG_FFTTYPE) (-0.293460935354 *PICODSP_WGT_SHIFT); + + i = 0; + for (;;) { + i0 = i + CDFT_LOOP_DIV_4; + if (i0 > mh - 4) { + i0 = mh - 4; + } + for (j = i + 2; j < i0; j += 4) { + + wd1r -= Mult_W_W(ss1, wk1i); + wd1i += Mult_W_W(ss1, wk1r); + wd3r -= Mult_W_W(ss3, wk3i); + wd3i += Mult_W_W(ss3, wk3r); + + j1 = j + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j] + a[j2]; + x0i = -a[j + 1] - a[j2 + 1]; + x1r = a[j] - a[j2]; + x1i = -a[j + 1] + a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i - x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i + x2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2] = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); + a[j2 + 1] = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3] = Mult_W_W(wk3r, x0r) + Mult_W_W(wk3i, x0i); + a[j3 + 1] = Mult_W_W(wk3r, x0i) - Mult_W_W(wk3i, x0r); + x0r = a[j + 2] + a[j2 + 2]; + x0i = -a[j + 3] - a[j2 + 3]; + x1r = a[j + 2] - a[j2 + 2]; + x1i = -a[j + 3] + a[j2 + 3]; + x2r = a[j1 + 2] + a[j3 + 2]; + x2i = a[j1 + 3] + a[j3 + 3]; + x3r = a[j1 + 2] - a[j3 + 2]; + x3i = a[j1 + 3] - a[j3 + 3]; + a[j + 2] = x0r + x2r; + a[j + 3] = x0i - x2i; + a[j1 + 2] = x0r - x2r; + a[j1 + 3] = x0i + x2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2 + 2] = Mult_W_W(wd1r, x0r) - Mult_W_W(wd1i, x0i); + a[j2 + 3] = Mult_W_W(wd1r, x0i) + Mult_W_W(wd1i, x0r); + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3 + 2] = Mult_W_W(wd3r, x0r) + Mult_W_W(wd3i, x0i); + a[j3 + 3] = Mult_W_W(wd3r, x0i) - Mult_W_W(wd3i, x0r); + j0 = m - j; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] + a[j2]; + x0i = -a[j0 + 1] - a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = -a[j0 + 1] + a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i - x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i + x2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2] = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); + a[j2 + 1] = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3] = Mult_W_W(wk3i, x0r) + Mult_W_W(wk3r, x0i); + a[j3 + 1] = Mult_W_W(wk3i, x0i) - Mult_W_W(wk3r, x0r); + x0r = a[j0 - 2] + a[j2 - 2]; + x0i = -a[j0 - 1] - a[j2 - 1]; + x1r = a[j0 - 2] - a[j2 - 2]; + x1i = -a[j0 - 1] + a[j2 - 1]; + x2r = a[j1 - 2] + a[j3 - 2]; + x2i = a[j1 - 1] + a[j3 - 1]; + x3r = a[j1 - 2] - a[j3 - 2]; + x3i = a[j1 - 1] - a[j3 - 1]; + a[j0 - 2] = x0r + x2r; + a[j0 - 1] = x0i - x2i; + a[j1 - 2] = x0r - x2r; + a[j1 - 1] = x0i + x2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2 - 2] = Mult_W_W(wd1i, x0r) - Mult_W_W(wd1r, x0i); + a[j2 - 1] = Mult_W_W(wd1i, x0i) + Mult_W_W(wd1r, x0r); + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3 - 2] = Mult_W_W(wd3i, x0r) + Mult_W_W(wd3r, x0i); + a[j3 - 1] = Mult_W_W(wd3i, x0i) - Mult_W_W(wd3r, x0r); + wk1r -= Mult_W_W(ss1, wd1i); + wk1i += Mult_W_W(ss1, wd1r); + wk3r -= Mult_W_W(ss3, wd3i); + wk3i += Mult_W_W(ss3, wd3r); + } + if (i0 == mh - 4) { + break; + } + } + wd1r = WR5000; + j0 = mh; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0 - 2] + a[j2 - 2]; + x0i = -a[j0 - 1] - a[j2 - 1]; + x1r = a[j0 - 2] - a[j2 - 2]; + x1i = -a[j0 - 1] + a[j2 - 1]; + x2r = a[j1 - 2] + a[j3 - 2]; + x2i = a[j1 - 1] + a[j3 - 1]; + x3r = a[j1 - 2] - a[j3 - 2]; + x3i = a[j1 - 1] - a[j3 - 1]; + a[j0 - 2] = x0r + x2r; + a[j0 - 1] = x0i - x2i; + a[j1 - 2] = x0r - x2r; + a[j1 - 1] = x0i + x2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2 - 2] = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); + a[j2 - 1] = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3 - 2] = Mult_W_W(wk3r, x0r) + Mult_W_W(wk3i, x0i); + a[j3 - 1] = Mult_W_W(wk3r, x0i) - Mult_W_W(wk3i, x0r); + x0r = a[j0] + a[j2]; + x0i = -a[j0 + 1] - a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = -a[j0 + 1] + a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i - x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i + x2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2] = picofftsg_mult_w_a(wd1r, (x0r - x0i)); + a[j2 + 1] = picofftsg_mult_w_a(wd1r, (x0i + x0r)); + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3] = -picofftsg_mult_w_a(wd1r, (x0r + x0i)); + a[j3 + 1] = -picofftsg_mult_w_a(wd1r, (x0i - x0r)); + x0r = a[j0 + 2] + a[j2 + 2]; + x0i = -a[j0 + 3] - a[j2 + 3]; + x1r = a[j0 + 2] - a[j2 + 2]; + x1i = -a[j0 + 3] + a[j2 + 3]; + x2r = a[j1 + 2] + a[j3 + 2]; + x2i = a[j1 + 3] + a[j3 + 3]; + x3r = a[j1 + 2] - a[j3 + 2]; + x3i = a[j1 + 3] - a[j3 + 3]; + a[j0 + 2] = x0r + x2r; + a[j0 + 3] = x0i - x2i; + a[j1 + 2] = x0r - x2r; + a[j1 + 3] = x0i + x2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2 + 2] = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); + a[j2 + 3] = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3 + 2] = Mult_W_W(wk3i, x0r) + Mult_W_W(wk3r, x0i); + a[j3 + 3] = Mult_W_W(wk3i, x0i) - Mult_W_W(wk3r, x0r); +} + +void cftrec4(picoos_int32 n, PICOFFTSG_FFTTYPE *a) +{ + picoos_int32 isplt, j, k, m; + + m = n; + while (m > 512) { + m >>= 2; + cftmdl1(m, &a[n - m]); + } + cftleaf(m, 1, &a[n - m]); + k = 0; + for (j = n - m; j > 0; j -= m) { + k++; + isplt = cfttree(m, j, k, a); + cftleaf(m, isplt, &a[j - m]); + } +} + + +picoos_int32 cfttree(picoos_int32 n, picoos_int32 j, picoos_int32 k, PICOFFTSG_FFTTYPE *a) +{ + picoos_int32 i, isplt, m; + + if ((k & 3) != 0) { + isplt = k & 1; + if (isplt != 0) { + cftmdl1(n, &a[j - n]); + } else { + cftmdl2(n, &a[j - n]); + } + } else { + m = n; + for (i = k; (i & 3) == 0; i >>= 2) { + m <<= 2; + } + isplt = i & 1; + if (isplt != 0) { + while (m > 128) { + cftmdl1(m, &a[j - m]); + m >>= 2; + } + } else { + while (m > 128) { + cftmdl2(m, &a[j - m]); + m >>= 2; + } + } + } + return isplt; +} + + +void cftleaf(picoos_int32 n, picoos_int32 isplt, PICOFFTSG_FFTTYPE *a) +{ + + if (n == 512) { + cftmdl1(128, a); + cftf161(a); + cftf162(&a[32]); + cftf161(&a[64]); + cftf161(&a[96]); + cftmdl2(128, &a[128]); + cftf161(&a[128]); + cftf162(&a[160]); + cftf161(&a[192]); + cftf162(&a[224]); + cftmdl1(128, &a[256]); + cftf161(&a[256]); + cftf162(&a[288]); + cftf161(&a[320]); + cftf161(&a[352]); + if (isplt != 0) { + cftmdl1(128, &a[384]); + cftf161(&a[480]); + } else { + cftmdl2(128, &a[384]); + cftf162(&a[480]); + } + cftf161(&a[384]); + cftf162(&a[416]); + cftf161(&a[448]); + } else { + cftmdl1(64, a); + cftf081(a); + cftf082(&a[16]); + cftf081(&a[32]); + cftf081(&a[48]); + cftmdl2(64, &a[64]); + cftf081(&a[64]); + cftf082(&a[80]); + cftf081(&a[96]); + cftf082(&a[112]); + cftmdl1(64, &a[128]); + cftf081(&a[128]); + cftf082(&a[144]); + cftf081(&a[160]); + cftf081(&a[176]); + if (isplt != 0) { + cftmdl1(64, &a[192]); + cftf081(&a[240]); + } else { + cftmdl2(64, &a[192]); + cftf082(&a[240]); + } + cftf081(&a[192]); + cftf082(&a[208]); + cftf081(&a[224]); + } +} + + +void cftmdl1(picoos_int32 n, PICOFFTSG_FFTTYPE *a) +{ + picoos_int32 i, i0, j, j0, j1, j2, j3, m, mh; + PICOFFTSG_FFTTYPE wk1r, wk1i, wk3r, wk3i, + wd1r, wd1i, wd3r, wd3i, ss1, ss3; + PICOFFTSG_FFTTYPE x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + mh = n >> 3; + m = 2 * mh; + j1 = m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[0] + a[j2]; + x0i = a[1] + a[j2 + 1]; + x1r = a[0] - a[j2]; + x1i = a[1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + a[j2] = x1r - x3i; + a[j2 + 1] = x1i + x3r; + a[j3] = x1r + x3i; + a[j3 + 1] = x1i - x3r; + wd1r = (PICOFFTSG_FFTTYPE)(PICODSP_WGT_SHIFT); + wd1i = 0; + wd3r = (PICOFFTSG_FFTTYPE)(PICODSP_WGT_SHIFT); + wd3i = 0; + wk1r = (PICOFFTSG_FFTTYPE) (0.980785250664 *PICODSP_WGT_SHIFT); + wk1i = (PICOFFTSG_FFTTYPE) (0.195090323687 *PICODSP_WGT_SHIFT); + ss1 = (PICOFFTSG_FFTTYPE) (0.390180647373 *PICODSP_WGT_SHIFT); + wk3i = (PICOFFTSG_FFTTYPE) (-0.555570185184 *PICODSP_WGT_SHIFT); + wk3r = (PICOFFTSG_FFTTYPE) (0.831469595432 *PICODSP_WGT_SHIFT); + ss3 = (PICOFFTSG_FFTTYPE) (-1.111140370369 *PICODSP_WGT_SHIFT); + + i = 0; + for (;;) { + i0 = i + CDFT_LOOP_DIV_4; + if (i0 > mh - 4) { + i0 = mh - 4; + } + for (j = i + 2; j < i0; j += 4) { + wd1r -= Mult_W_W(ss1, wk1i); + wd1i += Mult_W_W(ss1, wk1r); + wd3r -= Mult_W_W(ss3, wk3i); + wd3i += Mult_W_W(ss3, wk3r); + j1 = j + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j] + a[j2]; + x0i = a[j + 1] + a[j2 + 1]; + x1r = a[j] - a[j2]; + x1i = a[j + 1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); + a[j2 + 1] = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = Mult_W_W(wk3r, x0r) + Mult_W_W(wk3i, x0i); + a[j3 + 1] = Mult_W_W(wk3r, x0i) - Mult_W_W(wk3i, x0r); + x0r = a[j + 2] + a[j2 + 2]; + x0i = a[j + 3] + a[j2 + 3]; + x1r = a[j + 2] - a[j2 + 2]; + x1i = a[j + 3] - a[j2 + 3]; + x2r = a[j1 + 2] + a[j3 + 2]; + x2i = a[j1 + 3] + a[j3 + 3]; + x3r = a[j1 + 2] - a[j3 + 2]; + x3i = a[j1 + 3] - a[j3 + 3]; + a[j + 2] = x0r + x2r; + a[j + 3] = x0i + x2i; + a[j1 + 2] = x0r - x2r; + a[j1 + 3] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2 + 2] = Mult_W_W(wd1r, x0r) - Mult_W_W(wd1i, x0i); + a[j2 + 3] = Mult_W_W(wd1r, x0i) + Mult_W_W(wd1i, x0r); + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3 + 2] = Mult_W_W(wd3r, x0r) + Mult_W_W(wd3i, x0i); + a[j3 + 3] = Mult_W_W(wd3r, x0i) - Mult_W_W(wd3i, x0r); + j0 = m - j; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] + a[j2]; + x0i = a[j0 + 1] + a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = a[j0 + 1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); + a[j2 + 1] = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = Mult_W_W(wk3i, x0r) + Mult_W_W(wk3r, x0i); + a[j3 + 1] = Mult_W_W(wk3i, x0i) - Mult_W_W(wk3r, x0r); + x0r = a[j0 - 2] + a[j2 - 2]; + x0i = a[j0 - 1] + a[j2 - 1]; + x1r = a[j0 - 2] - a[j2 - 2]; + x1i = a[j0 - 1] - a[j2 - 1]; + x2r = a[j1 - 2] + a[j3 - 2]; + x2i = a[j1 - 1] + a[j3 - 1]; + x3r = a[j1 - 2] - a[j3 - 2]; + x3i = a[j1 - 1] - a[j3 - 1]; + a[j0 - 2] = x0r + x2r; + a[j0 - 1] = x0i + x2i; + a[j1 - 2] = x0r - x2r; + a[j1 - 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2 - 2] = Mult_W_W(wd1i, x0r) - Mult_W_W(wd1r, x0i); + a[j2 - 1] = Mult_W_W(wd1i, x0i) + Mult_W_W(wd1r, x0r); + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3 - 2] = Mult_W_W(wd3i, x0r) + Mult_W_W(wd3r, x0i); + a[j3 - 1] = Mult_W_W(wd3i, x0i) - Mult_W_W(wd3r, x0r); + wk1r -= Mult_W_W(ss1, wd1i); + wk1i += Mult_W_W(ss1, wd1r); + wk3r -= Mult_W_W(ss3, wd3i); + wk3i += Mult_W_W(ss3, wd3r); + } + if (i0 == mh - 4) { + break; + } + } + wd1r = WR5000; + j0 = mh; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0 - 2] + a[j2 - 2]; + x0i = a[j0 - 1] + a[j2 - 1]; + x1r = a[j0 - 2] - a[j2 - 2]; + x1i = a[j0 - 1] - a[j2 - 1]; + x2r = a[j1 - 2] + a[j3 - 2]; + x2i = a[j1 - 1] + a[j3 - 1]; + x3r = a[j1 - 2] - a[j3 - 2]; + x3i = a[j1 - 1] - a[j3 - 1]; + a[j0 - 2] = x0r + x2r; + a[j0 - 1] = x0i + x2i; + a[j1 - 2] = x0r - x2r; + a[j1 - 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2 - 2] = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); + a[j2 - 1] = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3 - 2] = Mult_W_W(wk3r, x0r) + Mult_W_W(wk3i, x0i); + a[j3 - 1] = Mult_W_W(wk3r, x0i) - Mult_W_W(wk3i, x0r); + x0r = a[j0] + a[j2]; + x0i = a[j0 + 1] + a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = a[j0 + 1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = picofftsg_mult_w_a(wd1r, (x0r - x0i)); + a[j2 + 1] = picofftsg_mult_w_a(wd1r, (x0i + x0r)); + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = -picofftsg_mult_w_a(wd1r, (x0r + x0i)); + a[j3 + 1] = -picofftsg_mult_w_a(wd1r, (x0i - x0r)); + x0r = a[j0 + 2] + a[j2 + 2]; + x0i = a[j0 + 3] + a[j2 + 3]; + x1r = a[j0 + 2] - a[j2 + 2]; + x1i = a[j0 + 3] - a[j2 + 3]; + x2r = a[j1 + 2] + a[j3 + 2]; + x2i = a[j1 + 3] + a[j3 + 3]; + x3r = a[j1 + 2] - a[j3 + 2]; + x3i = a[j1 + 3] - a[j3 + 3]; + a[j0 + 2] = x0r + x2r; + a[j0 + 3] = x0i + x2i; + a[j1 + 2] = x0r - x2r; + a[j1 + 3] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2 + 2] = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); + a[j2 + 3] = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3 + 2] = Mult_W_W(wk3i, x0r) + Mult_W_W(wk3r, x0i); + a[j3 + 3] = Mult_W_W(wk3i, x0i) - Mult_W_W(wk3r, x0r); +} + + +void cftmdl2(picoos_int32 n, PICOFFTSG_FFTTYPE *a) +{ + picoos_int32 i, i0, j, j0, j1, j2, j3, m, mh; + PICOFFTSG_FFTTYPE wn4r, wk1r, wk1i, wk3r, wk3i, + wl1r, wl1i, wl3r, wl3i, wd1r, wd1i, wd3r, wd3i, + we1r, we1i, we3r, we3i, ss1, ss3; + PICOFFTSG_FFTTYPE x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y2r, y2i; + + mh = n >> 3; + m = 2 * mh; + wn4r = WR5000; + j1 = m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[0] - a[j2 + 1]; + x0i = a[1] + a[j2]; + x1r = a[0] + a[j2 + 1]; + x1i = a[1] - a[j2]; + x2r = a[j1] - a[j3 + 1]; + x2i = a[j1 + 1] + a[j3]; + x3r = a[j1] + a[j3 + 1]; + x3i = a[j1 + 1] - a[j3]; + y0r = picofftsg_mult_w_a(wn4r, (x2r - x2i)); + y0i = picofftsg_mult_w_a(wn4r, (x2i + x2r)); + a[0] = x0r + y0r; + a[1] = x0i + y0i; + a[j1] = x0r - y0r; + a[j1 + 1] = x0i - y0i; + y0r = picofftsg_mult_w_a(wn4r, (x3r - x3i)); + y0i = picofftsg_mult_w_a(wn4r, (x3i + x3r)); + a[j2] = x1r - y0i; + a[j2 + 1] = x1i + y0r; + a[j3] = x1r + y0i; + a[j3 + 1] = x1i - y0r; + wl1r = PICODSP_WGT_SHIFT; + wl1i = 0; + wl3r = PICODSP_WGT_SHIFT; + wl3i = 0; + we1r = wn4r; + we1i = wn4r; + we3r = -wn4r; + we3i = -wn4r; + + wk1r = (PICOFFTSG_FFTTYPE)(0.995184719563 *PICODSP_WGT_SHIFT); + wk1i = (PICOFFTSG_FFTTYPE)(0.098017141223 *PICODSP_WGT_SHIFT); + wd1r = (PICOFFTSG_FFTTYPE)(0.634393274784 *PICODSP_WGT_SHIFT); + wd1i = (PICOFFTSG_FFTTYPE)(0.773010432720 *PICODSP_WGT_SHIFT); + ss1 = (PICOFFTSG_FFTTYPE)(0.196034282446 *PICODSP_WGT_SHIFT); + wk3i = (PICOFFTSG_FFTTYPE)(-0.290284663439 *PICODSP_WGT_SHIFT); + wk3r = (PICOFFTSG_FFTTYPE)(0.956940352917 *PICODSP_WGT_SHIFT); + ss3 = (PICOFFTSG_FFTTYPE)(-0.580569326878 *PICODSP_WGT_SHIFT); + wd3r = (PICOFFTSG_FFTTYPE)(-0.881921231747 *PICODSP_WGT_SHIFT); + wd3i = (PICOFFTSG_FFTTYPE)(-0.471396744251 *PICODSP_WGT_SHIFT); + + i = 0; + for (;;) { + i0 = i + 4 * CDFT_LOOP_DIV; + if (i0 > mh - 4) { + i0 = mh - 4; + } + for (j = i + 2; j < i0; j += 4) { + wl1r -= Mult_W_W(ss1, wk1i); + wl1i += Mult_W_W(ss1, wk1r); + wl3r -= Mult_W_W(ss3, wk3i); + wl3i += Mult_W_W(ss3, wk3r); + we1r -= Mult_W_W(ss1, wd1i); + we1i += Mult_W_W(ss1, wd1r); + we3r -= Mult_W_W(ss3, wd3i); + we3i += Mult_W_W(ss3, wd3r); + j1 = j + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j] - a[j2 + 1]; + x0i = a[j + 1] + a[j2]; + x1r = a[j] + a[j2 + 1]; + x1i = a[j + 1] - a[j2]; + x2r = a[j1] - a[j3 + 1]; + x2i = a[j1 + 1] + a[j3]; + x3r = a[j1] + a[j3 + 1]; + x3i = a[j1 + 1] - a[j3]; + y0r = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); + y0i = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); + y2r = Mult_W_W(wd1r, x2r) - Mult_W_W(wd1i, x2i); + y2i = Mult_W_W(wd1r, x2i) + Mult_W_W(wd1i, x2r); + a[j] = y0r + y2r; + a[j + 1] = y0i + y2i; + a[j1] = y0r - y2r; + a[j1 + 1] = y0i - y2i; + y0r = Mult_W_W(wk3r, x1r) + Mult_W_W(wk3i, x1i); + y0i = Mult_W_W(wk3r, x1i) - Mult_W_W(wk3i, x1r); + y2r = Mult_W_W(wd3r, x3r) + Mult_W_W(wd3i, x3i); + y2i = Mult_W_W(wd3r, x3i) - Mult_W_W(wd3i, x3r); + a[j2] = y0r + y2r; + a[j2 + 1] = y0i + y2i; + a[j3] = y0r - y2r; + a[j3 + 1] = y0i - y2i; + x0r = a[j + 2] - a[j2 + 3]; + x0i = a[j + 3] + a[j2 + 2]; + x1r = a[j + 2] + a[j2 + 3]; + x1i = a[j + 3] - a[j2 + 2]; + x2r = a[j1 + 2] - a[j3 + 3]; + x2i = a[j1 + 3] + a[j3 + 2]; + x3r = a[j1 + 2] + a[j3 + 3]; + x3i = a[j1 + 3] - a[j3 + 2]; + y0r = Mult_W_W(wl1r, x0r) - Mult_W_W(wl1i, x0i); + y0i = Mult_W_W(wl1r, x0i) + Mult_W_W(wl1i, x0r); + y2r = Mult_W_W(we1r, x2r) - Mult_W_W(we1i, x2i); + y2i = Mult_W_W(we1r, x2i) + Mult_W_W(we1i, x2r); + a[j + 2] = y0r + y2r; + a[j + 3] = y0i + y2i; + a[j1 + 2] = y0r - y2r; + a[j1 + 3] = y0i - y2i; + y0r = Mult_W_W(wl3r, x1r) + Mult_W_W(wl3i, x1i); + y0i = Mult_W_W(wl3r, x1i) - Mult_W_W(wl3i, x1r); + y2r = Mult_W_W(we3r, x3r) + Mult_W_W(we3i, x3i); + y2i = Mult_W_W(we3r, x3i) - Mult_W_W(we3i, x3r); + a[j2 + 2] = y0r + y2r; + a[j2 + 3] = y0i + y2i; + a[j3 + 2] = y0r - y2r; + a[j3 + 3] = y0i - y2i; + j0 = m - j; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] - a[j2 + 1]; + x0i = a[j0 + 1] + a[j2]; + x1r = a[j0] + a[j2 + 1]; + x1i = a[j0 + 1] - a[j2]; + x2r = a[j1] - a[j3 + 1]; + x2i = a[j1 + 1] + a[j3]; + x3r = a[j1] + a[j3 + 1]; + x3i = a[j1 + 1] - a[j3]; + y0r = Mult_W_W(wd1i, x0r) - Mult_W_W(wd1r, x0i); + y0i = Mult_W_W(wd1i, x0i) + Mult_W_W(wd1r, x0r); + y2r = Mult_W_W(wk1i, x2r) - Mult_W_W(wk1r, x2i); + y2i = Mult_W_W(wk1i, x2i) + Mult_W_W(wk1r, x2r); + a[j0] = y0r + y2r; + a[j0 + 1] = y0i + y2i; + a[j1] = y0r - y2r; + a[j1 + 1] = y0i - y2i; + y0r = Mult_W_W(wd3i, x1r) + Mult_W_W(wd3r, x1i); + y0i = Mult_W_W(wd3i, x1i) - Mult_W_W(wd3r, x1r); + y2r = Mult_W_W(wk3i, x3r) + Mult_W_W(wk3r, x3i); + y2i = Mult_W_W(wk3i, x3i) - Mult_W_W(wk3r, x3r); + a[j2] = y0r + y2r; + a[j2 + 1] = y0i + y2i; + a[j3] = y0r - y2r; + a[j3 + 1] = y0i - y2i; + x0r = a[j0 - 2] - a[j2 - 1]; + x0i = a[j0 - 1] + a[j2 - 2]; + x1r = a[j0 - 2] + a[j2 - 1]; + x1i = a[j0 - 1] - a[j2 - 2]; + x2r = a[j1 - 2] - a[j3 - 1]; + x2i = a[j1 - 1] + a[j3 - 2]; + x3r = a[j1 - 2] + a[j3 - 1]; + x3i = a[j1 - 1] - a[j3 - 2]; + y0r = Mult_W_W(we1i, x0r) - Mult_W_W(we1r, x0i); + y0i = Mult_W_W(we1i, x0i) + Mult_W_W(we1r, x0r); + y2r = Mult_W_W(wl1i, x2r) - Mult_W_W(wl1r, x2i); + y2i = Mult_W_W(wl1i, x2i) + Mult_W_W(wl1r, x2r); + a[j0 - 2] = y0r + y2r; + a[j0 - 1] = y0i + y2i; + a[j1 - 2] = y0r - y2r; + a[j1 - 1] = y0i - y2i; + y0r = Mult_W_W(we3i, x1r) + Mult_W_W(we3r, x1i); + y0i = Mult_W_W(we3i, x1i) - Mult_W_W(we3r, x1r); + y2r = Mult_W_W(wl3i, x3r) + Mult_W_W(wl3r, x3i); + y2i = Mult_W_W(wl3i, x3i) - Mult_W_W(wl3r, x3r); + a[j2 - 2] = y0r + y2r; + a[j2 - 1] = y0i + y2i; + a[j3 - 2] = y0r - y2r; + a[j3 - 1] = y0i - y2i; + wk1r -= Mult_W_W(ss1, wl1i); + wk1i += Mult_W_W(ss1, wl1r); + wk3r -= Mult_W_W(ss3, wl3i); + wk3i += Mult_W_W(ss3, wl3r); + wd1r -= Mult_W_W(ss1, we1i); + wd1i += Mult_W_W(ss1, we1r); + wd3r -= Mult_W_W(ss3, we3i); + wd3i += Mult_W_W(ss3, we3r); + } + if (i0 == mh - 4) { + break; + } + } + wl1r = WR2500; + wl1i = WI2500; + j0 = mh; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0 - 2] - a[j2 - 1]; + x0i = a[j0 - 1] + a[j2 - 2]; + x1r = a[j0 - 2] + a[j2 - 1]; + x1i = a[j0 - 1] - a[j2 - 2]; + x2r = a[j1 - 2] - a[j3 - 1]; + x2i = a[j1 - 1] + a[j3 - 2]; + x3r = a[j1 - 2] + a[j3 - 1]; + x3i = a[j1 - 1] - a[j3 - 2]; + y0r = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); + y0i = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); + y2r = Mult_W_W(wd1r, x2r) - Mult_W_W(wd1i, x2i); + y2i = Mult_W_W(wd1r, x2i) + Mult_W_W(wd1i, x2r); + a[j0 - 2] = y0r + y2r; + a[j0 - 1] = y0i + y2i; + a[j1 - 2] = y0r - y2r; + a[j1 - 1] = y0i - y2i; + y0r = Mult_W_W(wk3r, x1r) + Mult_W_W(wk3i, x1i); + y0i = Mult_W_W(wk3r, x1i) - Mult_W_W(wk3i, x1r); + y2r = Mult_W_W(wd3r, x3r) + Mult_W_W(wd3i, x3i); + y2i = Mult_W_W(wd3r, x3i) - Mult_W_W(wd3i, x3r); + a[j2 - 2] = y0r + y2r; + a[j2 - 1] = y0i + y2i; + a[j3 - 2] = y0r - y2r; + a[j3 - 1] = y0i - y2i; + x0r = a[j0] - a[j2 + 1]; + x0i = a[j0 + 1] + a[j2]; + x1r = a[j0] + a[j2 + 1]; + x1i = a[j0 + 1] - a[j2]; + x2r = a[j1] - a[j3 + 1]; + x2i = a[j1 + 1] + a[j3]; + x3r = a[j1] + a[j3 + 1]; + x3i = a[j1 + 1] - a[j3]; + y0r = Mult_W_W(wl1r, x0r) - Mult_W_W(wl1i, x0i); + y0i = Mult_W_W(wl1r, x0i) + Mult_W_W(wl1i, x0r); + y2r = Mult_W_W(wl1i, x2r) - Mult_W_W(wl1r, x2i); + y2i = Mult_W_W(wl1i, x2i) + Mult_W_W(wl1r, x2r); + a[j0] = y0r + y2r; + a[j0 + 1] = y0i + y2i; + a[j1] = y0r - y2r; + a[j1 + 1] = y0i - y2i; + y0r = Mult_W_W(wl1i, x1r) - Mult_W_W(wl1r, x1i); + y0i = Mult_W_W(wl1i, x1i) + Mult_W_W(wl1r, x1r); + y2r = Mult_W_W(wl1r, x3r) - Mult_W_W(wl1i, x3i); + y2i = Mult_W_W(wl1r, x3i) + Mult_W_W(wl1i, x3r); + a[j2] = y0r - y2r; + a[j2 + 1] = y0i - y2i; + a[j3] = y0r + y2r; + a[j3 + 1] = y0i + y2i; + x0r = a[j0 + 2] - a[j2 + 3]; + x0i = a[j0 + 3] + a[j2 + 2]; + x1r = a[j0 + 2] + a[j2 + 3]; + x1i = a[j0 + 3] - a[j2 + 2]; + x2r = a[j1 + 2] - a[j3 + 3]; + x2i = a[j1 + 3] + a[j3 + 2]; + x3r = a[j1 + 2] + a[j3 + 3]; + x3i = a[j1 + 3] - a[j3 + 2]; + y0r = Mult_W_W(wd1i, x0r) - Mult_W_W(wd1r, x0i); + y0i = Mult_W_W(wd1i, x0i) + Mult_W_W(wd1r, x0r); + y2r = Mult_W_W(wk1i, x2r) - Mult_W_W(wk1r, x2i); + y2i = Mult_W_W(wk1i, x2i) + Mult_W_W(wk1r, x2r); + a[j0 + 2] = y0r + y2r; + a[j0 + 3] = y0i + y2i; + a[j1 + 2] = y0r - y2r; + a[j1 + 3] = y0i - y2i; + y0r = Mult_W_W(wd3i, x1r) + Mult_W_W(wd3r, x1i); + y0i = Mult_W_W(wd3i, x1i) - Mult_W_W(wd3r, x1r); + y2r = Mult_W_W(wk3i, x3r) + Mult_W_W(wk3r, x3i); + y2i = Mult_W_W(wk3i, x3i) - Mult_W_W(wk3r, x3r); + a[j2 + 2] = y0r + y2r; + a[j2 + 3] = y0i + y2i; + a[j3 + 2] = y0r - y2r; + a[j3 + 3] = y0i - y2i; +} + + +void cftfx41(picoos_int32 n, PICOFFTSG_FFTTYPE *a) +{ + + if (n == 128) { + cftf161(a); + cftf162(&a[32]); + cftf161(&a[64]); + cftf161(&a[96]); + } else { + cftf081(a); + cftf082(&a[16]); + cftf081(&a[32]); + cftf081(&a[48]); + } +} + + +void cftf161(PICOFFTSG_FFTTYPE *a) +{ + PICOFFTSG_FFTTYPE wn4r, wk1r, wk1i, + x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, + y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, + y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, + y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; + + wn4r = WR5000; + wk1r = WR2500; + wk1i = WI2500; + x0r = a[0] + a[16]; + x0i = a[1] + a[17]; + x1r = a[0] - a[16]; + x1i = a[1] - a[17]; + x2r = a[8] + a[24]; + x2i = a[9] + a[25]; + x3r = a[8] - a[24]; + x3i = a[9] - a[25]; + y0r = x0r + x2r; + y0i = x0i + x2i; + y4r = x0r - x2r; + y4i = x0i - x2i; + y8r = x1r - x3i; + y8i = x1i + x3r; + y12r = x1r + x3i; + y12i = x1i - x3r; + x0r = a[2] + a[18]; + x0i = a[3] + a[19]; + x1r = a[2] - a[18]; + x1i = a[3] - a[19]; + x2r = a[10] + a[26]; + x2i = a[11] + a[27]; + x3r = a[10] - a[26]; + x3i = a[11] - a[27]; + y1r = x0r + x2r; + y1i = x0i + x2i; + y5r = x0r - x2r; + y5i = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + y9r = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); + y9i = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); + x0r = x1r + x3i; + x0i = x1i - x3r; + y13r = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); + y13i = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); + x0r = a[4] + a[20]; + x0i = a[5] + a[21]; + x1r = a[4] - a[20]; + x1i = a[5] - a[21]; + x2r = a[12] + a[28]; + x2i = a[13] + a[29]; + x3r = a[12] - a[28]; + x3i = a[13] - a[29]; + y2r = x0r + x2r; + y2i = x0i + x2i; + y6r = x0r - x2r; + y6i = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + y10r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); + y10i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); + x0r = x1r + x3i; + x0i = x1i - x3r; + y14r = picofftsg_mult_w_a(wn4r, (x0r + x0i)); + y14i = picofftsg_mult_w_a(wn4r, (x0i - x0r)); + x0r = a[6] + a[22]; + x0i = a[7] + a[23]; + x1r = a[6] - a[22]; + x1i = a[7] - a[23]; + x2r = a[14] + a[30]; + x2i = a[15] + a[31]; + x3r = a[14] - a[30]; + x3i = a[15] - a[31]; + y3r = x0r + x2r; + y3i = x0i + x2i; + y7r = x0r - x2r; + y7i = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + y11r = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); + y11i = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); + x0r = x1r + x3i; + x0i = x1i - x3r; + y15r = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); + y15i = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); + x0r = y12r - y14r; + x0i = y12i - y14i; + x1r = y12r + y14r; + x1i = y12i + y14i; + x2r = y13r - y15r; + x2i = y13i - y15i; + x3r = y13r + y15r; + x3i = y13i + y15i; + a[24] = x0r + x2r; + a[25] = x0i + x2i; + a[26] = x0r - x2r; + a[27] = x0i - x2i; + a[28] = x1r - x3i; + a[29] = x1i + x3r; + a[30] = x1r + x3i; + a[31] = x1i - x3r; + x0r = y8r + y10r; + x0i = y8i + y10i; + x1r = y8r - y10r; + x1i = y8i - y10i; + x2r = y9r + y11r; + x2i = y9i + y11i; + x3r = y9r - y11r; + x3i = y9i - y11i; + a[16] = x0r + x2r; + a[17] = x0i + x2i; + a[18] = x0r - x2r; + a[19] = x0i - x2i; + a[20] = x1r - x3i; + a[21] = x1i + x3r; + a[22] = x1r + x3i; + a[23] = x1i - x3r; + x0r = y5r - y7i; + x0i = y5i + y7r; + x2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); + x2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); + x0r = y5r + y7i; + x0i = y5i - y7r; + x3r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); + x3i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); + x0r = y4r - y6i; + x0i = y4i + y6r; + x1r = y4r + y6i; + x1i = y4i - y6r; + a[8] = x0r + x2r; + a[9] = x0i + x2i; + a[10] = x0r - x2r; + a[11] = x0i - x2i; + a[12] = x1r - x3i; + a[13] = x1i + x3r; + a[14] = x1r + x3i; + a[15] = x1i - x3r; + x0r = y0r + y2r; + x0i = y0i + y2i; + x1r = y0r - y2r; + x1i = y0i - y2i; + x2r = y1r + y3r; + x2i = y1i + y3i; + x3r = y1r - y3r; + x3i = y1i - y3i; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[2] = x0r - x2r; + a[3] = x0i - x2i; + a[4] = x1r - x3i; + a[5] = x1i + x3r; + a[6] = x1r + x3i; + a[7] = x1i - x3r; +} + + +void cftf162(PICOFFTSG_FFTTYPE *a) +{ + PICOFFTSG_FFTTYPE wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, + x0r, x0i, x1r, x1i, x2r, x2i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, + y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, + y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, + y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; + + wn4r = WR5000; + wk1r = WR1250; + wk1i = WI1250; + wk2r = WR2500; + wk2i = WI2500; + wk3r = WR3750; + wk3i = WI3750; + x1r = a[0] - a[17]; + x1i = a[1] + a[16]; + x0r = a[8] - a[25]; + x0i = a[9] + a[24]; + x2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); + x2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); + y0r = x1r + x2r; + y0i = x1i + x2i; + y4r = x1r - x2r; + y4i = x1i - x2i; + x1r = a[0] + a[17]; + x1i = a[1] - a[16]; + x0r = a[8] + a[25]; + x0i = a[9] - a[24]; + x2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); + x2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); + y8r = x1r - x2i; + y8i = x1i + x2r; + y12r = x1r + x2i; + y12i = x1i - x2r; + x0r = a[2] - a[19]; + x0i = a[3] + a[18]; + x1r = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); + x1i = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); + x0r = a[10] - a[27]; + x0i = a[11] + a[26]; + x2r = Mult_W_W(wk3i, x0r) - Mult_W_W(wk3r, x0i); + x2i = Mult_W_W(wk3i, x0i) + Mult_W_W(wk3r, x0r); + y1r = x1r + x2r; + y1i = x1i + x2i; + y5r = x1r - x2r; + y5i = x1i - x2i; + x0r = a[2] + a[19]; + x0i = a[3] - a[18]; + x1r = Mult_W_W(wk3r, x0r) - Mult_W_W(wk3i, x0i); + x1i = Mult_W_W(wk3r, x0i) + Mult_W_W(wk3i, x0r); + x0r = a[10] + a[27]; + x0i = a[11] - a[26]; + x2r = Mult_W_W(wk1r, x0r) + Mult_W_W(wk1i, x0i); + x2i = Mult_W_W(wk1r, x0i) - Mult_W_W(wk1i, x0r); + y9r = x1r - x2r; + y9i = x1i - x2i; + y13r = x1r + x2r; + y13i = x1i + x2i; + x0r = a[4] - a[21]; + x0i = a[5] + a[20]; + x1r = Mult_W_W(wk2r, x0r) - Mult_W_W(wk2i, x0i); + x1i = Mult_W_W(wk2r, x0i) + Mult_W_W(wk2i, x0r); + x0r = a[12] - a[29]; + x0i = a[13] + a[28]; + x2r = Mult_W_W(wk2i, x0r) - Mult_W_W(wk2r, x0i); + x2i = Mult_W_W(wk2i, x0i) + Mult_W_W(wk2r, x0r); + y2r = x1r + x2r; + y2i = x1i + x2i; + y6r = x1r - x2r; + y6i = x1i - x2i; + x0r = a[4] + a[21]; + x0i = a[5] - a[20]; + x1r = Mult_W_W(wk2i, x0r) - Mult_W_W(wk2r, x0i); + x1i = Mult_W_W(wk2i, x0i) + Mult_W_W(wk2r, x0r); + x0r = a[12] + a[29]; + x0i = a[13] - a[28]; + x2r = Mult_W_W(wk2r, x0r) - Mult_W_W(wk2i, x0i); + x2i = Mult_W_W(wk2r, x0i) + Mult_W_W(wk2i, x0r); + y10r = x1r - x2r; + y10i = x1i - x2i; + y14r = x1r + x2r; + y14i = x1i + x2i; + x0r = a[6] - a[23]; + x0i = a[7] + a[22]; + x1r = Mult_W_W(wk3r, x0r) - Mult_W_W(wk3i, x0i); + x1i = Mult_W_W(wk3r, x0i) + Mult_W_W(wk3i, x0r); + x0r = a[14] - a[31]; + x0i = a[15] + a[30]; + x2r = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); + x2i = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); + y3r = x1r + x2r; + y3i = x1i + x2i; + y7r = x1r - x2r; + y7i = x1i - x2i; + x0r = a[6] + a[23]; + x0i = a[7] - a[22]; + x1r = Mult_W_W(wk1i, x0r) + Mult_W_W(wk1r, x0i); + x1i = Mult_W_W(wk1i, x0i) - Mult_W_W(wk1r, x0r); + x0r = a[14] + a[31]; + x0i = a[15] - a[30]; + x2r = Mult_W_W(wk3i, x0r) - Mult_W_W(wk3r, x0i); + x2i = Mult_W_W(wk3i, x0i) + Mult_W_W(wk3r, x0r); + y11r = x1r + x2r; + y11i = x1i + x2i; + y15r = x1r - x2r; + y15i = x1i - x2i; + x1r = y0r + y2r; + x1i = y0i + y2i; + x2r = y1r + y3r; + x2i = y1i + y3i; + a[0] = x1r + x2r; + a[1] = x1i + x2i; + a[2] = x1r - x2r; + a[3] = x1i - x2i; + x1r = y0r - y2r; + x1i = y0i - y2i; + x2r = y1r - y3r; + x2i = y1i - y3i; + a[4] = x1r - x2i; + a[5] = x1i + x2r; + a[6] = x1r + x2i; + a[7] = x1i - x2r; + x1r = y4r - y6i; + x1i = y4i + y6r; + x0r = y5r - y7i; + x0i = y5i + y7r; + x2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); + x2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); + a[8] = x1r + x2r; + a[9] = x1i + x2i; + a[10] = x1r - x2r; + a[11] = x1i - x2i; + x1r = y4r + y6i; + x1i = y4i - y6r; + x0r = y5r + y7i; + x0i = y5i - y7r; + x2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); + x2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); + a[12] = x1r - x2i; + a[13] = x1i + x2r; + a[14] = x1r + x2i; + a[15] = x1i - x2r; + x1r = y8r + y10r; + x1i = y8i + y10i; + x2r = y9r - y11r; + x2i = y9i - y11i; + a[16] = x1r + x2r; + a[17] = x1i + x2i; + a[18] = x1r - x2r; + a[19] = x1i - x2i; + x1r = y8r - y10r; + x1i = y8i - y10i; + x2r = y9r + y11r; + x2i = y9i + y11i; + a[20] = x1r - x2i; + a[21] = x1i + x2r; + a[22] = x1r + x2i; + a[23] = x1i - x2r; + x1r = y12r - y14i; + x1i = y12i + y14r; + x0r = y13r + y15i; + x0i = y13i - y15r; + x2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); + x2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); + a[24] = x1r + x2r; + a[25] = x1i + x2i; + a[26] = x1r - x2r; + a[27] = x1i - x2i; + x1r = y12r + y14i; + x1i = y12i - y14r; + x0r = y13r - y15i; + x0i = y13i + y15r; + x2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); + x2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); + a[28] = x1r - x2i; + a[29] = x1i + x2r; + a[30] = x1r + x2i; + a[31] = x1i - x2r; +} + + +void cftf081(PICOFFTSG_FFTTYPE *a) +{ + PICOFFTSG_FFTTYPE wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, + y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; + + wn4r = WR5000; + x0r = a[0] + a[8]; + x0i = a[1] + a[9]; + x1r = a[0] - a[8]; + x1i = a[1] - a[9]; + x2r = a[4] + a[12]; + x2i = a[5] + a[13]; + x3r = a[4] - a[12]; + x3i = a[5] - a[13]; + y0r = x0r + x2r; + y0i = x0i + x2i; + y2r = x0r - x2r; + y2i = x0i - x2i; + y1r = x1r - x3i; + y1i = x1i + x3r; + y3r = x1r + x3i; + y3i = x1i - x3r; + x0r = a[2] + a[10]; + x0i = a[3] + a[11]; + x1r = a[2] - a[10]; + x1i = a[3] - a[11]; + x2r = a[6] + a[14]; + x2i = a[7] + a[15]; + x3r = a[6] - a[14]; + x3i = a[7] - a[15]; + y4r = x0r + x2r; + y4i = x0i + x2i; + y6r = x0r - x2r; + y6i = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + x2r = x1r + x3i; + x2i = x1i - x3r; + y5r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); + y5i = picofftsg_mult_w_a(wn4r, (x0r + x0i)); + y7r = picofftsg_mult_w_a(wn4r, (x2r - x2i)); + y7i = picofftsg_mult_w_a(wn4r, (x2r + x2i)); + a[8] = y1r + y5r; + a[9] = y1i + y5i; + a[10] = y1r - y5r; + a[11] = y1i - y5i; + a[12] = y3r - y7i; + a[13] = y3i + y7r; + a[14] = y3r + y7i; + a[15] = y3i - y7r; + a[0] = y0r + y4r; + a[1] = y0i + y4i; + a[2] = y0r - y4r; + a[3] = y0i - y4i; + a[4] = y2r - y6i; + a[5] = y2i + y6r; + a[6] = y2r + y6i; + a[7] = y2i - y6r; +} + + +void cftf082(PICOFFTSG_FFTTYPE *a) +{ + PICOFFTSG_FFTTYPE wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, + y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; + + wn4r = WR5000; + wk1r = WR2500; + wk1i = WI2500; + y0r = a[0] - a[9]; + y0i = a[1] + a[8]; + y1r = a[0] + a[9]; + y1i = a[1] - a[8]; + x0r = a[4] - a[13]; + x0i = a[5] + a[12]; + y2r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); + y2i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); + x0r = a[4] + a[13]; + x0i = a[5] - a[12]; + y3r = picofftsg_mult_w_a(wn4r, (x0r - x0i)); + y3i = picofftsg_mult_w_a(wn4r, (x0i + x0r)); + x0r = a[2] - a[11]; + x0i = a[3] + a[10]; + y4r = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); + y4i = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); + x0r = a[2] + a[11]; + x0i = a[3] - a[10]; + y5r = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); + y5i = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); + x0r = a[6] - a[15]; + x0i = a[7] + a[14]; + y6r = Mult_W_W(wk1i, x0r) - Mult_W_W(wk1r, x0i); + y6i = Mult_W_W(wk1i, x0i) + Mult_W_W(wk1r, x0r); + x0r = a[6] + a[15]; + x0i = a[7] - a[14]; + y7r = Mult_W_W(wk1r, x0r) - Mult_W_W(wk1i, x0i); + y7i = Mult_W_W(wk1r, x0i) + Mult_W_W(wk1i, x0r); + x0r = y0r + y2r; + x0i = y0i + y2i; + x1r = y4r + y6r; + x1i = y4i + y6i; + a[0] = x0r + x1r; + a[1] = x0i + x1i; + a[2] = x0r - x1r; + a[3] = x0i - x1i; + x0r = y0r - y2r; + x0i = y0i - y2i; + x1r = y4r - y6r; + x1i = y4i - y6i; + a[4] = x0r - x1i; + a[5] = x0i + x1r; + a[6] = x0r + x1i; + a[7] = x0i - x1r; + x0r = y1r - y3i; + x0i = y1i + y3r; + x1r = y5r - y7r; + x1i = y5i - y7i; + a[8] = x0r + x1r; + a[9] = x0i + x1i; + a[10] = x0r - x1r; + a[11] = x0i - x1i; + x0r = y1r + y3i; + x0i = y1i - y3r; + x1r = y5r + y7r; + x1i = y5i + y7i; + a[12] = x0r - x1i; + a[13] = x0i + x1r; + a[14] = x0r + x1i; + a[15] = x0i - x1r; +} + + +void cftf040(PICOFFTSG_FFTTYPE *a) +{ + PICOFFTSG_FFTTYPE x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + x0r = a[0] + a[4]; + x0i = a[1] + a[5]; + x1r = a[0] - a[4]; + x1i = a[1] - a[5]; + x2r = a[2] + a[6]; + x2i = a[3] + a[7]; + x3r = a[2] - a[6]; + x3i = a[3] - a[7]; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[2] = x1r - x3i; + a[3] = x1i + x3r; + a[4] = x0r - x2r; + a[5] = x0i - x2i; + a[6] = x1r + x3i; + a[7] = x1i - x3r; +} + + +void cftb040(PICOFFTSG_FFTTYPE *a) +{ + PICOFFTSG_FFTTYPE x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + x0r = a[0] + a[4]; + x0i = a[1] + a[5]; + x1r = a[0] - a[4]; + x1i = a[1] - a[5]; + x2r = a[2] + a[6]; + x2i = a[3] + a[7]; + x3r = a[2] - a[6]; + x3i = a[3] - a[7]; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[2] = x1r + x3i; + a[3] = x1i - x3r; + a[4] = x0r - x2r; + a[5] = x0i - x2i; + a[6] = x1r - x3i; + a[7] = x1i + x3r; +} + + +void cftx020(PICOFFTSG_FFTTYPE *a) +{ + PICOFFTSG_FFTTYPE x0r, x0i; + + x0r = a[0] - a[2]; + x0i = a[1] - a[3]; + a[0] += a[2]; + a[1] += a[3]; + a[2] = x0r; + a[3] = x0i; +} + + +void rftfsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a) +{ + picoos_int32 i, i0, j, k; + PICOFFTSG_FFTTYPE w1r, w1i, wkr, wki, wdr, wdi, ss, xr, xi, yr, yi; + + wkr = 0; + wki = 0; + + switch (n) { + case 8 : + wdi=(PICOFFTSG_FFTTYPE)(0.353553414345*PICODSP_WGT_SHIFT); wdr=(PICOFFTSG_FFTTYPE)(0.146446630359*PICODSP_WGT_SHIFT); + w1r=(PICOFFTSG_FFTTYPE)(0.707106709480*PICODSP_WGT_SHIFT); w1i=(PICOFFTSG_FFTTYPE)(0.707106828690*PICODSP_WGT_SHIFT); + ss =(PICOFFTSG_FFTTYPE)(1.414213657379*PICODSP_WGT_SHIFT); break; + case 16 : + wdi=(PICOFFTSG_FFTTYPE)(0.191341713071*PICODSP_WGT_SHIFT); wdr=(PICOFFTSG_FFTTYPE)(0.038060232997*PICODSP_WGT_SHIFT); + w1r=(PICOFFTSG_FFTTYPE)(0.923879504204*PICODSP_WGT_SHIFT); w1i=(PICOFFTSG_FFTTYPE)(0.382683426142*PICODSP_WGT_SHIFT); + ss =(PICOFFTSG_FFTTYPE)(0.765366852283*PICODSP_WGT_SHIFT); break; + case 32 : + wdi=(PICOFFTSG_FFTTYPE)(0.097545161843*PICODSP_WGT_SHIFT); wdr=(PICOFFTSG_FFTTYPE)(0.009607359767*PICODSP_WGT_SHIFT); + w1r=(PICOFFTSG_FFTTYPE)(0.980785250664*PICODSP_WGT_SHIFT); w1i=(PICOFFTSG_FFTTYPE)(0.195090323687*PICODSP_WGT_SHIFT); + ss =(PICOFFTSG_FFTTYPE)(0.390180647373*PICODSP_WGT_SHIFT); break; + case 64 : + wdi=(PICOFFTSG_FFTTYPE)(0.049008570611*PICODSP_WGT_SHIFT); wdr=(PICOFFTSG_FFTTYPE)(0.002407636726*PICODSP_WGT_SHIFT); + w1r=(PICOFFTSG_FFTTYPE)(0.995184719563*PICODSP_WGT_SHIFT); w1i=(PICOFFTSG_FFTTYPE)(0.098017141223*PICODSP_WGT_SHIFT); + ss =(PICOFFTSG_FFTTYPE)(0.196034282446*PICODSP_WGT_SHIFT); break; + default : + wdr = 0; wdi = 0; ss = 0; + break; + } + + i = n >> 1; + for (;;) { + i0 = i - RDFT_LOOP_DIV_4; + if (i0 < 4) { + i0 = 4; + } + for (j = i - 4; j >= i0; j -= 4) { + k = n - j; + xr = a[j + 2] - a[k - 2]; + xi = a[j + 3] + a[k - 1]; + yr = Mult_W_W(wdr, xr) - Mult_W_W(wdi, xi); + yi = Mult_W_W(wdr, xi) + Mult_W_W(wdi, xr); + a[j + 2] -= yr; + a[j + 3] -= yi; + a[k - 2] += yr; + a[k - 1] -= yi; + wkr += Mult_W_W(ss, wdi); + wki += picofftsg_mult_w_w(ss, (PICOFFTSG_WGT_SHIFT2 - wdr)); + xr = a[j] - a[k]; + xi = a[j + 1] + a[k + 1]; + yr = Mult_W_W(wkr, xr) - Mult_W_W(wki, xi); + yi = Mult_W_W(wkr, xi) + Mult_W_W(wki, xr); + a[j] -= yr; + a[j + 1] -= yi; + a[k] += yr; + a[k + 1] -= yi; + wdr += Mult_W_W(ss, wki); + wdi += picofftsg_mult_w_w(ss, (PICOFFTSG_WGT_SHIFT2 - wkr)); + } + if (i0 == 4) { + break; + } + } + + xr = a[2] - a[n - 2]; + xi = a[3] + a[n - 1]; + yr = Mult_W_W(wdr, xr) - Mult_W_W(wdi, xi); + yi = Mult_W_W(wdr, xi) + Mult_W_W(wdi, xr); + + a[2] -= yr; + a[3] -= yi; + a[n - 2] += yr; + a[n - 1] -= yi; + + +} + + +void rftbsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a) +{ + picoos_int32 i, i0, j, k; + PICOFFTSG_FFTTYPE w1r, w1i, wkr, wki, wdr, wdi, ss, xr, xi, yr, yi; + wkr = 0; + wki = 0; + wdi=(PICOFFTSG_FFTTYPE)(0.012270614505*PICODSP_WGT_SHIFT); + wdr=(PICOFFTSG_FFTTYPE)(0.000150590655*PICODSP_WGT_SHIFT); + w1r=(PICOFFTSG_FFTTYPE)(0.999698817730*PICODSP_WGT_SHIFT); + w1i=(PICOFFTSG_FFTTYPE)(0.024541229010*PICODSP_WGT_SHIFT); + ss=(PICOFFTSG_FFTTYPE)(0.049082458019*PICODSP_WGT_SHIFT); + + i = n >> 1; + for (;;) { + i0 = i - RDFT_LOOP_DIV4; + if (i0 < 4) { + i0 = 4; + } + for (j = i - 4; j >= i0; j -= 4) { + k = n - j; + xr = a[j + 2] - a[k - 2]; + xi = a[j + 3] + a[k - 1]; + yr = Mult_W_W(wdr, xr) + Mult_W_W(wdi, xi); + yi = Mult_W_W(wdr, xi) - Mult_W_W(wdi, xr); + a[j + 2] -= yr; + a[j + 3] -= yi; + a[k - 2] += yr; + a[k - 1] -= yi; + wkr += Mult_W_W(ss, wdi); + wki += picofftsg_mult_w_w(ss, (PICOFFTSG_WGT_SHIFT2 - wdr)); + xr = a[j] - a[k]; + xi = a[j + 1] + a[k + 1]; + yr = Mult_W_W(wkr, xr) + Mult_W_W(wki, xi); + yi = Mult_W_W(wkr, xi) - Mult_W_W(wki, xr); + a[j] -= yr; + a[j + 1] -= yi; + a[k] += yr; + a[k + 1] -= yi; + wdr += Mult_W_W(ss, wki); + wdi += picofftsg_mult_w_w(ss, (PICOFFTSG_WGT_SHIFT2 - wkr)); + } + if (i0 == 4) { + break; + } + } + xr = a[2] - a[n - 2]; + xi = a[3] + a[n - 1]; + yr = Mult_W_W(wdr, xr) + Mult_W_W(wdi, xi); + yi = Mult_W_W(wdr, xi) - Mult_W_W(wdi, xr); + a[2] -= yr; + a[3] -= yi; + a[n - 2] += yr; + a[n - 1] -= yi; +} + + +void dctsub(picoos_int32 n, PICOFFTSG_FFTTYPE *a) +{ + picoos_int32 i, i0, j, k, m; + PICOFFTSG_FFTTYPE w1r, w1i, wkr, wki, wdr, wdi, ss, xr, xi, yr, yi; + wkr = (PICOFFTSG_FFTTYPE)(0.5*PICODSP_WGT_SHIFT); + wki = (PICOFFTSG_FFTTYPE)(0.5*PICODSP_WGT_SHIFT); + + switch (n) { + case 8 : wdi=(PICOFFTSG_FFTTYPE)(0.587937772274*PICODSP_WGT_SHIFT); + wdr=(PICOFFTSG_FFTTYPE)(0.392847478390*PICODSP_WGT_SHIFT); w1r=(PICOFFTSG_FFTTYPE)(0.980785250664*PICODSP_WGT_SHIFT); + w1i=(PICOFFTSG_FFTTYPE)(0.195090323687*PICODSP_WGT_SHIFT); ss =(PICOFFTSG_FFTTYPE)(0.390180647373*PICODSP_WGT_SHIFT); break; + case 16 : wdi=(PICOFFTSG_FFTTYPE)(0.546600937843*PICODSP_WGT_SHIFT); + wdr=(PICOFFTSG_FFTTYPE)(0.448583781719*PICODSP_WGT_SHIFT); w1r=(PICOFFTSG_FFTTYPE)(0.995184719563*PICODSP_WGT_SHIFT); + w1i=(PICOFFTSG_FFTTYPE)(0.098017141223*PICODSP_WGT_SHIFT); ss =(PICOFFTSG_FFTTYPE)(0.196034282446*PICODSP_WGT_SHIFT); break; + case 32 : wdi=(PICOFFTSG_FFTTYPE)(0.523931562901*PICODSP_WGT_SHIFT); + wdr=(PICOFFTSG_FFTTYPE)(0.474863886833*PICODSP_WGT_SHIFT); w1r=(PICOFFTSG_FFTTYPE)(0.998795449734*PICODSP_WGT_SHIFT); + w1i=(PICOFFTSG_FFTTYPE)(0.049067676067*PICODSP_WGT_SHIFT); ss =(PICOFFTSG_FFTTYPE)(0.098135352135*PICODSP_WGT_SHIFT); break; + case 64 : wdi=(PICOFFTSG_FFTTYPE)(0.512120008469*PICODSP_WGT_SHIFT); + wdr=(PICOFFTSG_FFTTYPE)(0.487578809261*PICODSP_WGT_SHIFT); w1r=(PICOFFTSG_FFTTYPE)(0.999698817730*PICODSP_WGT_SHIFT); + w1i=(PICOFFTSG_FFTTYPE)(0.024541229010*PICODSP_WGT_SHIFT); ss =(PICOFFTSG_FFTTYPE)(0.049082458019*PICODSP_WGT_SHIFT); break; + default: + wdr = 0; wdi = 0; ss = 0; break; + } + + m = n >> 1; + i = 0; + for (;;) { + i0 = i + DCST_LOOP_DIV2; + if (i0 > m - 2) { + i0 = m - 2; + } + for (j = i + 2; j <= i0; j += 2) { + k = n - j; + xr = picofftsg_mult_w_a(wdi, a[j - 1]) - picofftsg_mult_w_a(wdr, a[k + 1]); + xi = picofftsg_mult_w_a(wdr, a[j - 1]) + picofftsg_mult_w_a(wdi, a[k + 1]); + wkr -= Mult_W_W(ss, wdi); + wki += Mult_W_W(ss, wdr); + yr = Mult_W_W(wki, a[j]) - Mult_W_W(wkr, a[k]); + yi = Mult_W_W(wkr, a[j]) + Mult_W_W(wki, a[k]); + wdr -= Mult_W_W(ss, wki); + wdi += Mult_W_W(ss, wkr); + a[k + 1] = xr; + a[k] = yr; + a[j - 1] = xi; + a[j] = yi; + } + if (i0 == m - 2) { + break; + } + } + xr = picofftsg_mult_w_a(wdi, a[m - 1]) - picofftsg_mult_w_a(wdr, a[m + 1]); + a[m - 1] = picofftsg_mult_w_a(wdr, a[m - 1]) + picofftsg_mult_w_a(wdi, a[m + 1]); + a[m + 1] = xr; + a[m] = Mult_W_W(WR5000, a[m]); +} + + +void dctsub4(picoos_int32 n, PICOFFTSG_FFTTYPE *a) +{ + picoos_int32 m; + PICOFFTSG_FFTTYPE wki, wdr, wdi, xr; + + wki = WR5000; + m = n >> 1; + if (m == 2) { + wdr = Mult_W_W(wki, WI2500); + wdi = Mult_W_W(wki, WR2500); + xr = Mult_W_W(wdi, a[1]) - Mult_W_W(wdr, a[3]); + a[1] = Mult_W_W(wdr, a[1]) + Mult_W_W(wdi, a[3]); + a[3] = xr; + } + a[m] = Mult_W_W(wki, a[m]); +} + +#ifdef __cplusplus +} +#endif diff --git a/pico/lib/picofftsg.h b/pico/lib/picofftsg.h new file mode 100644 index 0000000..d9c6a1a --- /dev/null +++ b/pico/lib/picofftsg.h @@ -0,0 +1,54 @@ +/* + * 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 picofftsg.h + * + * include file for FFT/DCT related data types, constants and functions in Pico + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * +*/ +#ifndef PICOFFTSG_H_ +#define PCOFFTSG_H_ + +#include "picoos.h" +#include "picodsp.h" + + +#ifdef __cplusplus +extern "C" { + +#endif +#if 0 +} +#endif + +#define PICOFFTSG_FFTTYPE picoos_int32 + +extern void rdft(int n, int isgn, PICOFFTSG_FFTTYPE *a); +extern void dfct(int n, float *a, int VAL_SHIFT); +extern void dfct_nmf(int n, int *a); +extern float norm_result(int m2, PICOFFTSG_FFTTYPE *tmpX, PICOFFTSG_FFTTYPE *norm_window); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pico/lib/picokdbg.c b/pico/lib/picokdbg.c new file mode 100644 index 0000000..c0336ba --- /dev/null +++ b/pico/lib/picokdbg.c @@ -0,0 +1,173 @@ +/* + * 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 picokdbg.c + * + * debug support knowledge base + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#include "picoos.h" +#include "picoknow.h" +#include "picodbg.h" +#include "picokdbg.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +#if defined(PICO_DEBUG) + +/** + * @addtogroup picokdbg + + * Pico Debug Support for knowledge base \n + * + + * @b Phones + + * overview of binary file format for dbg kb: + + dbg-kb = phonesyms + + phonesyms = {PHONESYM8}=256 + + PHONESYM6: 8 bytes, symbol name (must be 0 terminated), the + corresponding ID corresponds to the offset in the + phonesyms array +*/ + +/* maximum length of phonesym string including terminating 0 */ +#define KDBG_PHONESYMLEN_MAX 8 + + +typedef struct kdbg_subobj *kdbg_SubObj; + +typedef struct kdbg_subobj { + picoos_uint8 *phonesyms; +} kdbg_subobj_t; + + +static pico_status_t kdbgInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) { + kdbg_subobj_t *kdbg; + + PICODBG_DEBUG(("start")); + + if (NULL == this || NULL == this->subObj) { + PICODBG_DEBUG(("2nd check failed")); + return picoos_emRaiseException(common->em, PICO_ERR_OTHER, NULL, NULL); + } + kdbg = (kdbg_subobj_t *)this->subObj; + kdbg->phonesyms = this->base; + return PICO_OK; +} + + +static pico_status_t kdbgSubObjDeallocate(register picoknow_KnowledgeBase this, + picoos_MemoryManager mm) { + if (NULL != this) { + picoos_deallocate(mm, (void *) &this->subObj); + } + return PICO_OK; +} + + +pico_status_t picokdbg_specializeDbgKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common) { + if (NULL == this) { + PICODBG_INFO(("no debug symbols loaded")); + return PICO_OK; + } + this->subDeallocate = kdbgSubObjDeallocate; + this->subObj = picoos_allocate(common->mm, sizeof(kdbg_subobj_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + return kdbgInitialize(this, common); +} + + +picokdbg_Dbg picokdbg_getDbg(picoknow_KnowledgeBase this) { + if (NULL == this) { + return NULL; + } else { + return (picokdbg_Dbg)this->subObj; + } +} + + +/* Dbg methods */ + +picoos_uint8 picokdbg_getPhoneId(const picokdbg_Dbg this, + const picoos_char *phsym) { + kdbg_subobj_t *kdbg; + picoos_uint16 i; + + if (this == NULL) + return 0; + + kdbg = (kdbg_subobj_t *)this; + /* sequential search */ + for (i = 0; i < 256; i++) { + if (!picoos_strcmp(phsym, + (picoos_char *)&(kdbg->phonesyms[i * KDBG_PHONESYMLEN_MAX]))) + return (picoos_uint8)i; + } + return 0; +} + + +picoos_char *picokdbg_getPhoneSym(const picokdbg_Dbg this, + const picoos_uint8 phid) { + kdbg_subobj_t *kdbg; + + if (this == NULL) + return NULL; + + kdbg = (kdbg_subobj_t *)this; + return (picoos_char *)&(kdbg->phonesyms[phid * KDBG_PHONESYMLEN_MAX]); +} + + + +#else + +/* To prevent warning about "translation unit is empty" when + diagnostic output is disabled. */ +static void picokdbg_dummy(void) { + picokdbg_dummy(); +} + + +#endif /* defined(PICO_DEBUG) */ + +#ifdef __cplusplus +} +#endif + + +/* end */ diff --git a/pico/lib/picokdbg.h b/pico/lib/picokdbg.h new file mode 100644 index 0000000..c17942f --- /dev/null +++ b/pico/lib/picokdbg.h @@ -0,0 +1,82 @@ +/* + * 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 picokdbg.h + * + * debug support knowledge base + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + *- 0.1, 08.05.2008, MRi - initial version + * + */ + +#ifndef PICOKDBG_H_ +#define PICOKDBG_H_ + + +#include "picoos.h" +#include "picoknow.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* ************************************************************/ +/* Dbg type and functions */ +/* ************************************************************/ + +/** + * to be used by picorsrc only + */ +pico_status_t picokdbg_specializeDbgKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common); + +typedef struct picokdbg_dbg *picokdbg_Dbg; + +/** + * return kb Phones for usage in PU + */ +picokdbg_Dbg picokdbg_getDbg(picoknow_KnowledgeBase this); + + +/* phone ID - phone symbol conversion functions */ + +/** + * return phone ID for phone symbol 'phsym' which must be 0 terminated + */ +picoos_uint8 picokdbg_getPhoneId(const picokdbg_Dbg dbg, + const picoos_char *phsym); + +/** + * return pointer to phone symbol for phone ID phid + */ +picoos_char *picokdbg_getPhoneSym(const picokdbg_Dbg dbg, + const picoos_uint8 phid); + +#ifdef __cplusplus +} +#endif + + +#endif /*PICOKDBG_H_*/ diff --git a/pico/lib/picokdt.c b/pico/lib/picokdt.c new file mode 100644 index 0000000..54e36ac --- /dev/null +++ b/pico/lib/picokdt.c @@ -0,0 +1,2642 @@ +/* + * 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 picokdt.c + * + * knowledge handling for decision trees + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#include "picoos.h" +#include "picodbg.h" +#include "picobase.h" +#include "picoknow.h" +#include "picodata.h" +#include "picokdt.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* ************************************************************/ +/* decision tree */ +/* ************************************************************/ + +/** + * @addtogroup picokdt + * ---------------------------------------------------\n + * Pico KDT support \n + * ---------------------------------------------------\n + overview extended binary tree file: + - dt consists of optional attribute mapping tables and a non-empty + tree part + - using the attribute mapping tables an attribute value as used + throughout the TTS can be mapped to its smaller representation + used in the tree + - multi-byte values always little endian + + ------------------------------------------------------------------- + - bin-file, decision tree knowledge base in binary form + + - dt-kb = header inputmaptables outputmaptables tree + + + - header = INPMAPTABLEPOS2 OUTMAPTABLEPOS2 TREEPOS2 + + - INPMAPTABLEPOS2: two bytes, equals offest in number of bytes from + the start of kb to the start of input map tables, + may not be 0 + - OUTMAPTABLEPOS2: two bytes, equals offest in number of bytes from + the start of kb to the start of outtables, + may not be 0 + - TREEPOS2: two bytes, equals offest in number of bytes from the + start of kb to the start of the tree + + + - inputmaptables = maptables + - outputmaptables = maptables + - maptables = NRMAPTABLES1 {maptable}=NRMAPTABLES1 + - maptable = LENTABLE2 TABLETYPE1 ( bytemaptable + | wordmaptable + | graphinmaptable + | bytetovarmaptable ) + - bytemaptable (in or out, usage varies) = NRBYTES2 {BYTE1}=NRBYTES2 + - wordmaptable (in or out, usage varies) = NRWORDS2 {WORD2}=NRWORDS2 + - graphinmaptable (in only) = NRGRAPHS2 {GRAPH1:4}=NRGRAPHS2 + - bytetovarmaptable (out only) = NRINBYTES2 outvarsearchind + outvaroutputs + - outvarsearchind = {OUTVAROFFSET2}=NRINBYTES2 + - outvaroutputs = {VARVALID1:}=NRINBYTES2 + + - bytemaptable: fixed size, *Map*Fixed \n + - wordmaptable: fixed size, *Map*Fixed \n + - graphinmaptable: search value is variable size (UTF8 grapheme), \n + value to be mapped to is fixed size, one byte \n + - bytetovarmaptable: search value is fixed size, one byte, values \n + to be mapped to are of variable size (e.g. several \n + phones) \n + + - NRMAPTABLES1: one byte representing the number of map tables + - LENTABLE2: two bytes, equals offset to the next table (or next + part of kb, e.g. tree), + if LENTABLE2 = 3, and + TABLETYPE1 = EMPTY -> empty table, no mapping to be done + - TABLETYPE1: one byte, type of map table (byte, word, or graph=utf8) + - NRBYTES2: two bytes, number of bytes following in the table (one + would be okay, to simplify some implementation also set + to 2) + - BYTE1: one btye, the sequence is used to determine the values + being mapped to, starting with 0 + - NRWORDS2: two bytes, number of words (two btyes) following in the table + - WORD2: two bytes, the sequence is used to determine the values + being mapped to, starting with 0 + - NRGRAPHS2: two bytes, number of graphemes encoded in UTF8 following + in table + - GRAPH1:4: one to four bytes, UTF8 representation of a grapheme, the + sequence of graphemes is used to determine the value being + mapped to, starting with 0, the length information is + encoded in UTF8, no need for extra length info + - NRINBYTES2: two bytes, number of single byte IDs the tree can produce + - OUTVAROFFSET2: two bytes, offset from the start of the + outvaroutputs to the start of the following output + phone ID group, ie. the first outvaroffset is the + offset to the start of the second PHONEID + group. Using the previous outvaroffset (or the start + of the outvaroutputs) the start and lenth of the + PHONEID group can be determined and we can get the + sequence of output values we map the chunk value to + - VARVALID1:: one to several bytes, one byte each for an output phone ID + + - tree = treenodeinfos TREEBODYSIZE4 treebody + - treenodeinfos = NRVFIELDS1 vfields NRATTRIBUTES1 NRQFIELDS1 qfields + - vfields = {VFIELD1}=NRVFIELDS1 + - qfields = {QFIELD1}=NRATTRIBUTES1xNRQFIELDS1 + - treebody = "cf. code" + + - TREEBODYSIZE4: four bytes, size of treebody in number of bytes + - NRVFIELDS1: one byte, number of node properties in the following + vector (predefined and fixed sequence of properties) + - VFIELD1: number of bits used to represent a node property + - NRATTRIBUTES1: one byte, number of attributes (rows) in the + following matrix + - NRQFIELDS1: one byte, number (columns) of question-dependent node + properties per attribute in the following matrix + (predefined and fixed sequence of properties) + - QFIELD1: number of bits used to represent a question-dependent + property in the matrix + + + - Currently, + - NRVFIELDS1 is fixed at 2 for all trees, ie. + - vfields = 2 aVFIELD1 bVFIELD1 + - aVFIELD1: nr of bits for questions + - bVFIELD1: nr of bits for decisions + + - NRQFIELDS1 is fixed at 5 for all trees, ie. \n + - qfields = NRATTRIBUTES1 5 aQFIELD1 bQFIELD1 cQFIELD1 dQFIELD1 eQFIELD1 \n + - aQFIELD1: nr of bits for fork count \n + - bQFIELD1: nr of bits for start position for subsets \n + - cQFIELD1: nr of bits for group size \n + - dQFIELD1: nr of bits for offset to reach output \n + - eQFIELD1: nr of bits for threshold (if continuous node) \n +*/ + + +/* ************************************************************/ +/* decision tree data defines */ +/* may not be changed with current implementation */ +/* ************************************************************/ + +/* maptables fields */ +#define PICOKDT_MTSPOS_NRMAPTABLES 0 + +/* position of first byte of first maptable (for omt the only table */ +#define PICOKDT_MTPOS_START 1 + +/* maptable fields */ +#define PICOKDT_MTPOS_LENTABLE 0 +#define PICOKDT_MTPOS_TABLETYPE 2 +#define PICOKDT_MTPOS_NUMBER 3 +#define PICOKDT_MTPOS_MAPSTART 5 + +/* treenodeinfos fields */ +#define PICOKDT_NIPOS_NRVFIELDS 0 +#define PICOKDT_NIPOS_NRATTS 3 +#define PICOKDT_NIPOS_NRQFIELDS 4 + +/* fixed treenodeinfos number of fields */ +#define PICOKDT_NODEINFO_NRVFIELDS 2 +#define PICOKDT_NODEINFO_NRQFIELDS 5 + +/* fixed number of bits used */ +#define PICOKDT_NODETYPE_NRBITS 2 +#define PICOKDT_SUBSETTYPE_NRBITS 2 +#define PICOKDT_ISDECIDE_NRBITS 1 + +/* number of inpmaptables for each tree. Since we have a possibly + empty input map table for each att, currently these values must be + equal to PICOKDT_NRATT* */ +typedef enum { + PICOKDT_NRINPMT_POSP = 12, + PICOKDT_NRINPMT_POSD = 7, + PICOKDT_NRINPMT_G2P = 16, + PICOKDT_NRINPMT_PHR = 8, + PICOKDT_NRINPMT_ACC = 13, + PICOKDT_NRINPMT_PAM = 60 +} kdt_nrinpmaptables_t; + +/* number of outmaptables for each tree, at least one, possibly empty, + output map table for each tree */ +typedef enum { + PICOKDT_NROUTMT_POSP = 1, + PICOKDT_NROUTMT_POSD = 1, + PICOKDT_NROUTMT_G2P = 1, + PICOKDT_NROUTMT_PHR = 1, + PICOKDT_NROUTMT_ACC = 1, + PICOKDT_NROUTMT_PAM = 1 +} kdt_nroutmaptables_t; + +/* maptable types */ +typedef enum { + PICOKDT_MTTYPE_EMPTY = 0, + PICOKDT_MTTYPE_BYTE = 1, + PICOKDT_MTTYPE_WORD = 2, + PICOKDT_MTTYPE_GRAPH = 3, + PICOKDT_MTTYPE_BYTETOVAR = 4 +} kdt_mttype_t; + + +/* ************************************************************/ +/* decision tree types and loading */ +/* ************************************************************/ +/* object : Dt*KnowledgeBase + * shortcut : kdt* + * derived from : picoknow_KnowledgeBase + */ + +/* subobj shared by all decision trees */ +typedef struct { + picokdt_kdttype_t type; + picoos_uint8 *inpmaptable; + picoos_uint8 *outmaptable; + picoos_uint8 *tree; + picoos_uint32 beg_offset[128]; /* for efficiency */ + + /* tree-internal details for faster processing */ + picoos_uint8 *vfields; + picoos_uint8 *qfields; + picoos_uint8 nrattributes; + picoos_uint8 *treebody; + /*picoos_uint8 nrvfields;*/ /* fix PICOKDT_NODEINFO_NRVFIELDS */ + /*picoos_uint8 nrqfields;*/ /* fix PICOKDT_NODEINFO_NRQFIELDS */ + + /* direct output vector (no output mapping) */ + picoos_uint8 dset; /* TRUE if class set, FALSE otherwise */ + picoos_uint16 dclass; +} kdt_subobj_t; + +/* subobj specific for each decision tree type */ +typedef struct { + kdt_subobj_t dt; + picoos_uint16 invec[PICOKDT_NRATT_POSP]; /* input vector */ + picoos_uint8 inveclen; /* nr of ele set in invec; must be =nrattributes */ +} kdtposp_subobj_t; + +typedef struct { + kdt_subobj_t dt; + picoos_uint16 invec[PICOKDT_NRATT_POSD]; /* input vector */ + picoos_uint8 inveclen; /* nr of ele set in invec; must be =nrattributes */ +} kdtposd_subobj_t; + +typedef struct { + kdt_subobj_t dt; + picoos_uint16 invec[PICOKDT_NRATT_G2P]; /* input vector */ + picoos_uint8 inveclen; /* nr of ele set in invec; must be =nrattributes */ +} kdtg2p_subobj_t; + +typedef struct { + kdt_subobj_t dt; + picoos_uint16 invec[PICOKDT_NRATT_PHR]; /* input vector */ + picoos_uint8 inveclen; /* nr of ele set in invec; must be =nrattributes */ +} kdtphr_subobj_t; + +typedef struct { + kdt_subobj_t dt; + picoos_uint16 invec[PICOKDT_NRATT_ACC]; /* input vector */ + picoos_uint8 inveclen; /* nr of ele set in invec; must be =nrattributes */ +} kdtacc_subobj_t; + +typedef struct { + kdt_subobj_t dt; + picoos_uint16 invec[PICOKDT_NRATT_PAM]; /* input vector */ + picoos_uint8 inveclen; /* nr of ele set in invec; must be =nrattributes */ +} kdtpam_subobj_t; + + +static pico_status_t kdtDtInitialize(register picoknow_KnowledgeBase this, + picoos_Common common, + kdt_subobj_t *dtp) { + picoos_uint16 inppos; + picoos_uint16 outpos; + picoos_uint16 treepos; + picoos_uint32 curpos = 0, pos; + picoos_uint16 lentable; + picoos_uint16 i; + picoos_uint8 imtnr; + + PICODBG_DEBUG(("start")); + + /* get inmap, outmap, tree offsets */ + if ((PICO_OK == picoos_read_mem_pi_uint16(this->base, &curpos, &inppos)) + && (PICO_OK == picoos_read_mem_pi_uint16(this->base, &curpos, &outpos)) + && (PICO_OK == picoos_read_mem_pi_uint16(this->base, &curpos, + &treepos))) { + + /* all pos are mandatory, verify */ + if (inppos && outpos && treepos) { + dtp->inpmaptable = this->base + inppos; + dtp->outmaptable = this->base + outpos; + dtp->tree = this->base + treepos; + /* precalc beg offset table */ + imtnr=dtp->inpmaptable[0]; + pos=1; + dtp->beg_offset[0] = 1; + for (i = 0; i < imtnr; i++) { + lentable = ((picoos_uint16)(dtp->inpmaptable[pos+1])) << 8 | + dtp->inpmaptable[pos]; + pos += lentable; + dtp->beg_offset[i+1] = pos; + } + } else { + dtp->inpmaptable = NULL; + dtp->outmaptable = NULL; + dtp->tree = NULL; + PICODBG_ERROR(("invalid kb position info")); + return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, + NULL, NULL); + } + + /* nr of outmaptables is equal 1 for all trees, verify */ + if (dtp->outmaptable[PICOKDT_MTSPOS_NRMAPTABLES] != 1) { + PICODBG_ERROR(("wrong number of outmaptables")); + return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, + NULL, NULL); + } + + /* check if this is an empty table, ie. len == 3 */ + if ((dtp->outmaptable[PICOKDT_MTPOS_START + PICOKDT_MTPOS_LENTABLE] + == 3) + && (dtp->outmaptable[PICOKDT_MTPOS_START + PICOKDT_MTPOS_LENTABLE + + 1] == 0)) { + /* verify that this is supposed to be an empty table and + set outmaptable to NULL if so */ + if (dtp->outmaptable[PICOKDT_MTPOS_START + PICOKDT_MTPOS_TABLETYPE] + == PICOKDT_MTTYPE_EMPTY) { + dtp->outmaptable = NULL; + } else { + PICODBG_ERROR(("table length vs. type problem")); + return picoos_emRaiseException(common->em, + PICO_EXC_FILE_CORRUPT, + NULL, NULL); + } + } + + dtp->vfields = dtp->tree + 1; + dtp->qfields = dtp->tree + PICOKDT_NODEINFO_NRVFIELDS + 3; + dtp->nrattributes = dtp->tree[PICOKDT_NIPOS_NRATTS]; + dtp->treebody = dtp->qfields + 4 + + (dtp->nrattributes * PICOKDT_NODEINFO_NRQFIELDS); /* TREEBODYSIZE4*/ + + /*dtp->nrvfields = dtp->tree[PICOKDT_NIPOS_NRVFIELDS]; <- is fix */ + /*dtp->nrqfields = dtp->tree[PICOKDT_NIPOS_NRQFIELDS]; <- is fix */ + /* verify that nrvfields ad nrqfields are correct */ + if ((PICOKDT_NODEINFO_NRVFIELDS != dtp->tree[PICOKDT_NIPOS_NRVFIELDS]) || + (PICOKDT_NODEINFO_NRQFIELDS != dtp->tree[PICOKDT_NIPOS_NRQFIELDS])) { + PICODBG_ERROR(("problem with nr of vfields (%d) or qfields (%d)", + dtp->tree[PICOKDT_NIPOS_NRVFIELDS], + dtp->tree[PICOKDT_NIPOS_NRQFIELDS])); + return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, + NULL, NULL); + } + dtp->dset = 0; + dtp->dclass = 0; + PICODBG_DEBUG(("tree init: nratt: %d, posomt: %d, postree: %d", + dtp->nrattributes, (dtp->outmaptable - dtp->inpmaptable), + (dtp->tree - dtp->inpmaptable))); + return PICO_OK; + } else { + PICODBG_ERROR(("problem reading kb in memory")); + return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, + NULL, NULL); + } +} + + +static pico_status_t kdtDtCheck(register picoknow_KnowledgeBase this, + picoos_Common common, + kdt_subobj_t *dtp, + kdt_nratt_t nratt, + kdt_nrinpmaptables_t nrinpmt, + kdt_nroutmaptables_t nroutmt, + kdt_mttype_t mttype) { + /* check nr attributes */ + /* check nr inpmaptables */ + /* check nr outmaptables */ + /* check outmaptable is word type */ + if ((nratt != dtp->nrattributes) + || (dtp->inpmaptable == NULL) + || (dtp->outmaptable == NULL) + || (dtp->inpmaptable[PICOKDT_MTSPOS_NRMAPTABLES] != nrinpmt) + || (dtp->outmaptable[PICOKDT_MTSPOS_NRMAPTABLES] != nroutmt) + || (dtp->outmaptable[PICOKDT_MTPOS_START+PICOKDT_MTPOS_TABLETYPE] + != mttype)) { + PICODBG_ERROR(("check failed, nratt %d, nrimt %d, nromt %d, omttype %d", + dtp->nrattributes, + dtp->inpmaptable[PICOKDT_MTSPOS_NRMAPTABLES], + dtp->outmaptable[PICOKDT_MTSPOS_NRMAPTABLES], + dtp->outmaptable[PICOKDT_MTPOS_START + + PICOKDT_MTPOS_TABLETYPE])); + return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, + NULL, NULL); + } + return PICO_OK; +} + + + +static pico_status_t kdtPosPInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) { + pico_status_t status; + kdtposp_subobj_t *dtposp; + kdt_subobj_t *dt; + picoos_uint8 i; + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + dtposp = (kdtposp_subobj_t *)this->subObj; + dt = &(dtposp->dt); + dt->type = PICOKDT_KDTTYPE_POSP; + if ((status = kdtDtInitialize(this, common, dt)) != PICO_OK) { + return status; + } + if ((status = kdtDtCheck(this, common, dt, PICOKDT_NRATT_POSP, + PICOKDT_NRINPMT_POSP, PICOKDT_NROUTMT_POSP, + PICOKDT_MTTYPE_WORD)) != PICO_OK) { + return status; + } + + /* init specialized subobj part */ + for (i = 0; i < PICOKDT_NRATT_POSP; i++) { + dtposp->invec[i] = 0; + } + dtposp->inveclen = 0; + PICODBG_DEBUG(("posp tree initialized")); + return PICO_OK; +} + + +static pico_status_t kdtPosDInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) { + pico_status_t status; + kdtposd_subobj_t *dtposd; + kdt_subobj_t *dt; + picoos_uint8 i; + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + dtposd = (kdtposd_subobj_t *)this->subObj; + dt = &(dtposd->dt); + dt->type = PICOKDT_KDTTYPE_POSD; + if ((status = kdtDtInitialize(this, common, dt)) != PICO_OK) { + return status; + } + if ((status = kdtDtCheck(this, common, dt, PICOKDT_NRATT_POSD, + PICOKDT_NRINPMT_POSD, PICOKDT_NROUTMT_POSD, + PICOKDT_MTTYPE_WORD)) != PICO_OK) { + return status; + } + + /* init spezialized subobj part */ + for (i = 0; i < PICOKDT_NRATT_POSD; i++) { + dtposd->invec[i] = 0; + } + dtposd->inveclen = 0; + PICODBG_DEBUG(("posd tree initialized")); + return PICO_OK; +} + + +static pico_status_t kdtG2PInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) { + pico_status_t status; + kdtg2p_subobj_t *dtg2p; + kdt_subobj_t *dt; + picoos_uint8 i; + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + dtg2p = (kdtg2p_subobj_t *)this->subObj; + dt = &(dtg2p->dt); + dt->type = PICOKDT_KDTTYPE_G2P; + if ((status = kdtDtInitialize(this, common, dt)) != PICO_OK) { + return status; + } + + if ((status = kdtDtCheck(this, common, dt, PICOKDT_NRATT_G2P, + PICOKDT_NRINPMT_G2P, PICOKDT_NROUTMT_G2P, + PICOKDT_MTTYPE_BYTETOVAR)) != PICO_OK) { + return status; + } + + /* init spezialized subobj part */ + for (i = 0; i < PICOKDT_NRATT_G2P; i++) { + dtg2p->invec[i] = 0; + } + dtg2p->inveclen = 0; + PICODBG_DEBUG(("g2p tree initialized")); + return PICO_OK; +} + + +static pico_status_t kdtPhrInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) { + pico_status_t status; + kdtphr_subobj_t *dtphr; + kdt_subobj_t *dt; + picoos_uint8 i; + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + dtphr = (kdtphr_subobj_t *)this->subObj; + dt = &(dtphr->dt); + dt->type = PICOKDT_KDTTYPE_PHR; + if ((status = kdtDtInitialize(this, common,dt)) != PICO_OK) { + return status; + } + + if ((status = kdtDtCheck(this, common, dt, PICOKDT_NRATT_PHR, + PICOKDT_NRINPMT_PHR, PICOKDT_NROUTMT_PHR, + PICOKDT_MTTYPE_WORD)) != PICO_OK) { + return status; + } + + /* init spezialized subobj part */ + for (i = 0; i < PICOKDT_NRATT_PHR; i++) { + dtphr->invec[i] = 0; + } + dtphr->inveclen = 0; + PICODBG_DEBUG(("phr tree initialized")); + return PICO_OK; +} + + +static pico_status_t kdtAccInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) { + pico_status_t status; + kdtacc_subobj_t *dtacc; + kdt_subobj_t *dt; + picoos_uint8 i; + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + dtacc = (kdtacc_subobj_t *)this->subObj; + dt = &(dtacc->dt); + dt->type = PICOKDT_KDTTYPE_ACC; + if ((status = kdtDtInitialize(this, common, dt)) != PICO_OK) { + return status; + } + + if ((status = kdtDtCheck(this, common, dt, PICOKDT_NRATT_ACC, + PICOKDT_NRINPMT_ACC, PICOKDT_NROUTMT_ACC, + PICOKDT_MTTYPE_WORD)) != PICO_OK) { + return status; + } + + /* init spezialized subobj part */ + for (i = 0; i < PICOKDT_NRATT_ACC; i++) { + dtacc->invec[i] = 0; + } + dtacc->inveclen = 0; + PICODBG_DEBUG(("acc tree initialized")); + return PICO_OK; +} + + +static pico_status_t kdtPamInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) { + pico_status_t status; + kdtpam_subobj_t *dtpam; + kdt_subobj_t *dt; + picoos_uint8 i; + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + dtpam = (kdtpam_subobj_t *)this->subObj; + dt = &(dtpam->dt); + dt->type = PICOKDT_KDTTYPE_PAM; + if ((status = kdtDtInitialize(this, common, dt)) != PICO_OK) { + return status; + } + + if ((status = kdtDtCheck(this, common, dt, PICOKDT_NRATT_PAM, + PICOKDT_NRINPMT_PAM, PICOKDT_NROUTMT_PAM, + PICOKDT_MTTYPE_WORD)) != PICO_OK) { + return status; + } + + /* init spezialized subobj part */ + for (i = 0; i < PICOKDT_NRATT_PAM; i++) { + dtpam->invec[i] = 0; + } + dtpam->inveclen = 0; + PICODBG_DEBUG(("pam tree initialized")); + return PICO_OK; +} + + +static pico_status_t kdtSubObjDeallocate(register picoknow_KnowledgeBase this, + picoos_MemoryManager mm) { + if (NULL != this) { + picoos_deallocate(mm, (void *) &this->subObj); + } + return PICO_OK; +} + + +/* we don't offer a specialized constructor for a *KnowledgeBase but + * instead a "specializer" of an allready existing generic + * picoknow_KnowledgeBase */ + +pico_status_t picokdt_specializeDtKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common, + const picokdt_kdttype_t kdttype) { + pico_status_t status; + + if (NULL == this) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + this->subDeallocate = kdtSubObjDeallocate; + switch (kdttype) { + case PICOKDT_KDTTYPE_POSP: + this->subObj = picoos_allocate(common->mm,sizeof(kdtposp_subobj_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + status = kdtPosPInitialize(this, common); + break; + case PICOKDT_KDTTYPE_POSD: + this->subObj = picoos_allocate(common->mm,sizeof(kdtposd_subobj_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + status = kdtPosDInitialize(this, common); + break; + case PICOKDT_KDTTYPE_G2P: + this->subObj = picoos_allocate(common->mm,sizeof(kdtg2p_subobj_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + status = kdtG2PInitialize(this, common); + break; + case PICOKDT_KDTTYPE_PHR: + this->subObj = picoos_allocate(common->mm,sizeof(kdtphr_subobj_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + status = kdtPhrInitialize(this, common); + break; + case PICOKDT_KDTTYPE_ACC: + this->subObj = picoos_allocate(common->mm,sizeof(kdtacc_subobj_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + status = kdtAccInitialize(this, common); + break; + case PICOKDT_KDTTYPE_PAM: + this->subObj = picoos_allocate(common->mm,sizeof(kdtpam_subobj_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + status = kdtPamInitialize(this, common); + break; + default: + return picoos_emRaiseException(common->em, PICO_ERR_OTHER, + NULL, NULL); + } + + if (status != PICO_OK) { + picoos_deallocate(common->mm, (void *) &this->subObj); + return picoos_emRaiseException(common->em, status, NULL, NULL); + } + return PICO_OK; +} + + +/* ************************************************************/ +/* decision tree getDt* */ +/* ************************************************************/ + +picokdt_DtPosP picokdt_getDtPosP(picoknow_KnowledgeBase this) { + return ((NULL == this) ? NULL : ((picokdt_DtPosP) this->subObj)); +} + +picokdt_DtPosD picokdt_getDtPosD(picoknow_KnowledgeBase this) { + return ((NULL == this) ? NULL : ((picokdt_DtPosD) this->subObj)); +} + +picokdt_DtG2P picokdt_getDtG2P (picoknow_KnowledgeBase this) { + return ((NULL == this) ? NULL : ((picokdt_DtG2P) this->subObj)); +} + +picokdt_DtPHR picokdt_getDtPHR (picoknow_KnowledgeBase this) { + return ((NULL == this) ? NULL : ((picokdt_DtPHR) this->subObj)); +} + +picokdt_DtACC picokdt_getDtACC (picoknow_KnowledgeBase this) { + return ((NULL == this) ? NULL : ((picokdt_DtACC) this->subObj)); +} + +picokdt_DtPAM picokdt_getDtPAM (picoknow_KnowledgeBase this) { + return ((NULL == this) ? NULL : ((picokdt_DtPAM) this->subObj)); +} + + + +/* ************************************************************/ +/* decision tree support functions, tree */ +/* ************************************************************/ + + +typedef enum { + eQuestion = 0, /* index to #bits to identify question */ + eDecide = 1 /* index to #bits to identify decision */ +} kdt_vfields_ind_t; + +typedef enum { + eForkCount = 0, /* index to #bits for number of forks */ + eBitNo = 1, /* index to #bits for index of 1st element */ + eBitCount = 2, /* index to #bits for size of the group */ + eJump = 3, /* index to #bits for offset to reach output node */ + eCut = 4 /* for contin. node: #bits for threshold checked */ +} kdt_qfields_ind_t; + +typedef enum { + eNTerminal = 0, + eNBinary = 1, + eNContinuous = 2, + eNDiscrete = 3 +} kdt_nodetypes_t; + +typedef enum { + eOneValue = 0, + eTwoValues = 1, + eWithoutBitMask = 2, + eBitMask = 3 +} kdt_subsettypes_t; + + +/* Name : kdt_jump + Function: maps the iJump offset to byte + bit coordinates + Input : iJump absolute bit offset (0..(nr-bytes-treebody)*8) + Output : iByteNo the first byte containing the bits to extract + (0..(nr-bytes-treebody)) + iBitNo the first bit to be extracted (0..7) + Returns : void + Notes : updates the iByteNo + iBitNo fields +*/ +static void kdt_jump(const picoos_uint32 iJump, + picoos_uint32 *iByteNo, + picoos_int8 *iBitNo) { + picoos_uint32 iByteSize; + + iByteSize = (iJump / 8 ); + *iBitNo = (iJump - (iByteSize * 8)) + (7 - *iBitNo); + *iByteNo += iByteSize; + if (*iBitNo >= 8) { + (*iByteNo)++; + *iBitNo = 15 - *iBitNo; + } else { + *iBitNo = 7 - *iBitNo; + } +} + + +/* replaced inline for speedup */ +/* Name : kdtIsVal + Function: Returns the binary value of the bit pointed to by iByteNo, iBitNo + Input : iByteNo ofsset to the byte containing the bits to extract + (0..sizeof(treebody)) + iBitNo ofsset to the first bit to be extracted (0..7) + Returns : 0/1 depending on the bit pointed to +*/ +/* +static picoos_uint8 kdtIsVal(register kdt_subobj_t *this, + picoos_uint32 iByteNo, + picoos_int8 iBitNo) { + return ((this->treebody[iByteNo] & ((1)< 0); +} +*/ + + +/* @todo : consider replacing inline for speedup */ + +/* Name : kdtGetQFieldsVal (was: m_QuestDependentFields) + Function: gets a byte from qfields + Input : this handle to a dt subobj + attind index of the attribute + qind index of the byte to be read + Returns : the requested byte + Notes : check that attind < this->nrattributes needed before calling + this function! +*/ +static picoos_uint8 kdtGetQFieldsVal(register kdt_subobj_t *this, + const picoos_uint8 attind, + const kdt_qfields_ind_t qind) { + /* check of qind done in initialize and (for some compilers) with typing */ + /* check of attind needed before calling this function */ + return this->qfields[(attind * PICOKDT_NODEINFO_NRQFIELDS) + qind]; +} + + +/* Name : kdtGetShiftVal (was: get_shift_value) + Function: returns the (treebody) value pointed to by iByteNo, iBitNo, + and with size iSize + Input : this reference to the processing unit struct + iSize number of bits to be extracted (0..N) + iByteNo ofsset to the byte containing the bits to extract + (0..sizeof(treebody)) + iBitNo ofsset to the first bit to be extracted (0..7) + Returns : the value requested (if size==0 --> 0 is returned) +*/ +/* +static picoos_uint32 orig_kdtGetShiftVal(register kdt_subobj_t *this, + const picoos_int16 iSize, + picoos_uint32 *iByteNo, + picoos_int8 *iBitNo) { + picoos_uint32 iVal; + picoos_int16 i; + + iVal = 0; + for (i = iSize-1; i >= 0; i--) { + if ( (this->treebody[*iByteNo] & ((1)<<(*iBitNo))) > 0) { + iVal |= ( (1) << i ); + } + (*iBitNo)--; + if (*iBitNo < 0) { + *iBitNo = 7; + (*iByteNo)++; + } + } + return iVal; +} +*/ +/* refactor */ +static picoos_uint32 kdtGetShiftVal(register kdt_subobj_t *this, + const picoos_int16 iSize, picoos_uint32 *iByteNo, picoos_int8 *iBitNo) +{ + picoos_uint32 v, b, iVal; + picoos_int16 i, j, len; + picoos_uint8 val; + + if (iSize < 4) { + iVal = 0; + for (i = iSize - 1; i >= 0; i--) { + /* no check that *iByteNo is within valid treebody range */ + if ((this->treebody[*iByteNo] & ((1) << (*iBitNo))) > 0) { + iVal |= ((1) << i); + } + (*iBitNo)--; + if (*iBitNo < 0) { + *iBitNo = 7; + (*iByteNo)++; + } + } + return iVal; + } + + b = *iByteNo; + j = *iBitNo; + len = iSize; + *iBitNo = j - iSize; + v = 0; + while (*iBitNo < 0) { + *iBitNo += 8; + (*iByteNo)++; + } + + val = this->treebody[b++]; + if (j < 7) { + switch (j) { + case 0: + val &= 0x01; + break; + case 1: + val &= 0x03; + break; + case 2: + val &= 0x07; + break; + case 3: + val &= 0x0f; + break; + case 4: + val &= 0x1f; + break; + case 5: + val &= 0x3f; + break; + case 6: + val &= 0x7f; + break; + } + } + len -= j + 1; + if (len < 0) { + val >>= -len; + } + v = val; + while (len > 0) { + if (len >= 8) { + j = 8; + } else { + j = len; + } + v <<= j; + val = this->treebody[b++]; + if (j < 8) { + switch (j) { + case 1: + val &= 0x80; + val >>= 7; + break; + case 2: + val &= 0xc0; + val >>= 6; + break; + case 3: + val &= 0xe0; + val >>= 5; + break; + case 4: + val &= 0xf0; + val >>= 4; + break; + case 5: + val &= 0xf8; + val >>= 3; + break; + case 6: + val &= 0xfc; + val >>= 2; + break; + case 7: + val &= 0xfe; + val >>= 1; + break; + } + } + v |= val; + len -= j; + } + return v; +} + + +/* Name : kdtAskTree + Function: Tree Traversal routine + Input : iByteNo ofsset to the first byte containing the bits + to extract (0..sizeof(treebody)) + iBitNo ofsset to the first bit to be extracted (0..7) + Returns : >0 continue, no solution yet found + =0 solution found + <0 error, no solution found + Notes : +*/ +static picoos_int8 kdtAskTree(register kdt_subobj_t *this, + picoos_uint16 *invec, + const kdt_nratt_t invecmax, + picoos_uint32 *iByteNo, + picoos_int8 *iBitNo) { + picoos_uint32 iNodeType; + picoos_uint8 iQuestion; + picoos_int32 iVal; + picoos_int32 iForks; + picoos_int32 iID; + + picoos_int32 iCut, iSubsetType, iBitPos, iBitCount, iPos, iJump, iDecision; + picoos_int32 i; + picoos_char iIsDecide; + + PICODBG_TRACE(("start")); + + /* get node type, value should be in kdt_nodetype_t range */ + iNodeType = kdtGetShiftVal(this, PICOKDT_NODETYPE_NRBITS, iByteNo, iBitNo); + PICODBG_TRACE(("iNodeType: %d", iNodeType)); + + /* get attribute to be used in question, check if in range, and get val */ + /* check of vfields argument done in initialize */ + iQuestion = kdtGetShiftVal(this, this->vfields[eQuestion], iByteNo, iBitNo); + if ((iQuestion < this->nrattributes) && (iQuestion < invecmax)) { + iVal = invec[iQuestion]; + } else { + this->dset = FALSE; + PICODBG_TRACE(("invalid question")); + return -1; /* iQuestion invalid */ + } + iForks = 0; + iID = -1; + PICODBG_TRACE(("iQuestion: %d", iQuestion)); + + switch (iNodeType) { + case eNBinary: { + iForks = 2; + iID = iVal; + break; + } + case eNContinuous: { + iForks = 2; + iID = 1; + iCut = kdtGetShiftVal(this, kdtGetQFieldsVal(this, iQuestion, eCut), + iByteNo, iBitNo); /*read the threshold*/ + if (iVal <= iCut) { + iID = 0; + } + break; + } + case eNDiscrete: { + iForks = + kdtGetShiftVal(this, + kdtGetQFieldsVal(this, iQuestion, eForkCount), + iByteNo, iBitNo); + + for (i = 0; i < iForks-1; i++) { + iSubsetType = + kdtGetShiftVal(this, PICOKDT_SUBSETTYPE_NRBITS, + iByteNo, iBitNo); + + switch (iSubsetType) { + case eOneValue: { + if (iID > -1) { + kdt_jump(kdtGetQFieldsVal(this, iQuestion, eBitNo), + iByteNo, iBitNo); + break; + } + iBitPos = + kdtGetShiftVal(this, + kdtGetQFieldsVal(this, iQuestion, + eBitNo), + iByteNo, iBitNo); + if (iVal == iBitPos) { + iID = i; + } + break; + } + case eTwoValues: { + if (iID > -1) { + kdt_jump((kdtGetQFieldsVal(this, iQuestion, eBitNo) + + kdtGetQFieldsVal(this, iQuestion, eBitCount)), + iByteNo, iBitNo); + break; + } + + iBitPos = + kdtGetShiftVal(this, kdtGetQFieldsVal(this, iQuestion, + eBitNo), + iByteNo, iBitNo); + iBitCount = + kdtGetShiftVal(this, kdtGetQFieldsVal(this, iQuestion, + eBitCount), + iByteNo, iBitNo); + if ((iVal == iBitPos) || (iVal == iBitCount)) { + iID = i; + } + break; + } + case eWithoutBitMask: { + if (iID > -1) { + kdt_jump((kdtGetQFieldsVal(this, iQuestion, eBitNo) + + kdtGetQFieldsVal(this, iQuestion, eBitCount)), + iByteNo, iBitNo); + break; + } + + iBitPos = + kdtGetShiftVal(this, kdtGetQFieldsVal(this, iQuestion, + eBitNo), + iByteNo, iBitNo); + iBitCount = + kdtGetShiftVal(this, kdtGetQFieldsVal(this, iQuestion, + eBitCount), + iByteNo, iBitNo); + if ((iVal >= iBitPos) && (iVal < (iBitPos + iBitCount))) { + iID = i; + } + break; + } + case eBitMask: { + iBitPos = 0; + if (iID > -1) { + kdt_jump(kdtGetQFieldsVal(this, iQuestion, eBitNo), + iByteNo, iBitNo); + } else { + iBitPos = + kdtGetShiftVal(this, + kdtGetQFieldsVal(this, iQuestion, + eBitNo), + iByteNo, iBitNo); + } + + iBitCount = + kdtGetShiftVal(this, + kdtGetQFieldsVal(this, iQuestion, + eBitCount), + iByteNo, iBitNo); + if (iID > -1) { + kdt_jump(iBitCount, iByteNo, iBitNo); + break; + } + + if ((iVal >= iBitPos) && (iVal < (iBitPos + iBitCount))) { + iPos = iVal - iBitPos; + kdt_jump((iVal - iBitPos), iByteNo, iBitNo); + /* if (kdtIsVal(this, *iByteNo, *iBitNo))*/ + if ((this->treebody[*iByteNo] & ((1)<<(*iBitNo))) > 0) { + iID = i; + } + kdt_jump((iBitCount - (iVal-iBitPos)), iByteNo, iBitNo); + } else { + kdt_jump(iBitCount, iByteNo, iBitNo); + } + break; + }/*end case eBitMask*/ + }/*end switch (iSubsetType)*/ + }/*end for ( i = 0; i < iForks-1; i++ ) */ + + /*default tree branch*/ + if (-1 == iID) { + iID = iForks-1; + } + break; + }/*end case eNDiscrete*/ + }/*end switch (iNodeType)*/ + + for (i = 0; i < iForks; i++) { + iIsDecide = kdtGetShiftVal(this, PICOKDT_ISDECIDE_NRBITS, iByteNo, iBitNo); + + PICODBG_TRACE(("doing forks: %d", i)); + + if (!iIsDecide) { + if (iID == i) { + iJump = + kdtGetShiftVal(this, kdtGetQFieldsVal(this, iQuestion, eJump), + iByteNo, iBitNo); + kdt_jump(iJump, iByteNo, iBitNo); + this->dset = FALSE; + return 1; /* to be continued, no solution yet found */ + } else { + kdt_jump(kdtGetQFieldsVal(this, iQuestion, eJump), + iByteNo, iBitNo); + } + } else { + if (iID == i) { + /* check of vfields argument done in initialize */ + iDecision = kdtGetShiftVal(this, this->vfields[eDecide], + iByteNo, iBitNo); + this->dclass = iDecision; + this->dset = TRUE; + return 0; /* solution found */ + } else { + /* check of vfields argument done in initialize */ + kdt_jump(this->vfields[eDecide], iByteNo, iBitNo); + } + }/*end if (!iIsDecide)*/ + }/*end for (i = 0; i < iForks; i++ )*/ + + this->dset = FALSE; + PICODBG_TRACE(("problem determining class")); + return -1; /* solution not found, problem determining a class */ +} + + + +/* ************************************************************/ +/* decision tree support functions, mappings */ +/* ************************************************************/ + + +/* size==1 -> MapInByte, size==2 -> MapInWord, + size determined from table type contained in kb. + if the inmaptable is empty, outval = inval */ + +static picoos_uint8 kdtMapInFixed(const kdt_subobj_t *dt, + const picoos_uint8 imtnr, + const picoos_uint16 inval, + picoos_uint16 *outval, + picoos_uint16 *outfallbackval) { + picoos_uint8 size; + picoos_uint32 pos; + picoos_uint16 lentable; + picoos_uint16 posbound; + picoos_uint16 i; + + *outval = 0; + *outfallbackval = 0; + + size = 0; + pos = 0; + + /* check what can be checked */ + if (imtnr >= dt->inpmaptable[pos++]) { /* outside tablenr range? */ + PICODBG_ERROR(("check failed: nrtab: %d, imtnr: %d", + dt->inpmaptable[pos-1], imtnr)); + return FALSE; + } + + /* go forward to the needed tablenr */ + if (imtnr > 0) { + pos = dt->beg_offset[imtnr]; + } + + /* get length */ + lentable = ((picoos_uint16)(dt->inpmaptable[pos+1])) << 8 | + dt->inpmaptable[pos]; + posbound = pos + lentable; + pos += 2; + + /* check type of table and set size */ + if (dt->inpmaptable[pos] == PICOKDT_MTTYPE_EMPTY) { + /* empty table no mapping needed */ + PICODBG_TRACE(("empty table: %d", imtnr)); + *outval = inval; + return TRUE; + } else if (dt->inpmaptable[pos] == PICOKDT_MTTYPE_BYTE) { + size = 1; + } else if (dt->inpmaptable[pos] == PICOKDT_MTTYPE_WORD) { + size = 2; + } else { + /* wrong table type */ + PICODBG_ERROR(("wrong table type %d", dt->inpmaptable[pos])); + return FALSE; + } + pos++; + + /* set fallback value in case of failed mapping, and set upper bound pos */ + *outfallbackval = ((picoos_uint16)(dt->inpmaptable[pos+1])) << 8 | + dt->inpmaptable[pos]; + pos += 2; + + /* size must be 1 or 2 here, keep 'redundant' so save time */ + if (size == 1) { + for (i = 0; (i < *outfallbackval) && (pos < posbound); i++) { + if (inval == dt->inpmaptable[pos]) { + *outval = i; + PICODBG_TRACE(("s1 %d in %d -> out %d", imtnr, inval, *outval)); + return TRUE; + } + pos++; + } + } else if (size == 2) { + posbound--; + for (i = 0; (i < *outfallbackval) && (pos < posbound); i++) { + if (inval == (((picoos_uint16)(dt->inpmaptable[pos+1])) << 8 | + dt->inpmaptable[pos])) { + *outval = i; + PICODBG_TRACE(("s2 %d in %d -> out %d", imtnr, inval, *outval)); + return TRUE; + } + pos += 2; + } + } else { + /* impossible size */ + PICODBG_ERROR(("wrong size %d", size)); + return FALSE; + } + + PICODBG_DEBUG(("no mapping found, fallback: %d", *outfallbackval)); + return FALSE; +} + + +static picoos_uint8 kdtMapInGraph(const kdt_subobj_t *dt, + const picoos_uint8 imtnr, + const picoos_uint8 *inval, + const picoos_uint8 invalmaxlen, + picoos_uint16 *outval, + picoos_uint16 *outfallbackval) { + picoos_uint8 ilen; + picoos_uint8 tlen; + picoos_uint8 cont; + picoos_uint32 pos; + picoos_uint16 lentable; + picoos_uint16 posbound; + picoos_uint16 i; + picoos_uint8 j; + + *outfallbackval = 0; + + pos = 0; + /* check what can be checked */ + if ((imtnr >= dt->inpmaptable[pos++]) || /* outside tablenr range? */ + (invalmaxlen == 0) || /* too short? */ + ((ilen = picobase_det_utf8_length(inval[0])) == 0) || /* invalid? */ + (ilen > invalmaxlen)) { /* not accessible? */ + PICODBG_ERROR(("check failed: nrtab: %d, imtnr: %d, invalmaxlen: %d, " + "ilen: %d", + dt->inpmaptable[pos-1], imtnr, invalmaxlen, ilen)); + return FALSE; + } + + /* go forward to the needed tablenr */ + for (i = 0; i < imtnr; i++) { + lentable = ((picoos_uint16)(dt->inpmaptable[pos+1])) << 8 | + dt->inpmaptable[pos]; + pos += lentable; + } + + /* get length and check type of inpmaptable */ + lentable = ((picoos_uint16)(dt->inpmaptable[pos+1])) << 8 | + dt->inpmaptable[pos]; + posbound = pos + lentable; + pos += 2; + +#if defined(PICO_DEBUG) + if (1) { + int id; + PICODBG_TRACE(("imtnr %d", imtnr)); + for (id = pos-2; id < posbound; id++) { + PICODBG_TRACE(("imtbyte pos %d, %c %d", id - (pos-2), + dt->inpmaptable[id], dt->inpmaptable[id])); + } + } +#endif + + /* check type of table */ + if (dt->inpmaptable[pos] != PICOKDT_MTTYPE_GRAPH) { + /* empty table does not make sense for graph */ + /* wrong table type */ + PICODBG_ERROR(("wrong table type")); + return FALSE; + } + pos++; + + /* set fallback value in case of failed mapping, and set upper bound pos */ + *outfallbackval = ((picoos_uint16)(dt->inpmaptable[pos+1])) << 8 | + dt->inpmaptable[pos]; + pos += 2; + + /* sequential search */ + for (i = 0; (i < *outfallbackval) && (pos < posbound); i++) { + tlen = picobase_det_utf8_length(dt->inpmaptable[pos]); + if ((pos + tlen) > posbound) { + PICODBG_ERROR(("trying outside imt, posb: %d, pos: %d, tlen: %d", + posbound, pos, tlen)); + return FALSE; + } + if (ilen == tlen) { + cont = TRUE; + for (j = 0; cont && (j < ilen); j++) { + if (dt->inpmaptable[pos + j] != inval[j]) { + cont = FALSE; + } + } + if (cont && (j == ilen)) { /* match found */ + *outval = i; + PICODBG_TRACE(("found mapval, posb %d, pos %d, i %d, tlen %d", + posbound, pos, i, tlen)); + return TRUE; + } + } + pos += tlen; + } + PICODBG_DEBUG(("outside imt %d, posb/pos/i: %d/%d/%d, fallback: %d", + imtnr, posbound, pos, i, *outfallbackval)); + return FALSE; +} + + +/* size==1 -> MapOutByte, size==2 -> MapOutWord */ +static picoos_uint8 kdtMapOutFixed(const kdt_subobj_t *dt, + const picoos_uint16 inval, + picoos_uint16 *outval) { + picoos_uint8 size; + picoos_uint16 nr; + + /* no check of lentable vs. nr in initialize done */ + + size = 0; + + /* type */ + nr = dt->outmaptable[PICOKDT_MTPOS_START + PICOKDT_MTPOS_TABLETYPE]; + + /* check type of table and set size */ + if (nr == PICOKDT_MTTYPE_EMPTY) { + /* empty table no mapping needed */ + PICODBG_TRACE(("empty table")); + *outval = inval; + return TRUE; + } else if (nr == PICOKDT_MTTYPE_BYTE) { + size = 1; + } else if (nr == PICOKDT_MTTYPE_WORD) { + size = 2; + } else { + /* wrong table type */ + PICODBG_ERROR(("wrong table type %d", nr)); + return FALSE; + } + + /* number of mapvalues */ + nr = ((picoos_uint16)(dt->outmaptable[PICOKDT_MTPOS_START + + PICOKDT_MTPOS_NUMBER + 1])) << 8 + | dt->outmaptable[PICOKDT_MTPOS_START + PICOKDT_MTPOS_NUMBER]; + + if (inval < nr) { + if (size == 1) { + *outval = dt->outmaptable[PICOKDT_MTPOS_START + + PICOKDT_MTPOS_MAPSTART + (size * inval)]; + } else { + *outval = ((picoos_uint16)(dt->outmaptable[PICOKDT_MTPOS_START + + PICOKDT_MTPOS_MAPSTART + (size * inval) + 1])) << 8 + | dt->outmaptable[PICOKDT_MTPOS_START + + PICOKDT_MTPOS_MAPSTART + (size * inval)]; + } + return TRUE; + } else { + *outval = 0; + return FALSE; + } +} + + +/* size==1 -> ReverseMapOutByte, size==2 -> ReverseMapOutWord */ +/* outmaptable also used to map from decoded tree output domain to + direct tree output domain */ +static picoos_uint8 kdtReverseMapOutFixed(const kdt_subobj_t *dt, + const picoos_uint16 inval, + picoos_uint16 *outval, + picoos_uint16 *outfallbackval) { + picoos_uint8 size; + picoos_uint32 pos; + picoos_uint16 lentable; + picoos_uint16 posbound; + picoos_uint16 i; + + /* no check of lentable vs. nr in initialize done */ + + size = 0; + pos = 0; + *outval = 0; + *outfallbackval = 0; + + if (dt->outmaptable == NULL) { + /* empty table no mapping needed */ + PICODBG_TRACE(("empty table")); + *outval = inval; + return TRUE; + } + + /* check what can be checked */ + if (dt->outmaptable[pos++] != 1) { /* only one omt possible */ + PICODBG_ERROR(("check failed: nrtab: %d", dt->outmaptable[pos-1])); + return FALSE; + } + + /* get length */ + lentable = ((picoos_uint16)(dt->outmaptable[pos+1])) << 8 | + dt->outmaptable[pos]; + posbound = pos + lentable; + pos += 2; + + /* check type of table and set size */ + /* if (dt->outmaptable[pos] == PICOKDT_MTTYPE_EMPTY), in + ...Initialize the omt is set to NULL if not existing, checked + above */ + + if (dt->outmaptable[pos] == PICOKDT_MTTYPE_BYTE) { + size = 1; + } else if (dt->outmaptable[pos] == PICOKDT_MTTYPE_WORD) { + size = 2; + } else { + /* wrong table type */ + PICODBG_ERROR(("wrong table type %d", dt->outmaptable[pos])); + return FALSE; + } + pos++; + + /* set fallback value in case of failed mapping, and set upper bound pos */ + *outfallbackval = ((picoos_uint16)(dt->outmaptable[pos+1])) << 8 | + dt->outmaptable[pos]; + pos += 2; + + /* size must be 1 or 2 here, keep 'redundant' so save time */ + if (size == 1) { + for (i = 0; (i < *outfallbackval) && (pos < posbound); i++) { + if (inval == dt->outmaptable[pos]) { + *outval = i; + PICODBG_TRACE(("s1 inval %d -> outval %d", inval, *outval)); + return TRUE; + } + pos++; + } + } else if (size == 2) { + posbound--; + for (i = 0; (i < *outfallbackval) && (pos < posbound); i++) { + if (inval == (((picoos_uint16)(dt->outmaptable[pos+1])) << 8 | + dt->outmaptable[pos])) { + *outval = i; + PICODBG_TRACE(("s2 inval %d -> outval %d", inval, *outval)); + return TRUE; + } + pos += 2; + } + } else { + /* impossible size */ + PICODBG_ERROR(("wrong size %d", size)); + return FALSE; + } + + PICODBG_DEBUG(("no mapping found, fallback: %d", *outfallbackval)); + return FALSE; +} + + +picoos_uint8 picokdt_dtPosDreverseMapOutFixed(const picokdt_DtPosD this, + const picoos_uint16 inval, + picoos_uint16 *outval, + picoos_uint16 *outfallbackval) { + + kdtposd_subobj_t * dtposd = (kdtposd_subobj_t *)this; + kdt_subobj_t * dt = &(dtposd->dt); + return kdtReverseMapOutFixed(dt,inval, outval, outfallbackval); +} + +/* not yet impl. size==1 -> MapOutByteToVar, + fix: size==2 -> MapOutWordToVar */ +static picoos_uint8 kdtMapOutVar(const kdt_subobj_t *dt, + const picoos_uint16 inval, + picoos_uint8 *nr, + picoos_uint16 *outval, + const picoos_uint16 outvalmaxlen) { + picoos_uint16 pos; + picoos_uint16 off2ind; + picoos_uint16 lentable; + picoos_uint16 nrinbytes; + picoos_uint8 size; + picoos_uint16 offset1; + picoos_uint16 i; + + if (dt->outmaptable == NULL) { + /* empty table not possible */ + PICODBG_ERROR(("no table found")); + return FALSE; + } + + /* nr of tables == 1 already checked in *Initialize, no need here, go + directly to position 1 */ + pos = 1; + + /* get length of table */ + lentable = (((picoos_uint16)(dt->outmaptable[pos + 1])) << 8 | + dt->outmaptable[pos]); + pos += 2; + + /* check table type */ + if (dt->outmaptable[pos] != PICOKDT_MTTYPE_BYTETOVAR) { + /* wrong table type */ + PICODBG_ERROR(("wrong table type %d", dt->outmaptable[pos])); + return FALSE; + } + size = 2; + pos++; + + /* get nr of ele in maptable (= nr of possible invals) */ + nrinbytes = (((picoos_uint16)(dt->outmaptable[pos+1])) << 8 | + dt->outmaptable[pos]); + pos += 2; + + /* check what's checkable */ + if (nrinbytes == 0) { + PICODBG_ERROR(("table with length zero")); + return FALSE; + } else if (inval >= nrinbytes) { + PICODBG_ERROR(("inval %d outside valid range %d", inval, nrinbytes)); + return FALSE; + } + + PICODBG_TRACE(("inval %d, lentable %d, nrinbytes %d, pos %d", inval, + lentable, nrinbytes, pos)); + + /* set off2ind to the position of the start of offset2-val */ + /* offset2 points to start of next ele */ + off2ind = pos + (size*inval); + + /* get number of output values, offset2 - offset1 */ + if (inval == 0) { + offset1 = 0; + } else { + offset1 = (((picoos_uint16)(dt->outmaptable[off2ind - 1])) << 8 | + dt->outmaptable[off2ind - 2]); + } + *nr = (((picoos_uint16)(dt->outmaptable[off2ind + 1])) << 8 | + dt->outmaptable[off2ind]) - offset1; + + PICODBG_TRACE(("offset1 %d, nr %d, pos %d", offset1, *nr, pos)); + + /* set pos to position of 1st value being mapped to */ + pos += (size * nrinbytes) + offset1; + + if ((pos + *nr - 1) > lentable) { + /* outside table, should not happen */ + PICODBG_ERROR(("problem with table index, pos %d, nr %d, len %d", + pos, *nr, lentable)); + return FALSE; + } + if (*nr > outvalmaxlen) { + /* not enough space in outval */ + PICODBG_ERROR(("overflow in outval, %d > %d", *nr, outvalmaxlen)); + return FALSE; + } + + /* finally, copy outmap result to outval */ + for (i = 0; i < *nr; i++) { + outval[i] = dt->outmaptable[pos++]; + } + return TRUE; +} + + + +/* ************************************************************/ +/* decision tree POS prediction (PosP) functions */ +/* ************************************************************/ + +/* number of prefix and suffix graphemes used to construct the input vector */ +#define KDT_POSP_NRGRAPHPREFATT 4 +#define KDT_POSP_NRGRAPHSUFFATT 6 +#define KDT_POSP_NRGRAPHATT 10 + +/* positions of specgraph and nrgraphs attributes */ +#define KDT_POSP_SPECGRAPHATTPOS 10 +#define KDT_POSP_NRGRAPHSATTPOS 11 + + +/* construct PosP input vector + + PosP invec: 12 elements + + prefix 0-3 prefix graphemes (encoded using tree inpmaptable 0-3) + suffix 4-9 suffix graphemes (encoded using tree inpmaptable 4-9) + isspecchar 10 is a special grapheme (e.g. hyphen) inside the word (0/1)? + nr-utf-graphs 11 number of graphemes (ie. UTF8 chars) + + if there are less than 10 graphemes, each grapheme is used only + once, with the suffix having higher priority, ie. elements 0-9 are + filled as follows: + + #graph + 1 0 0 0 0 0 0 0 0 0 1 + 2 0 0 0 0 0 0 0 0 1 2 + 3 0 0 0 0 0 0 0 1 2 3 + 4 0 0 0 0 0 0 1 2 3 4 + 5 0 0 0 0 0 1 2 3 4 5 + 6 0 0 0 0 1 2 3 4 5 6 + 7 1 0 0 0 2 3 4 5 6 7 + 8 1 2 0 0 3 4 5 6 7 8 + 9 1 2 3 0 4 5 6 7 8 9 + 10 1 2 3 4 5 6 7 8 9 10 + 11 1 2 3 4 6 7 8 9 10 11 + ... + + 1-6: Fill chbuf + 7-10: front to invec 1st part, remove front, add rear + >10: remove front, add rear + no more graph -> + while chbuflen>0: + add rear to the last empty slot in 2nd part of invec, remove rear +*/ + + +picoos_uint8 picokdt_dtPosPconstructInVec(const picokdt_DtPosP this, + const picoos_uint8 *graph, + const picoos_uint16 graphlen, + const picoos_uint8 specgraphflag) { + kdtposp_subobj_t *dtposp; + + /* utf8 circular char buffer, used as restricted input deque */ + /* 2nd part of graph invec has KDT_POSP_NRGRAPHSUFFATT elements, */ + /* max of UTF8_MAXLEN bytes per utf8 char */ + picoos_uint8 chbuf[KDT_POSP_NRGRAPHSUFFATT][PICOBASE_UTF8_MAXLEN]; + picoos_uint8 chbrear; /* next free pos */ + picoos_uint8 chbfront; /* next read pos */ + picoos_uint8 chblen; /* empty=0; full=KDT_POSP_NRGRAPHSUFFATT */ + + picoos_uint16 poscg; /* position of current graph (= utf8 char) */ + picoos_uint16 lencg = 0; /* length of current grapheme */ + picoos_uint16 nrutfg; /* number of utf graphemes */ + picoos_uint8 invecpos; /* next element to add in invec */ + picoos_uint16 fallback; /* fallback value for failed graph encodings */ + picoos_uint8 i; + + dtposp = (kdtposp_subobj_t *)this; + chbrear = 0; + chbfront = 0; + chblen = 0; + poscg = 0; + nrutfg = 0; + invecpos = 0; + + PICODBG_DEBUG(("graphlen %d", graphlen)); + + /* not needed, since all elements are set + for (i = 0; i < PICOKDT_NRATT_POSP; i++) { + dtposp->invec[i] = '\x63'; + } + */ + + dtposp->inveclen = 0; + + while ((poscg < graphlen) && + ((lencg = picobase_det_utf8_length(graph[poscg])) > 0)) { + if (chblen >= KDT_POSP_NRGRAPHSUFFATT) { /* chbuf full */ + if (invecpos < KDT_POSP_NRGRAPHPREFATT) { /* prefix not full */ + /* att-encode front utf graph and add in invec */ + if (!kdtMapInGraph(&(dtposp->dt), invecpos, + chbuf[chbfront], PICOBASE_UTF8_MAXLEN, + &(dtposp->invec[invecpos]), + &fallback)) { + if (fallback) { + dtposp->invec[invecpos] = fallback; + } else { + return FALSE; + } + } + invecpos++; + } + /* remove front utf graph */ + chbfront++; + chbfront %= KDT_POSP_NRGRAPHSUFFATT; + chblen--; + } + /* add current utf graph to chbuf */ + for (i=0; i 0) { + + while (invecpos < KDT_POSP_NRGRAPHPREFATT) { /* fill up prefix */ + if (!kdtMapInGraph(&(dtposp->dt), invecpos, + PICOKDT_OUTSIDEGRAPH_DEFSTR, + PICOKDT_OUTSIDEGRAPH_DEFLEN, + &(dtposp->invec[invecpos]), &fallback)) { + if (fallback) { + dtposp->invec[invecpos] = fallback; + } else { + return FALSE; + } + } + invecpos++; + } + + for (i = (KDT_POSP_NRGRAPHATT - 1); + i >= KDT_POSP_NRGRAPHPREFATT; i--) { + if (chblen > 0) { + if (chbrear == 0) { + chbrear = KDT_POSP_NRGRAPHSUFFATT - 1; + } else { + chbrear--; + } + if (!kdtMapInGraph(&(dtposp->dt), i, chbuf[chbrear], + PICOBASE_UTF8_MAXLEN, + &(dtposp->invec[i]), &fallback)) { + if (fallback) { + dtposp->invec[i] = fallback; + } else { + return FALSE; + } + } + chblen--; + } else { + if (!kdtMapInGraph(&(dtposp->dt), i, + PICOKDT_OUTSIDEGRAPH_DEFSTR, + PICOKDT_OUTSIDEGRAPH_DEFLEN, + &(dtposp->invec[i]), &fallback)) { + if (fallback) { + dtposp->invec[i] = fallback; + } else { + return FALSE; + } + } + } + } + + /* set isSpecChar attribute, reuse var i */ + i = (specgraphflag ? 1 : 0); + if (!kdtMapInFixed(&(dtposp->dt), KDT_POSP_SPECGRAPHATTPOS, i, + &(dtposp->invec[KDT_POSP_SPECGRAPHATTPOS]), + &fallback)) { + if (fallback) { + dtposp->invec[KDT_POSP_SPECGRAPHATTPOS] = fallback; + } else { + return FALSE; + } + } + + /* set nrGraphs attribute */ + if (!kdtMapInFixed(&(dtposp->dt), KDT_POSP_NRGRAPHSATTPOS, nrutfg, + &(dtposp->invec[KDT_POSP_NRGRAPHSATTPOS]), + &fallback)) { + if (fallback) { + dtposp->invec[KDT_POSP_NRGRAPHSATTPOS] = fallback; + } else { + return FALSE; + } + } + PICODBG_DEBUG(("posp-invec: [%d,%d,%d,%d|%d,%d,%d,%d,%d,%d|%d|%d]", + dtposp->invec[0], dtposp->invec[1], dtposp->invec[2], + dtposp->invec[3], dtposp->invec[4], dtposp->invec[5], + dtposp->invec[6], dtposp->invec[7], dtposp->invec[8], + dtposp->invec[9], dtposp->invec[10], + dtposp->invec[11], dtposp->invec[12])); + dtposp->inveclen = PICOKDT_NRINPMT_POSP; + return TRUE; + } + + return FALSE; +} + + +picoos_uint8 picokdt_dtPosPclassify(const picokdt_DtPosP this) { + picoos_uint32 iByteNo; + picoos_int8 iBitNo; + picoos_int8 rv; + kdtposp_subobj_t *dtposp; + kdt_subobj_t *dt; + + dtposp = (kdtposp_subobj_t *)this; + dt = &(dtposp->dt); + iByteNo = 0; + iBitNo = 7; + while ((rv = kdtAskTree(dt, dtposp->invec, PICOKDT_NRATT_POSP, + &iByteNo, &iBitNo)) > 0) { + PICODBG_TRACE(("asking tree")); + } + PICODBG_DEBUG(("done: %d", dt->dclass)); + return ((rv == 0) && dt->dset); +} + + +picoos_uint8 picokdt_dtPosPdecomposeOutClass(const picokdt_DtPosP this, + picokdt_classify_result_t *dtres) { + kdtposp_subobj_t *dtposp; + picoos_uint16 val; + + dtposp = (kdtposp_subobj_t *)this; + + if (dtposp->dt.dset && + kdtMapOutFixed(&(dtposp->dt), dtposp->dt.dclass, &val)) { + dtres->set = TRUE; + dtres->class = val; + return TRUE; + } else { + dtres->set = FALSE; + return FALSE; + } +} + + + +/* ************************************************************/ +/* decision tree POS disambiguation (PosD) functions */ +/* ************************************************************/ + + +picoos_uint8 picokdt_dtPosDconstructInVec(const picokdt_DtPosD this, + const picoos_uint16 * input) { + kdtposd_subobj_t *dtposd; + picoos_uint8 i; + picoos_uint16 fallback = 0; + + dtposd = (kdtposd_subobj_t *)this; + dtposd->inveclen = 0; + + PICODBG_DEBUG(("in: [%d,%d,%d|%d|%d,%d,%d]", + input[0], input[1], input[2], + input[3], input[4], input[5], + input[6])); + for (i = 0; i < PICOKDT_NRATT_POSD; i++) { + + /* do the imt mapping for all inval */ + if (!kdtMapInFixed(&(dtposd->dt), i, input[i], + &(dtposd->invec[i]), &fallback)) { + if (fallback) { + PICODBG_DEBUG(("*** using fallback for input mapping: %i -> %i", input[i], fallback)); + dtposd->invec[i] = fallback; + } else { + PICODBG_ERROR(("problem doing input mapping")); + return FALSE; + } + } + } + + PICODBG_DEBUG(("out: [%d,%d,%d|%d|%d,%d,%d]", + dtposd->invec[0], dtposd->invec[1], dtposd->invec[2], + dtposd->invec[3], dtposd->invec[4], dtposd->invec[5], + dtposd->invec[6])); + dtposd->inveclen = PICOKDT_NRINPMT_POSD; + return TRUE; +} + + +picoos_uint8 picokdt_dtPosDclassify(const picokdt_DtPosD this, + picoos_uint16 *treeout) { + picoos_uint32 iByteNo; + picoos_int8 iBitNo; + picoos_int8 rv; + kdtposd_subobj_t *dtposd; + kdt_subobj_t *dt; + + dtposd = (kdtposd_subobj_t *)this; + dt = &(dtposd->dt); + iByteNo = 0; + iBitNo = 7; + while ((rv = kdtAskTree(dt, dtposd->invec, PICOKDT_NRATT_POSD, + &iByteNo, &iBitNo)) > 0) { + PICODBG_TRACE(("asking tree")); + } + PICODBG_DEBUG(("done: %d", dt->dclass)); + if ((rv == 0) && dt->dset) { + *treeout = dt->dclass; + return TRUE; + } else { + return FALSE; + } +} + + +/* decompose the tree output and return the class in dtres + dtres: POS classification result + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtPosDdecomposeOutClass(const picokdt_DtPosD this, + picokdt_classify_result_t *dtres) { + kdtposd_subobj_t *dtposd; + picoos_uint16 val; + + dtposd = (kdtposd_subobj_t *)this; + + if (dtposd->dt.dset && + kdtMapOutFixed(&(dtposd->dt), dtposd->dt.dclass, &val)) { + dtres->set = TRUE; + dtres->class = val; + return TRUE; + } else { + dtres->set = FALSE; + return FALSE; + } +} + + + +/* ************************************************************/ +/* decision tree grapheme-to-phoneme (G2P) functions */ +/* ************************************************************/ + + +/* get the nr'th (starting at 0) utf char in utfgraph */ +static picoos_uint8 kdtGetUTF8char(const picoos_uint8 *utfgraph, + const picoos_uint16 graphlen, + const picoos_uint16 nr, + picoos_uint8 *utf8char) { + picoos_uint16 i; + picoos_uint32 pos; + + pos = 0; + for (i = 0; i < nr; i++) { + if (!picobase_get_next_utf8charpos(utfgraph, graphlen, &pos)) { + return FALSE; + } + } + return picobase_get_next_utf8char(utfgraph, graphlen, &pos, utf8char); +} + +/* determine the utfchar count (starting at 1) of the utfchar starting at pos */ +static picoos_uint16 kdtGetUTF8Nr(const picoos_uint8 *utfgraph, + const picoos_uint16 graphlen, + const picoos_uint16 pos) { + picoos_uint32 postmp; + picoos_uint16 count; + + count = 0; + postmp = 0; + while ((postmp <= pos) && (count < graphlen)) { + if (!picobase_get_next_utf8charpos(utfgraph, graphlen, &postmp)) { + PICODBG_ERROR(("invalid utf8 string, count: %d, pos: %d, post: %d", + count, pos, postmp)); + return count + 1; + } + count++; + } + return count; +} + + +picoos_uint8 picokdt_dtG2PconstructInVec(const picokdt_DtG2P this, + const picoos_uint8 *graph, + const picoos_uint16 graphlen, + const picoos_uint8 count, + const picoos_uint8 pos, + const picoos_uint8 nrvow, + const picoos_uint8 ordvow, + picoos_uint8 *primstressflag, + const picoos_uint16 phonech1, + const picoos_uint16 phonech2, + const picoos_uint16 phonech3) { + kdtg2p_subobj_t *dtg2p; + picoos_uint16 fallback = 0; + picoos_uint8 iAttr; + picoos_uint8 utf8char[PICOBASE_UTF8_MAXLEN + 1]; + picoos_uint16 inval; + picoos_int16 cinv; + picoos_uint8 retval; + picoos_int32 utfgraphlen; + picoos_uint16 utfcount; + + dtg2p = (kdtg2p_subobj_t *)this; + retval = TRUE; + inval = 0; + + PICODBG_TRACE(("in: [%d,%d,%d|%d,%d|%d|%d,%d,%d]", graphlen, count, pos, + nrvow, ordvow, *primstressflag, phonech1, phonech2, + phonech3)); + + dtg2p->inveclen = 0; + + /* many speed-ups possible */ + + /* graph attributes */ + /* count > = <= count + iAttr lowbound eow upbound delta + 0 4 4 graphlen 5 + 1 3 3 graphlen 4 + 2 2 2 graphlen 3 + 3 1 1 graphlen 2 + 4 0 - graphlen 1 + + 5 0 graphlen graphlen-1 0 + 6 0 graphlen-1 graphlen-2 -1 + 7 0 graphlen-2 graphlen-3 -2 + 8 0 graphlen-3 graphlen-4 -3 + */ + + /* graph attributes left (context -4/-3/-2/-1) and current, MapInGraph */ + + utfgraphlen = picobase_utf8_length(graph, graphlen); + if (utfgraphlen <= 0) { + utfgraphlen = 0; + } + utfcount = kdtGetUTF8Nr(graph, graphlen, count); + + cinv = 4; + for (iAttr = 0; iAttr < 5; iAttr++) { + if ((utfcount > cinv) && (utfcount <= utfgraphlen)) { + +/* utf8char[0] = graph[count - cinv - 1];*/ + if (!kdtGetUTF8char(graph, graphlen, utfcount-cinv-1, + utf8char)) { + PICODBG_WARN(("problem getting UTF char %d", utfcount-cinv-1)); + utf8char[0] = PICOKDT_OUTSIDEGRAPH_DEFCH; + utf8char[1] = '\0'; + } + } else { + if ((utfcount == cinv) && (iAttr != 4)) { + utf8char[0] = PICOKDT_OUTSIDEGRAPH_EOW_DEFCH; + } else { + utf8char[0] = PICOKDT_OUTSIDEGRAPH_DEFCH; + } + utf8char[1] = '\0'; + } + + if (!kdtMapInGraph(&(dtg2p->dt), iAttr, + utf8char, PICOBASE_UTF8_MAXLEN, + &(dtg2p->invec[iAttr]), + &fallback)) { + if (fallback) { + dtg2p->invec[iAttr] = fallback; + } else { + PICODBG_WARN(("setting attribute %d to zero", iAttr)); + dtg2p->invec[iAttr] = 0; + retval = FALSE; + } + } + PICODBG_TRACE(("invec %d %c", iAttr, utf8char[0])); + cinv--; + } + + /* graph attributes right (context 1/2/3/4), MapInGraph */ + cinv = utfgraphlen; + for (iAttr = 5; iAttr < 9; iAttr++) { + if ((utfcount > 0) && (utfcount <= (cinv - 1))) { +/* utf8char[0] = graph[count + graphlen - cinv];*/ + if (!kdtGetUTF8char(graph, graphlen, utfcount+utfgraphlen-cinv, + utf8char)) { + PICODBG_WARN(("problem getting UTF char %d", + utfcount+utfgraphlen-cinv-1)); + utf8char[0] = PICOKDT_OUTSIDEGRAPH_DEFCH; + utf8char[1] = '\0'; + } + } else { + if (utfcount == cinv) { + utf8char[0] = PICOKDT_OUTSIDEGRAPH_EOW_DEFCH; + utf8char[1] = '\0'; + } else { + utf8char[0] = PICOKDT_OUTSIDEGRAPH_DEFCH; + utf8char[1] = '\0'; + } + } + if (!kdtMapInGraph(&(dtg2p->dt), iAttr, + utf8char, PICOBASE_UTF8_MAXLEN, + &(dtg2p->invec[iAttr]), + &fallback)) { + if (fallback) { + dtg2p->invec[iAttr] = fallback; + } else { + PICODBG_WARN(("setting attribute %d to zero", iAttr)); + dtg2p->invec[iAttr] = 0; + retval = FALSE; + } + } + PICODBG_TRACE(("invec %d %c", iAttr, utf8char[0])); + cinv--; + } + + /* other attributes, MapInFixed */ + for (iAttr = 9; iAttr < PICOKDT_NRATT_G2P; iAttr++) { + switch (iAttr) { + case 9: /* word POS, Fix1 */ + inval = pos; + break; + case 10: /* nr of vowel-like graphs in word, if vowel, Fix2 */ + inval = nrvow; + break; + case 11: /* order of current vowel-like graph in word, Fix2 */ + inval = ordvow; + break; + case 12: /* primary stress mark, Fix2 */ + if (*primstressflag == 1) { + /*already set previously*/ + inval = 1; + } else { + inval = 0; + } + break; + case 13: /* phone chunk right context +1, Hist */ + inval = phonech1; + break; + case 14: /* phone chunk right context +2, Hist */ + inval = phonech2; + break; + case 15: /* phone chunk right context +3, Hist */ + inval = phonech3; + break; + } + + PICODBG_TRACE(("invec %d %d", iAttr, inval)); + + if (!kdtMapInFixed(&(dtg2p->dt), iAttr, inval, + &(dtg2p->invec[iAttr]), &fallback)) { + if (fallback) { + dtg2p->invec[iAttr] = fallback; + } else { + PICODBG_WARN(("setting attribute %d to zero", iAttr)); + dtg2p->invec[iAttr] = 0; + retval = FALSE; + } + } + } + + PICODBG_TRACE(("out: [%d,%d%,%d,%d|%d|%d,%d,%d,%d|%d,%d,%d,%d|" + "%d,%d,%d]", dtg2p->invec[0], dtg2p->invec[1], + dtg2p->invec[2], dtg2p->invec[3], dtg2p->invec[4], + dtg2p->invec[5], dtg2p->invec[6], dtg2p->invec[7], + dtg2p->invec[8], dtg2p->invec[9], dtg2p->invec[10], + dtg2p->invec[11], dtg2p->invec[12], dtg2p->invec[13], + dtg2p->invec[14], dtg2p->invec[15])); + + dtg2p->inveclen = PICOKDT_NRINPMT_G2P; + return retval; +} + + + + +picoos_uint8 picokdt_dtG2Pclassify(const picokdt_DtG2P this, + picoos_uint16 *treeout) { + picoos_uint32 iByteNo; + picoos_int8 iBitNo; + picoos_int8 rv; + kdtg2p_subobj_t *dtg2p; + kdt_subobj_t *dt; + + dtg2p = (kdtg2p_subobj_t *)this; + dt = &(dtg2p->dt); + iByteNo = 0; + iBitNo = 7; + while ((rv = kdtAskTree(dt, dtg2p->invec, PICOKDT_NRATT_G2P, + &iByteNo, &iBitNo)) > 0) { + PICODBG_TRACE(("asking tree")); + } + PICODBG_TRACE(("done: %d", dt->dclass)); + if ((rv == 0) && dt->dset) { + *treeout = dt->dclass; + return TRUE; + } else { + return FALSE; + } +} + + + +picoos_uint8 picokdt_dtG2PdecomposeOutClass(const picokdt_DtG2P this, + picokdt_classify_vecresult_t *dtvres) { + kdtg2p_subobj_t *dtg2p; + + dtg2p = (kdtg2p_subobj_t *)this; + + if (dtg2p->dt.dset && + kdtMapOutVar(&(dtg2p->dt), dtg2p->dt.dclass, &(dtvres->nr), + dtvres->classvec, PICOKDT_MAXSIZE_OUTVEC)) { + return TRUE; + } else { + dtvres->nr = 0; + return FALSE; + } + return TRUE; +} + + + +/* ************************************************************/ +/* decision tree phrasing (PHR) functions */ +/* ************************************************************/ + +picoos_uint8 picokdt_dtPHRconstructInVec(const picokdt_DtPHR this, + const picoos_uint8 pre2, + const picoos_uint8 pre1, + const picoos_uint8 src, + const picoos_uint8 fol1, + const picoos_uint8 fol2, + const picoos_uint16 nrwordspre, + const picoos_uint16 nrwordsfol, + const picoos_uint16 nrsyllsfol) { + kdtphr_subobj_t *dtphr; + picoos_uint8 i; + picoos_uint16 inval = 0; + picoos_uint16 fallback = 0; + + dtphr = (kdtphr_subobj_t *)this; + PICODBG_DEBUG(("in: [%d,%d|%d|%d,%d|%d,%d,%d]", + pre2, pre1, src, fol1, fol2, + nrwordspre, nrwordsfol, nrsyllsfol)); + dtphr->inveclen = 0; + + for (i = 0; i < PICOKDT_NRATT_PHR; i++) { + switch (i) { + case 0: inval = pre2; break; + case 1: inval = pre1; break; + case 2: inval = src; break; + case 3: inval = fol1; break; + case 4: inval = fol2; break; + case 5: inval = nrwordspre; break; + case 6: inval = nrwordsfol; break; + case 7: inval = nrsyllsfol; break; + default: + PICODBG_ERROR(("size mismatch")); + return FALSE; + break; + } + + /* do the imt mapping for all inval */ + if (!kdtMapInFixed(&(dtphr->dt), i, inval, + &(dtphr->invec[i]), &fallback)) { + if (fallback) { + dtphr->invec[i] = fallback; + } else { + PICODBG_ERROR(("problem doing input mapping")); + return FALSE; + } + } + } + + PICODBG_DEBUG(("out: [%d,%d|%d|%d,%d|%d,%d,%d]", + dtphr->invec[0], dtphr->invec[1], dtphr->invec[2], + dtphr->invec[3], dtphr->invec[4], dtphr->invec[5], + dtphr->invec[6], dtphr->invec[7])); + dtphr->inveclen = PICOKDT_NRINPMT_PHR; + return TRUE; +} + + +picoos_uint8 picokdt_dtPHRclassify(const picokdt_DtPHR this) { + picoos_uint32 iByteNo; + picoos_int8 iBitNo; + picoos_int8 rv; + kdtphr_subobj_t *dtphr; + kdt_subobj_t *dt; + + dtphr = (kdtphr_subobj_t *)this; + dt = &(dtphr->dt); + iByteNo = 0; + iBitNo = 7; + while ((rv = kdtAskTree(dt, dtphr->invec, PICOKDT_NRATT_PHR, + &iByteNo, &iBitNo)) > 0) { + PICODBG_TRACE(("asking tree")); + } + PICODBG_DEBUG(("done: %d", dt->dclass)); + return ((rv == 0) && dt->dset); +} + + +picoos_uint8 picokdt_dtPHRdecomposeOutClass(const picokdt_DtPHR this, + picokdt_classify_result_t *dtres) { + kdtphr_subobj_t *dtphr; + picoos_uint16 val; + + dtphr = (kdtphr_subobj_t *)this; + + if (dtphr->dt.dset && + kdtMapOutFixed(&(dtphr->dt), dtphr->dt.dclass, &val)) { + dtres->set = TRUE; + dtres->class = val; + return TRUE; + } else { + dtres->set = FALSE; + return FALSE; + } +} + + + +/* ************************************************************/ +/* decision tree phono-acoustical model (PAM) functions */ +/* ************************************************************/ + +picoos_uint8 picokdt_dtPAMconstructInVec(const picokdt_DtPAM this, + const picoos_uint8 *vec, + const picoos_uint8 veclen) { + kdtpam_subobj_t *dtpam; + picoos_uint8 i; + picoos_uint16 fallback = 0; + + dtpam = (kdtpam_subobj_t *)this; + + PICODBG_TRACE(("in0: %d %d %d %d %d %d %d %d %d %d", + vec[0], vec[1], vec[2], vec[3], vec[4], + vec[5], vec[6], vec[7], vec[8], vec[9])); + PICODBG_TRACE(("in1: %d %d %d %d %d %d %d %d %d %d", + vec[10], vec[11], vec[12], vec[13], vec[14], + vec[15], vec[16], vec[17], vec[18], vec[19])); + PICODBG_TRACE(("in2: %d %d %d %d %d %d %d %d %d %d", + vec[20], vec[21], vec[22], vec[23], vec[24], + vec[25], vec[26], vec[27], vec[28], vec[29])); + PICODBG_TRACE(("in3: %d %d %d %d %d %d %d %d %d %d", + vec[30], vec[31], vec[32], vec[33], vec[34], + vec[35], vec[36], vec[37], vec[38], vec[39])); + PICODBG_TRACE(("in4: %d %d %d %d %d %d %d %d %d %d", + vec[40], vec[41], vec[42], vec[43], vec[44], + vec[45], vec[46], vec[47], vec[48], vec[49])); + PICODBG_TRACE(("in5: %d %d %d %d %d %d %d %d %d %d", + vec[50], vec[51], vec[52], vec[53], vec[54], + vec[55], vec[56], vec[57], vec[58], vec[59])); + + dtpam->inveclen = 0; + + /* check veclen */ + if (veclen != PICOKDT_NRINPMT_PAM) { + PICODBG_ERROR(("wrong number of input vector elements")); + return FALSE; + } + + for (i = 0; i < PICOKDT_NRATT_PAM; i++) { + + /* do the imt mapping for all vec eles */ + if (!kdtMapInFixed(&(dtpam->dt), i, vec[i], + &(dtpam->invec[i]), &fallback)) { + if (fallback) { + dtpam->invec[i] = fallback; + } else { + PICODBG_ERROR(("problem doing input mapping, %d %d", i,vec[i])); + return FALSE; + } + } + } + + PICODBG_TRACE(("in0: %d %d %d %d %d %d %d %d %d %d", + dtpam->invec[0], dtpam->invec[1], dtpam->invec[2], + dtpam->invec[3], dtpam->invec[4], dtpam->invec[5], + dtpam->invec[6], dtpam->invec[7], dtpam->invec[8], + dtpam->invec[9])); + PICODBG_TRACE(("in1: %d %d %d %d %d %d %d %d %d %d", + dtpam->invec[10], dtpam->invec[11], dtpam->invec[12], + dtpam->invec[13], dtpam->invec[14], dtpam->invec[15], + dtpam->invec[16], dtpam->invec[17], dtpam->invec[18], + dtpam->invec[19])); + PICODBG_TRACE(("in2: %d %d %d %d %d %d %d %d %d %d", + dtpam->invec[20], dtpam->invec[21], dtpam->invec[22], + dtpam->invec[23], dtpam->invec[24], dtpam->invec[25], + dtpam->invec[26], dtpam->invec[27], dtpam->invec[28], + dtpam->invec[29])); + PICODBG_TRACE(("in3: %d %d %d %d %d %d %d %d %d %d", + dtpam->invec[30], dtpam->invec[31], dtpam->invec[32], + dtpam->invec[33], dtpam->invec[34], dtpam->invec[35], + dtpam->invec[36], dtpam->invec[37], dtpam->invec[38], + dtpam->invec[39])); + PICODBG_TRACE(("in4: %d %d %d %d %d %d %d %d %d %d", + dtpam->invec[40], dtpam->invec[41], dtpam->invec[42], + dtpam->invec[43], dtpam->invec[44], dtpam->invec[45], + dtpam->invec[46], dtpam->invec[47], dtpam->invec[48], + dtpam->invec[49])); + PICODBG_TRACE(("in5: %d %d %d %d %d %d %d %d %d %d", + dtpam->invec[50], dtpam->invec[51], dtpam->invec[52], + dtpam->invec[53], dtpam->invec[54], dtpam->invec[55], + dtpam->invec[56], dtpam->invec[57], dtpam->invec[58], + dtpam->invec[59])); + + dtpam->inveclen = PICOKDT_NRINPMT_PAM; + return TRUE; +} + + +picoos_uint8 picokdt_dtPAMclassify(const picokdt_DtPAM this) { + picoos_uint32 iByteNo; + picoos_int8 iBitNo; + picoos_int8 rv; + kdtpam_subobj_t *dtpam; + kdt_subobj_t *dt; + + dtpam = (kdtpam_subobj_t *)this; + dt = &(dtpam->dt); + iByteNo = 0; + iBitNo = 7; + while ((rv = kdtAskTree(dt, dtpam->invec, PICOKDT_NRATT_PAM, + &iByteNo, &iBitNo)) > 0) { + PICODBG_TRACE(("asking tree")); + } + PICODBG_DEBUG(("done: %d", dt->dclass)); + return ((rv == 0) && dt->dset); +} + + +picoos_uint8 picokdt_dtPAMdecomposeOutClass(const picokdt_DtPAM this, + picokdt_classify_result_t *dtres) { + kdtpam_subobj_t *dtpam; + picoos_uint16 val; + + dtpam = (kdtpam_subobj_t *)this; + + if (dtpam->dt.dset && + kdtMapOutFixed(&(dtpam->dt), dtpam->dt.dclass, &val)) { + dtres->set = TRUE; + dtres->class = val; + return TRUE; + } else { + dtres->set = FALSE; + return FALSE; + } +} + + + +/* ************************************************************/ +/* decision tree accentuation (ACC) functions */ +/* ************************************************************/ + +picoos_uint8 picokdt_dtACCconstructInVec(const picokdt_DtACC this, + const picoos_uint8 pre2, + const picoos_uint8 pre1, + const picoos_uint8 src, + const picoos_uint8 fol1, + const picoos_uint8 fol2, + const picoos_uint16 hist1, + const picoos_uint16 hist2, + const picoos_uint16 nrwordspre, + const picoos_uint16 nrsyllspre, + const picoos_uint16 nrwordsfol, + const picoos_uint16 nrsyllsfol, + const picoos_uint16 footwordsfol, + const picoos_uint16 footsyllsfol) { + kdtacc_subobj_t *dtacc; + picoos_uint8 i; + picoos_uint16 inval = 0; + picoos_uint16 fallback = 0; + + dtacc = (kdtacc_subobj_t *)this; + PICODBG_DEBUG(("in: [%d,%d,%d,%d,%d|%d,%d|%d,%d,%d,%d|%d,%d]", + pre2, pre1, src, fol1, fol2, hist1, hist2, + nrwordspre, nrsyllspre, nrwordsfol, nrsyllsfol, + footwordsfol, footsyllsfol)); + dtacc->inveclen = 0; + + for (i = 0; i < PICOKDT_NRATT_ACC; i++) { + switch (i) { + case 0: inval = pre2; break; + case 1: inval = pre1; break; + case 2: inval = src; break; + case 3: inval = fol1; break; + case 4: inval = fol2; break; + case 5: inval = hist1; break; + case 6: inval = hist2; break; + case 7: inval = nrwordspre; break; + case 8: inval = nrsyllspre; break; + case 9: inval = nrwordsfol; break; + case 10: inval = nrsyllsfol; break; + case 11: inval = footwordsfol; break; + case 12: inval = footsyllsfol; break; + default: + PICODBG_ERROR(("size mismatch")); + return FALSE; + break; + } + + if (((i == 5) || (i == 6)) && (inval == PICOKDT_HISTORY_ZERO)) { + /* in input to this function the HISTORY_ZERO is used to + mark the no-value-available case. For sparsity reasons + this was not used in the training. For + no-value-available cases, instead, do reverse out + mapping of ACC0 to get tree domain for ACC0 */ + if (!kdtReverseMapOutFixed(&(dtacc->dt), PICODATA_ACC0, + &inval, &fallback)) { + if (fallback) { + inval = fallback; + } else { + PICODBG_ERROR(("problem doing reverse output mapping")); + return FALSE; + } + } + } + + /* do the imt mapping for all inval */ + if (!kdtMapInFixed(&(dtacc->dt), i, inval, + &(dtacc->invec[i]), &fallback)) { + if (fallback) { + dtacc->invec[i] = fallback; + } else { + PICODBG_ERROR(("problem doing input mapping")); + return FALSE; + } + } + } + + PICODBG_DEBUG(("out: [%d,%d,%d,%d,%d|%d,%d|%d,%d,%d,%d|%d,%d]", + dtacc->invec[0], dtacc->invec[1], dtacc->invec[2], + dtacc->invec[3], dtacc->invec[4], dtacc->invec[5], + dtacc->invec[6], dtacc->invec[7], dtacc->invec[8], + dtacc->invec[9], dtacc->invec[10], dtacc->invec[11], + dtacc->invec[12])); + dtacc->inveclen = PICOKDT_NRINPMT_ACC; + return TRUE; +} + + +picoos_uint8 picokdt_dtACCclassify(const picokdt_DtACC this, + picoos_uint16 *treeout) { + picoos_uint32 iByteNo; + picoos_int8 iBitNo; + picoos_int8 rv; + kdtacc_subobj_t *dtacc; + kdt_subobj_t *dt; + + dtacc = (kdtacc_subobj_t *)this; + dt = &(dtacc->dt); + iByteNo = 0; + iBitNo = 7; + while ((rv = kdtAskTree(dt, dtacc->invec, PICOKDT_NRATT_ACC, + &iByteNo, &iBitNo)) > 0) { + PICODBG_TRACE(("asking tree")); + } + PICODBG_TRACE(("done: %d", dt->dclass)); + if ((rv == 0) && dt->dset) { + *treeout = dt->dclass; + return TRUE; + } else { + return FALSE; + } +} + + +picoos_uint8 picokdt_dtACCdecomposeOutClass(const picokdt_DtACC this, + picokdt_classify_result_t *dtres) { + kdtacc_subobj_t *dtacc; + picoos_uint16 val; + + dtacc = (kdtacc_subobj_t *)this; + + if (dtacc->dt.dset && + kdtMapOutFixed(&(dtacc->dt), dtacc->dt.dclass, &val)) { + dtres->set = TRUE; + dtres->class = val; + return TRUE; + } else { + dtres->set = FALSE; + return FALSE; + } +} + +#ifdef __cplusplus +} +#endif + + +/* end */ diff --git a/pico/lib/picokdt.h b/pico/lib/picokdt.h new file mode 100644 index 0000000..3ef973c --- /dev/null +++ b/pico/lib/picokdt.h @@ -0,0 +1,465 @@ +/* + * 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 picokdt.h + * + * knowledge handling for decision trees + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#ifndef PICOKDT_H_ +#define PICOKDT_H_ + +#include "picoos.h" +#include "picoknow.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* ************************************************************/ +/* + Several specialized decision trees kb are provided by this + knowledge handling module: + + - Part of speech prediction decision tree: ...kdt_PosP + - Part of speech disambiguation decision tree: ...kdt_PosD + - Grapheme-to-phoneme decision tree: ...kdt_G2P + - Phrasing decision tree: ...kdt_PHR + - Accentuation decision tree: ...kdt_ACC + these 5 tree types may be unified in the future to a single type + + - Phono-acoustical model trees: ...kdt_PAM + (actually 11 trees, but all have the same characteristics and + are instances of the same class) +*/ +/* ************************************************************/ + + +/* ************************************************************/ +/* defines and functions to create specialized kb, */ +/* to be used by picorsrc only */ +/* ************************************************************/ + +typedef enum { + PICOKDT_KDTTYPE_POSP, + PICOKDT_KDTTYPE_POSD, + PICOKDT_KDTTYPE_G2P, + PICOKDT_KDTTYPE_PHR, + PICOKDT_KDTTYPE_ACC, + PICOKDT_KDTTYPE_PAM +} picokdt_kdttype_t; + +pico_status_t picokdt_specializeDtKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common, + const picokdt_kdttype_t type); + + +/* ************************************************************/ +/* decision tree types (opaque) and get Tree functions */ +/* ************************************************************/ + +/* decision tree types */ +typedef struct picokdt_dtposp * picokdt_DtPosP; +typedef struct picokdt_dtposd * picokdt_DtPosD; +typedef struct picokdt_dtg2p * picokdt_DtG2P; +typedef struct picokdt_dtphr * picokdt_DtPHR; +typedef struct picokdt_dtacc * picokdt_DtACC; +typedef struct picokdt_dtpam * picokdt_DtPAM; + +/* return kb decision tree for usage in PU */ +picokdt_DtPosP picokdt_getDtPosP(picoknow_KnowledgeBase this); +picokdt_DtPosD picokdt_getDtPosD(picoknow_KnowledgeBase this); +picokdt_DtG2P picokdt_getDtG2P (picoknow_KnowledgeBase this); +picokdt_DtPHR picokdt_getDtPHR (picoknow_KnowledgeBase this); +picokdt_DtACC picokdt_getDtACC (picoknow_KnowledgeBase this); +picokdt_DtPAM picokdt_getDtPAM (picoknow_KnowledgeBase this); + + +/* number of attributes (= input vector size) for each tree type */ +typedef enum { + PICOKDT_NRATT_POSP = 12, + PICOKDT_NRATT_POSD = 7, + PICOKDT_NRATT_G2P = 16, + PICOKDT_NRATT_PHR = 8, + PICOKDT_NRATT_ACC = 13, + PICOKDT_NRATT_PAM = 60 +} kdt_nratt_t; + + +/* ************************************************************/ +/* decision tree classification result type */ +/* ************************************************************/ + +typedef struct { + picoos_uint8 set; /* TRUE if class set, FALSE otherwise */ + picoos_uint16 class; +} picokdt_classify_result_t; + + +/* maximum number of output values the tree output is mapped to */ +#define PICOKDT_MAXSIZE_OUTVEC 8 + +typedef struct { + picoos_uint8 nr; /* 0 if no class set, nr of values set otherwise */ + picoos_uint16 classvec[PICOKDT_MAXSIZE_OUTVEC]; +} picokdt_classify_vecresult_t; + + +/* ************************************************************/ +/* decision tree functions */ +/* ************************************************************/ + +/* constructInVec: + for every tree type there is a constructInVec function to construct + the size-optimized input vector for the tree using the input map + tables that are part of the decistion tree knowledge base. The + constructed input vector is stored in the tree object (this->invec + and this->inveclen) and will be used in the following call to the + classify function. + + classify: + for every tree type there is a classify function to apply the + decision tree to the previously constructed input vector. The + size-optimized, encoded output is stored in the tree object + (this->outval) and will be used in the following call to the + decompose function. Where needed (hitory attribute) the direct tree + output is returned by the classify function in a variable. + + decomposeOutClass: + for every tree type there is a decompose function to decompose the + size-optimized, encoded tree output and map it to the outside the + tree usable class value. +*/ + + +/* ************************************************************/ +/* decision tree defines */ +/* ************************************************************/ + +/* to construct the input vectors several hard-coded values are used + to handle attributes that, at the given position, are outside the + context. */ + +/* graph attributes: values to be used if the graph attribute is + outside the grapheme string (ie. word) */ +#define PICOKDT_OUTSIDEGRAPH_DEFCH (picoos_uint8)'\x30' /* ascii "0" */ +#define PICOKDT_OUTSIDEGRAPH_DEFSTR (picoos_uint8 *)"\x30" /* ascii "0" */ +#define PICOKDT_OUTSIDEGRAPH_DEFLEN 1 + +/* graph attributes (special case for g2p): values to be used if the + graph attribute is directly outside the grapheme string (ie. at the + word boundary word). Use PICOKDT_OUTSIDEGRAPH_DEF* if further + outside. */ +#define PICOKDT_OUTSIDEGRAPH_EOW_DEFCH (picoos_uint8)'\x31' /* ascii "1" */ +#define PICOKDT_OUTSIDEGRAPH_EOW_DEFSTR (picoos_uint8 *)"\x31" /* ascii "1" */ +#define PICOKDT_OUTSIDEGRAPH_EOW_DEFLEN 1 + +/* byte and word type attributes: value to be used if a byte or word + attribute is outside the context, e.g. for POS */ +#define PICOKDT_EPSILON 7 + +/* byte and word type attributes: for attribute with history info a + 'zero' value is needed when starting the sequence of predictions. + Use the following value to initialize history. Note that the direct + tree outputs (not mapped with output map table) of previous + predictions need to be used when constructing the input vector for + a following prediction. This direct tree output will then be mapped + together with the rest of the input vector by the input map + table. */ +#define PICOKDT_HISTORY_ZERO 30000 + + +/* ************************************************************/ +/* decision tree POS prediction (PosP) functions */ +/* ************************************************************/ + +/* construct a POS prediction input vector + tree input vector: 0-3 prefix UTF8 graphemes + 4-9 suffex UTF8 graphemes + 10 special grapheme existence flag (TRUE/FALSE) + 11 number of graphemes + graph: the grapheme string of the word for wich POS will be predicted + graphlen: length of graph in number of bytes + specgraphflag: existence of a special grapheme boolean + returns: TRUE if okay, FALSE otherwise + note: use PICOKDT_OUTSIDEGRAPH* for att values outside context +*/ +picoos_uint8 picokdt_dtPosPconstructInVec(const picokdt_DtPosP this, + const picoos_uint8 *graph, + const picoos_uint16 graphlen, + const picoos_uint8 specgraphflag); + + +/* classify a previously constructed input vector using tree 'this' + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtPosPclassify(const picokdt_DtPosP this); + +/* decompose the tree output and return the class in dtres + dtres: POS or POSgroup ID classification result + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtPosPdecomposeOutClass(const picokdt_DtPosP this, + picokdt_classify_result_t *dtres); + + +/* ************************************************************/ +/* decision tree POS disambiguation (PosD) functions */ +/* ************************************************************/ + +/* construct a POS disambiguation input vector (run in left-to-right mode) + tree input vector: 0-2 POS or POSgroup for each of the three previous words + 3 POSgroup for current word + 4-6 POS or POSgroup (can be history) for each of + the three following words + pre3 - pre1: POSgroup or POS for the previous three words + src: POSgroup of current word (if unique POS no posdisa possible) + fol1 - fol3: POS or history for the following three words (the more + complicated the better... :-( NEEDS TO BE uint16 + ishist1-ishist3: flag to indicate if fol1-3 are predicted tree + output values (history) or the HISTORY_ZERO (TRUE) + or an already unambiguous POS (FALSE) + returns: TRUE if okay, FALSE otherwise + note: use PICOKDT_EPSILON for att values outside context, + if POS in fol* unique use this POS instead of real + history, use reverse output mapping in these cases +*/ +picoos_uint8 picokdt_dtPosDconstructInVec(const picokdt_DtPosD this, + const picoos_uint16 * input); + + +/* classify a previously constructed input vector using tree 'this' + treeout: direct tree output value + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtPosDclassify(const picokdt_DtPosD this, + picoos_uint16 *treeout); + +/* decompose the tree output and return the class in dtres + dtres: POS classification result + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtPosDdecomposeOutClass(const picokdt_DtPosD this, + picokdt_classify_result_t *dtres); + +/* convert (unique) POS index into corresponding tree output index */ +picoos_uint8 picokdt_dtPosDreverseMapOutFixed(const picokdt_DtPosD this, + const picoos_uint16 inval, + picoos_uint16 *outval, + picoos_uint16 *outfallbackval); + +/* ************************************************************/ +/* decision tree grapheme-to-phoneme (G2P) functions */ +/* ************************************************************/ + +/* construct a G2P input vector (run in right-to-left mode) + tree input vector: 0-8 the 4 previous, current, and 4 following graphemes + 9 POS + 10-11 vowel count and vowel ID + 12 primary stress flag (TRUE/FALSE) + 13-15 the three following phones predicted + graph: the grapheme string used to determine invec[0:8] + graphlen: length of graph in number of bytes + count: the grapheme number for which invec will be constructed [0..] + pos: the part of speech of the word + nrvow number of vowel-like graphemes in graph if vowel, + set to 0 otherwise + ordvow order of 'count' vowel in graph if vowel, + set to 0 otherwise + primstressflag: flag indicating if primary stress was already predicted + phonech1-3: the three following phon chunks predicted (right-to-left) + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtG2PconstructInVec(const picokdt_DtG2P this, + const picoos_uint8 *graph, + const picoos_uint16 graphlen, + const picoos_uint8 count, + const picoos_uint8 pos, + const picoos_uint8 nrvow, + const picoos_uint8 ordvow, + picoos_uint8 *primstressflag, + const picoos_uint16 phonech1, + const picoos_uint16 phonech2, + const picoos_uint16 phonech3); + +/* classify a previously constructed input vector using tree 'this' + treeout: direct tree output value + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtG2Pclassify(const picokdt_DtG2P this, + picoos_uint16 *treeout); + +/* decompose the tree output and return the class vector in dtvres + dtvres: phones vector classification result + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtG2PdecomposeOutClass(const picokdt_DtG2P this, + picokdt_classify_vecresult_t *dtvres); + + +/* ************************************************************/ +/* decision tree phrasing (PHR) functions */ +/* ************************************************************/ + +/* construct a PHR input vector (run in right-to-left mode) + tree input vector: 0-1 POS for each of the two previous words + 2 POS for current word + 3-4 POS for each of the two following words + 5 nr words left + 6 nr words right + 7 nr syllables right + pre2 - pre1: POS for the previous two words + src: POS of current word + fol1 - fol2: POS for the following two words + nrwordspre: number of words left (previous) of current word + nrwordsfol: number of words right (following) of current word, + incl. current word, up to next BOUND (also + considering previously predicted PHR2/3) + nrsyllsfol: number of syllables right (following) of current word, + incl. syllables of current word, up to next BOUND + (also considering previously predicted PHR2/3) + returns: TRUE if okay, FALSE otherwise + note: use PICOKDT_EPSILON for att values outside context +*/ +picoos_uint8 picokdt_dtPHRconstructInVec(const picokdt_DtPHR this, + const picoos_uint8 pre2, + const picoos_uint8 pre1, + const picoos_uint8 src, + const picoos_uint8 fol1, + const picoos_uint8 fol2, + const picoos_uint16 nrwordspre, + const picoos_uint16 nrwordsfol, + const picoos_uint16 nrsyllsfol); + +/* classify a previously constructed input vector using tree 'this' + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtPHRclassify(const picokdt_DtPHR this); + +/* decompose the tree output and return the class vector in dtres + dtres: phrasing classification result + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtPHRdecomposeOutClass(const picokdt_DtPHR this, + picokdt_classify_result_t *dtres); + + +/* ************************************************************/ +/* decision tree accentuation (ACC) functions */ +/* ************************************************************/ + +/* construct an ACC input vector (run in right-to-left mode) + tree input vector: 0-1 POS for each of the two previous words + 2 POS for current word + 3-4 POS for each of the two following words + 5-6 history values (already predicted following) + 7 nr words left (previous) to any bound + 8 nr syllables left to any bound + 9 nr words right (following) to any bound + 10 nr syllables right to any bound + 11 nr words right to predicted "1" prominence (foot) + 12 nr syllables right to predicted "1" prominence (foot) + pre2 - pre1: POS for the previous two words + src: POS of current word + fol1 - fol2: POS for the following two words + hist1 - hist2: previously predicted ACC values + nrwordspre: number of words left (previous) of current word + nrsyllspre: number of syllables left (previous) of current word, + incl. initial non-prim stress syllables of current word + nrwordsfol: number of words right (following) of current word, + incl. current word, up to next BOUND (any strength != 0) + nrsyllsfol: number of syllables right (following) of current word, + incl. syllables of current word starting with prim. stress + syllable + footwordsfol: nr of words to the following prominence '1' + footsyllspre: nr of syllables to the previous prominence '1' + returns: TRUE if okay, FALSE otherwise + note: use PICOKDT_EPSILON for att 0-4 values outside context +*/ +picoos_uint8 picokdt_dtACCconstructInVec(const picokdt_DtACC this, + const picoos_uint8 pre2, + const picoos_uint8 pre1, + const picoos_uint8 src, + const picoos_uint8 fol1, + const picoos_uint8 fol2, + const picoos_uint16 hist1, + const picoos_uint16 hist2, + const picoos_uint16 nrwordspre, + const picoos_uint16 nrsyllspre, + const picoos_uint16 nrwordsfol, + const picoos_uint16 nrsyllsfol, + const picoos_uint16 footwordsfol, + const picoos_uint16 footsyllsfol); + +/* classify a previously constructed input vector using tree 'this' + treeout: direct tree output value + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtACCclassify(const picokdt_DtACC this, + picoos_uint16 *treeout); + +/* decompose the tree output and return the class vector in dtres + dtres: phrasing classification result + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtACCdecomposeOutClass(const picokdt_DtACC this, + picokdt_classify_result_t *dtres); + + +/* ************************************************************/ +/* decision tree phono-acoustical model (PAM) functions */ +/* ************************************************************/ + +/* construct a Pam input vector and store the tree-specific encoded + input vector in the tree object. + vec: tree input vector, 60 single-byte-sized attributes + veclen: length of vec in number of bytes + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtPAMconstructInVec(const picokdt_DtPAM this, + const picoos_uint8 *vec, + const picoos_uint8 veclen); + +/* classify a previously constructed input vector using tree 'this' + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtPAMclassify(const picokdt_DtPAM this); + +/* decompose the tree output and return the class in dtres + dtres: phones vector classification result + returns: TRUE if okay, FALSE otherwise +*/ +picoos_uint8 picokdt_dtPAMdecomposeOutClass(const picokdt_DtPAM this, + picokdt_classify_result_t *dtres); + +#ifdef __cplusplus +} +#endif + + + +#endif /*PICOKDT_H_*/ diff --git a/pico/lib/picokfst.c b/pico/lib/picokfst.c new file mode 100644 index 0000000..560709c --- /dev/null +++ b/pico/lib/picokfst.c @@ -0,0 +1,438 @@ +/* + * 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 picokfst.c + * + * FST knowledge loading and access + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +#include "picoos.h" +#include "picodbg.h" +#include "picoknow.h" +#include "picokfst.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +#define FileHdrSize 4 /* size of FST file header */ + + + +/* ************************************************************/ +/* function to create specialized kb, */ +/* to be used by picorsrc only */ +/* ************************************************************/ + +/** object : FSTKnowledgeBase + * shortcut : kfst + * derived from : picoknow_KnowledgeBase + */ + +typedef struct kfst_subobj * kfst_SubObj; + +typedef struct kfst_subobj{ + picoos_uint8 * fstStream; /* the byte stream base address */ + picoos_int32 hdrLen; /* length of file header */ + picoos_int32 transductionMode; /* transduction mode to be used for FST */ + picoos_int32 nrClasses; /* nr of pair/transition classes in FST; class is in [1..nrClasses] */ + picoos_int32 nrStates; /* nr of states in FST; state is in [1..nrState] */ + picoos_int32 termClass; /* pair class of terminator symbol pair; probably obsolete */ + picoos_int32 alphaHashTabSize; /* size of pair alphabet hash table */ + picoos_int32 alphaHashTabPos; /* absolute address of the start of the pair alphabet */ + picoos_int32 transTabEntrySize; /* size in bytes of each transition table entry */ + picoos_int32 transTabPos; /* absolute address of the start of the transition table */ + picoos_int32 inEpsStateTabPos; /* absolute address of the start of the input epsilon transition table */ + picoos_int32 accStateTabPos; /* absolute address of the table of accepting states */ +} kfst_subobj_t; + + + +/* ************************************************************/ +/* primitives for reading from byte stream */ +/* ************************************************************/ + +/* Converts 'nrBytes' bytes starting at position '*pos' in byte stream 'stream' into unsigned number 'num'. + '*pos' is modified to the position right after the number */ +static void FixedBytesToUnsignedNum (picoos_uint8 * stream, picoos_uint8 nrBytes, picoos_uint32 * pos, picoos_uint32 * num) +{ + picoos_int32 i; + + (*num) = 0; + for (i = 0; i < nrBytes; i++) { + (*num) = ((*num) << 8) + (picoos_uint32)stream[*pos]; + (*pos)++; + } +} + + +/* Converts 'nrBytes' bytes starting at position '*pos' in byte stream 'stream' into signed number 'num'. + '*pos' is modified to the position right after the number */ +static void FixedBytesToSignedNum (picoos_uint8 * stream, picoos_uint8 nrBytes, picoos_uint32 * pos, picoos_int32 * num) +{ + picoos_int32 i; + picoos_uint32 val; + + val = 0; + for (i = 0; i < nrBytes; i++) { + val = (val << 8) + (picoos_uint32)stream[*pos]; + (*pos)++; + } + if (val % 2 == 1) { + /* negative number */ + (*num) = -((picoos_int32)((val - 1) / 2)) - 1; + } else { + /* positive number */ + (*num) = val / 2; + } +} + + +/* Converts varying-sized sequence of bytes starting at position '*pos' in byte stream 'stream' + into (signed) number 'num'. '*pos' is modified to the position right after the number. */ +static void BytesToNum (picoos_uint8 * stream, picoos_uint32 * pos, picoos_int32 * num) +{ + picoos_uint32 val; + picoos_uint32 b; + + val = 0; + b = (picoos_uint32)stream[*pos]; + (*pos)++; + while (b < 128) { + val = (val << 7) + b; + b = (picoos_uint32)stream[*pos]; + (*pos)++; + } + val = (val << 7) + (b - 128); + if (val % 2 == 1) { + /* negative number */ + (*num) = -((picoos_int32)((val - 1) / 2)) - 1; + } else { + /* positive number */ + (*num) = val / 2; + } +} + + +/* ************************************************************/ +/* setting up FST from byte stream */ +/* ************************************************************/ + +static pico_status_t kfstInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) +{ + picoos_uint32 curpos; + picoos_int32 offs; + kfst_subobj_t * kfst; + + PICODBG_DEBUG(("kfstInitialize -- start\n")); + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, NULL, + NULL); + } + kfst = (kfst_subobj_t *) this->subObj; + + /* +CT+ */ + kfst->fstStream = this->base; + PICODBG_TRACE(("base: %d\n",this->base)); + kfst->hdrLen = FileHdrSize; + curpos = kfst->hdrLen; + BytesToNum(kfst->fstStream,& curpos,& kfst->transductionMode); + BytesToNum(kfst->fstStream,& curpos,& kfst->nrClasses); + BytesToNum(kfst->fstStream,& curpos,& kfst->nrStates); + BytesToNum(kfst->fstStream,& curpos,& kfst->termClass); + BytesToNum(kfst->fstStream,& curpos,& kfst->alphaHashTabSize); + BytesToNum(kfst->fstStream,& curpos,& offs); + kfst->alphaHashTabPos = kfst->hdrLen + offs; + BytesToNum(kfst->fstStream,& curpos,& kfst->transTabEntrySize); + BytesToNum(kfst->fstStream,& curpos,& offs); + kfst->transTabPos = kfst->hdrLen + offs; + BytesToNum(kfst->fstStream,& curpos,& offs); + kfst->inEpsStateTabPos = kfst->hdrLen + offs; + BytesToNum(kfst->fstStream,& curpos,& offs); + kfst->accStateTabPos = kfst->hdrLen + offs; + /* -CT- */ + + return PICO_OK; +} + + +static pico_status_t kfstSubObjDeallocate(register picoknow_KnowledgeBase this, + picoos_MemoryManager mm) +{ + if (NULL != this) { + picoos_deallocate(mm, (void *) &this->subObj); + } + return PICO_OK; +} + + +/* calculates a small number of data (e.g. addresses) from kb for fast access. + * This data is encapsulated in a picokfst_FST that can later be retrieved + * with picokfst_getFST. */ +pico_status_t picokfst_specializeFSTKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common) +{ + pico_status_t status; + + if (NULL == this) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, NULL, NULL); + } + if (0 < this->size) { + /* not a dummy kb */ + this->subDeallocate = kfstSubObjDeallocate; + + this->subObj = picoos_allocate(common->mm, sizeof(kfst_subobj_t)); + + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); + } + status = kfstInitialize(this, common); + if (PICO_OK != status) { + picoos_deallocate(common->mm,(void **)&this->subObj); + } + } + return PICO_OK; +} + + +/* ************************************************************/ +/* FST type and getFST function */ +/* ************************************************************/ + + + +/* return kb FST for usage in PU */ +picokfst_FST picokfst_getFST(picoknow_KnowledgeBase this) +{ + if (NULL == this) { + return NULL; + } else { + return (picokfst_FST) this->subObj; + } +} + + + +/* ************************************************************/ +/* FST access methods */ +/* ************************************************************/ + + +/* see description in header file */ +extern picoos_uint8 picokfst_kfstGetTransductionMode(picokfst_FST this) +{ + kfst_SubObj fst = (kfst_SubObj) this; + if (fst != NULL) { + return fst->transductionMode; + } else { + return 0; + } +} + + +/* see description in header file */ +extern void picokfst_kfstGetFSTSizes (picokfst_FST this, picoos_int32 *nrStates, picoos_int32 *nrClasses) +{ + kfst_SubObj fst = (kfst_SubObj) this; + if (fst != NULL) { + *nrStates = fst->nrStates; + *nrClasses = fst->nrClasses; + } else { + *nrStates = 0; + *nrClasses = 0; + } +} + +/* see description in header file */ +extern void picokfst_kfstStartPairSearch (picokfst_FST this, picokfst_symid_t inSym, + picoos_bool * inSymFound, picoos_int32 * searchState) +{ + picoos_uint32 pos; + picoos_int32 offs; + picoos_int32 h; + picoos_int32 inSymCellPos; + picoos_int32 inSymX; + picoos_int32 nextSameHashInSymOffs; + + kfst_SubObj fst = (kfst_SubObj) this; + (*searchState) = -1; + (*inSymFound) = 0; + h = inSym % fst->alphaHashTabSize; + pos = fst->alphaHashTabPos + (h * 4); + FixedBytesToSignedNum(fst->fstStream,4,& pos,& offs); + if (offs > 0) { + inSymCellPos = fst->alphaHashTabPos + offs; + pos = inSymCellPos; + BytesToNum(fst->fstStream,& pos,& inSymX); + BytesToNum(fst->fstStream,& pos,& nextSameHashInSymOffs); + while ((inSymX != inSym) && (nextSameHashInSymOffs > 0)) { + inSymCellPos = inSymCellPos + nextSameHashInSymOffs; + pos = inSymCellPos; + BytesToNum(fst->fstStream,& pos,& inSymX); + BytesToNum(fst->fstStream,& pos,& nextSameHashInSymOffs); + } + if (inSymX == inSym) { + /* input symbol found; state is set to position after symbol cell */ + (*searchState) = pos; + (*inSymFound) = 1; + } + } +} + + +/* see description in header file */ +extern void picokfst_kfstGetNextPair (picokfst_FST this, picoos_int32 * searchState, + picoos_bool * pairFound, + picokfst_symid_t * outSym, picokfst_class_t * pairClass) +{ + picoos_uint32 pos; + picoos_int32 val; + + kfst_SubObj fst = (kfst_SubObj) this; + if ((*searchState) < 0) { + (*pairFound) = 0; + (*outSym) = PICOKFST_SYMID_ILLEG; + (*pairClass) = -1; + } else { + pos = (*searchState); + BytesToNum(fst->fstStream,& pos,& val); + *outSym = (picokfst_symid_t)val; + if ((*outSym) != PICOKFST_SYMID_ILLEG) { + BytesToNum(fst->fstStream,& pos,& val); + *pairClass = (picokfst_class_t)val; + (*pairFound) = 1; + (*searchState) = pos; + } else { + (*pairFound) = 0; + (*outSym) = PICOKFST_SYMID_ILLEG; + (*pairClass) = -1; + (*searchState) = -1; + } + } +} + + + +/* see description in header file */ +extern void picokfst_kfstGetTrans (picokfst_FST this, picokfst_state_t startState, picokfst_class_t transClass, + picokfst_state_t * endState) +{ + + picoos_uint32 pos; + picoos_int32 index; + picoos_uint32 endStateX; + + kfst_SubObj fst = (kfst_SubObj) this; + if ((startState < 1) || (startState > fst->nrStates) || (transClass < 1) || (transClass > fst->nrClasses)) { + (*endState) = 0; + } else { + index = (startState - 1) * fst->nrClasses + transClass - 1; + pos = fst->transTabPos + (index * fst->transTabEntrySize); + FixedBytesToUnsignedNum(fst->fstStream,fst->transTabEntrySize,& pos,& endStateX); + (*endState) = endStateX; + } +} + + +/* see description in header file */ +extern void picokfst_kfstStartInEpsTransSearch (picokfst_FST this, picokfst_state_t startState, + picoos_bool * inEpsTransFound, picoos_int32 * searchState) +{ + + picoos_int32 offs; + picoos_uint32 pos; + + kfst_SubObj fst = (kfst_SubObj) this; + (*searchState) = -1; + (*inEpsTransFound) = 0; + if ((startState > 0) && (startState <= fst->nrStates)) { + pos = fst->inEpsStateTabPos + (startState - 1) * 4; + FixedBytesToSignedNum(fst->fstStream,4,& pos,& offs); + if (offs > 0) { + (*searchState) = fst->inEpsStateTabPos + offs; + (*inEpsTransFound) = 1; + } + } +} + + + +/* see description in header file */ +extern void picokfst_kfstGetNextInEpsTrans (picokfst_FST this, picoos_int32 * searchState, + picoos_bool * inEpsTransFound, + picokfst_symid_t * outSym, picokfst_state_t * endState) +{ + picoos_uint32 pos; + picoos_int32 val; + + kfst_SubObj fst = (kfst_SubObj) this; + if ((*searchState) < 0) { + (*inEpsTransFound) = 0; + (*outSym) = PICOKFST_SYMID_ILLEG; + (*endState) = 0; + } else { + pos = (*searchState); + BytesToNum(fst->fstStream,& pos,& val); + *outSym = (picokfst_symid_t)val; + if ((*outSym) != PICOKFST_SYMID_ILLEG) { + BytesToNum(fst->fstStream,& pos,& val); + *endState = (picokfst_state_t)val; + (*inEpsTransFound) = 1; + (*searchState) = pos; + } else { + (*inEpsTransFound) = 0; + (*outSym) = PICOKFST_SYMID_ILLEG; + (*endState) = 0; + (*searchState) = -1; + } + } +} + + +/* see description in header file */ +extern picoos_bool picokfst_kfstIsAcceptingState (picokfst_FST this, picokfst_state_t state) +{ + + picoos_uint32 pos; + picoos_uint32 val; + + kfst_SubObj fst = (kfst_SubObj) this; + if ((state > 0) && (state <= fst->nrStates)) { + pos = fst->accStateTabPos + (state - 1); + FixedBytesToUnsignedNum(fst->fstStream,1,& pos,& val); + return (val == 1); + } else { + return 0; + } +} + +#ifdef __cplusplus +} +#endif + +/* End picofst.c */ diff --git a/pico/lib/picokfst.h b/pico/lib/picokfst.h new file mode 100644 index 0000000..b391013 --- /dev/null +++ b/pico/lib/picokfst.h @@ -0,0 +1,169 @@ +/* + * 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 picokfst.h + * + * FST knowledge loading and access + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +#ifndef PICOKFST_H_ +#define PICOKFST_H_ + +#include "picodefs.h" +#include "picodbg.h" +#include "picoos.h" +#include "picoknow.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +typedef picoos_int16 picokfst_symid_t; /* type of symbol identifiers */ +typedef picoos_int16 picokfst_class_t; /* type of symbol pair classes */ +typedef picoos_int16 picokfst_state_t; /* type of states */ + +#define PICOKFST_SYMID_EPS (picokfst_symid_t) 0 /* epsilon symbol id */ +#define PICOKFST_SYMID_ILLEG (picokfst_symid_t) -1 /* illegal symbol id */ + +/** + * @addtogroup picokfst + * + * Mapping of values to FST symbol id (relevant for compiling the FST) \n + * Value FST symbol id \n + * -------------------------------------- \n + * phoneme_id -> phoneme_id + 256 * PICOKFST_PLANE_PHONEMES \n + * accentlevel_id -> accentlevel_id + 256 * PICOKFST_PLANE_ACCENTS \n + * POS_id -> POS_id + 256 * PICOKFST_PLANE_POS \n + * pb_strength_id -> pb_strength_id + 256 * PICOKFST_PLANE_PB_STRENGTHS \n + * phon_term_id -> phon_term_id + 256 * PICOKFST_PLANE_INTERN \n +*/ +enum picokfst_symbol_plane { + PICOKFST_PLANE_PHONEMES = 0, /* phoneme plane */ + PICOKFST_PLANE_ASCII = 1, /* "ascii" plane (values > 127 may be used internally) */ + PICOKFST_PLANE_XSAMPA = 2, /* x-sampa primitives plane (pico-specific table) */ + PICOKFST_PLANE_ACCENTS = 4, /* accent plane */ + PICOKFST_PLANE_POS = 5, /* part of speech plane */ + PICOKFST_PLANE_PB_STRENGTHS = 6, /* phrase boundary strength plane */ + PICOKFST_PLANE_INTERN = 7 /* internal plane, e.g. phonStartId, phonTermId */ +}; + +/* to be used as bit set, e.g. + * picoos_uint8 transductionMode = PICOKFST_TRANSMODE_NEWSYMS | PICOKFST_TRANSMODE_POSUSED; + */ +enum picofst_transduction_mode { + PICOKFST_TRANSMODE_NEWSYMS = 1, /* e.g. {#WB},{#PB-S},{#PB-W},{#ACC0},{#ACC1},{#ACC2},{#ACC3}, */ + PICOKFST_TRANSMODE_POSUSED = 2 /* FST contains Part Of Speech symbols */ + +}; + + +/* ************************************************************/ +/* function to create specialized kb, */ +/* to be used by knowledge layer (picorsrc) only */ +/* ************************************************************/ + +/* calculates a small number of data (e.g. addresses) from kb for fast access. + * This data is encapsulated in a picokfst_FST that can later be retrieved + * with picokfst_getFST. */ +pico_status_t picokfst_specializeFSTKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common); + + +/* ************************************************************/ +/* FST type and getFST function */ +/* ************************************************************/ + +/* FST type */ +typedef struct picokfst_fst * picokfst_FST; + +/* return kb FST for usage in PU */ +picokfst_FST picokfst_getFST(picoknow_KnowledgeBase this); + + +/* ************************************************************/ +/* FST access methods */ +/* ************************************************************/ + +/* returns transduction mode specified with rule sources; + result to be interpreted as set of picofst_transduction_mode */ +picoos_uint8 picokfst_kfstGetTransductionMode(picokfst_FST this); + +/* returns number of states and number of pair classes in FST; + legal states are 1..nrStates, legal classes are 1..nrClasses */ +void picokfst_kfstGetFSTSizes (picokfst_FST this, picoos_int32 *nrStates, picoos_int32 *nrClasses); + +/* starts search for all pairs with input symbol 'inSym'; '*inSymFound' returns whether + such pairs exist at all; '*searchState' returns a search state to be used in + subsequent calls to function 'picokfst_kfstGetNextPair', which must be used + to get the symbol pairs */ +void picokfst_kfstStartPairSearch (picokfst_FST this, picokfst_symid_t inSym, + picoos_bool * inSymFound, picoos_int32 * searchState); + +/* gets next pair for input symbol specified with preceding call to 'picokfst_kfstStartPairSearch'; + '*searchState' maintains the search state, 'pairFound' returns whether any more pair was found, + '*outSym' returns the output symbol of the found pair, and '*pairClass' returns the + transition class of the found symbol pair */ +void picokfst_kfstGetNextPair (picokfst_FST this, picoos_int32 * searchState, + picoos_bool * pairFound, + picokfst_symid_t * outSym, picokfst_class_t * pairClass); + +/* attempts to do FST transition from state 'startState' with pair class 'transClass'; + if such a transition exists, 'endState' returns the end state of the transition (> 0), + otherwise 'endState' returns <= 0 */ +void picokfst_kfstGetTrans (picokfst_FST this, picokfst_state_t startState, picokfst_class_t transClass, + picokfst_state_t * endState); + +/* starts search for all pairs with input epsilon symbol and all correponding + FST transitions starting in state 'startState'; to be used for fast + computation of epsilon closures; + '*inEpsTransFound' returns whether any such transition was found at all; + if so, '*searchState' returns a search state to be used in subsequent calls + to 'picokfst_kfstGetNextInEpsTrans' */ +void picokfst_kfstStartInEpsTransSearch (picokfst_FST this, picokfst_state_t startState, + picoos_bool * inEpsTransFound, picoos_int32 * searchState); + +/* gets next FST transition with a pair with empty input symbol starting from a state + previoulsy specified in 'picokfst_kfstStartInEpsTransSearch'; + '*searchState' maintains the search state, '*inEpsTransFound' returns + whether a new transition with input epsilon was found, '*outSym 'returns + the output symbol of the found pair, and '*endState' returns the end state + of the found transition with that pair */ +void picokfst_kfstGetNextInEpsTrans (picokfst_FST this, picoos_int32 * searchState, + picoos_bool * inEpsTransFound, + picokfst_symid_t * outSym, picokfst_state_t * endState); + +/* returns whether 'state' is an accepting state of FST; originally, only + state 1 was an accepting state; however, in order to remove the need to + always do a last transition with a termination symbol pair, this function + defines a state as an accepting state if there is transition to state 1 + with the terminator symbol pair */ +picoos_bool picokfst_kfstIsAcceptingState (picokfst_FST this, picokfst_state_t state); + +#ifdef __cplusplus +} +#endif + + +#endif /*PICOKFST_H_*/ diff --git a/pico/lib/picoklex.c b/pico/lib/picoklex.c new file mode 100644 index 0000000..7ff0a33 --- /dev/null +++ b/pico/lib/picoklex.c @@ -0,0 +1,572 @@ +/* + * 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 picoklex.c + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +#include "picoos.h" +#include "picodbg.h" +#include "picodata.h" +#include "picoknow.h" +#include "picoklex.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/* ************************************************************/ +/* lexicon */ +/* ************************************************************/ + +/** + * @addtogroup picolex + * + overview: + - lex consists of optional searchindex and a non-empty list of lexblocks + - lexblocks are fixed size, at the start of a block there is also the + start of an entry + - using the searchindex a unambiguous lexblock can be determined which + contains the entry (or there is no entry) + - one lex entry has POS GRAPH PHON, all mandatory, but + - PHON can be empty string -> no pronunciation in the resulting TTS output + - PHON can be :G2P -> use G2P later to add pronunciation + - (POS,GRAPH) is a uniq key (only one entry allowed) + - (GRAPH) is almost a uniq key (2-4 entries with the same GRAPH, and + differing POS and differing PHON possible) + - for one graph we can have two or three solutions from the lex + which all need to be passed on the the next PU + - in this case GRAPH, POS, and PHON all must be available in lex + + sizing: + - 3 bytes entry index -> 16MB addressable + - 2 bytes searchindex nr -> 64K blocks possible + - 5 bytes per searchindex entry + - 3 bytes for graph-prefix + - 2 bytes blockadr in searchindex -> 64K blocks possible + - lexblock size 512B: + - 32M possible + - with ~20 bytes per entry + -> max. average of ~26 entries to be searched per lookup + - overhead of ~10 bytes per block to sync with + block boundaries + - examples: + - 500KB lex -> 1000 blocks, + 1000 entries in searchindex, ~25.6K lex-entries, + - ~5KB searchindex + ~10KB overhead for block sync + - 100KB lex -> 200 blocks, + 200 entries in searchindex, ~5.1K lex-entries, + - ~1KB searchindex + ~2KB overhead for block sync + + pil-file: lexicon knowledge base in binary form + + lex-kb = content + + content = searchindex {lexblock}1:NRBLOCKS2 + + lexblock = {lexentry}1: (lexblock size is fixed 512Bytes) + + searchindex = NRBLOCKS2 {GRAPH1 GRAPH1 GRAPH1 LEXBLOCKIND2}=NRBLOCKS2 + + lexentry = LENGRAPH1 {GRAPH1}=LENGRAPH1-1 + LENPOSPHON1 POS1 {PHON1}=LENPOSPHON1-2 + + - special cases: + - PHON is empty string (no pronunciation in the resulting TTS output): + lexentry = LENGRAPH1 {GRAPH1}=LENGRAPH1-1 2 POS1 + - PHON can be :G2P -> use G2P later to add pronunciation: + lexentry = LENGRAPH1 {GRAPH1}=LENGRAPH1-1 3 POS1 + - multi-byte values always little endian +*/ + + +/* ************************************************************/ +/* lexicon data defines */ +/* may not be changed with current implementation */ +/* ************************************************************/ + +/* nr bytes of nrblocks info */ +#define PICOKLEX_LEX_NRBLOCKS_SIZE 2 + +/* search index entry: - nr graphs + - nr bytes of block index + - nr bytes per entry, NRGRAPHS*INDSIZE */ +#define PICOKLEX_LEX_SIE_NRGRAPHS 3 +#define PICOKLEX_LEX_SIE_INDSIZE 2 +#define PICOKLEX_LEX_SIE_SIZE 5 + +/* nr of bytes per lexblock */ +#define PICOKLEX_LEXBLOCK_SIZE 512 + + +/* reserved values in klex to indicate :G2P needed for a lexentry */ +#define PICOKLEX_NEEDS_G2P 5 + + +/* ************************************************************/ +/* lexicon type and loading */ +/* ************************************************************/ + +/** object : LexKnowledgeBase + * shortcut : klex + * derived from : picoknow_KnowledgeBase + */ + +typedef struct klex_subobj *klex_SubObj; + +typedef struct klex_subobj +{ + picoos_uint16 nrblocks; /* nr lexblocks = nr eles in searchind */ + picoos_uint8 *searchind; + picoos_uint8 *lexblocks; +} klex_subobj_t; + + +static pico_status_t klexInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) +{ + picoos_uint32 curpos = 0; + klex_subobj_t *klex; + + PICODBG_DEBUG(("start")); + + /* check whether (this->size != 0) done before calling this function */ + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + klex = (klex_subobj_t *) this->subObj; + + if (PICO_OK == picoos_read_mem_pi_uint16(this->base, &curpos, + &(klex->nrblocks))) { + if (klex->nrblocks > 0) { + PICODBG_DEBUG(("nr blocks: %i, curpos: %i", klex->nrblocks,curpos)); + klex->searchind = this->base + curpos; + } else { + klex->searchind = NULL; + } + klex->lexblocks = this->base + PICOKLEX_LEX_NRBLOCKS_SIZE + + (klex->nrblocks * (PICOKLEX_LEX_SIE_SIZE)); + return PICO_OK; + } else { + return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, + NULL, NULL); + } +} + + +static pico_status_t klexSubObjDeallocate(register picoknow_KnowledgeBase this, + picoos_MemoryManager mm) +{ + if (NULL != this) { + picoos_deallocate(mm, (void *) &this->subObj); + } + return PICO_OK; +} + + +/* we don't offer a specialized constructor for a LexKnowledgeBase but + * instead a "specializer" of an allready existing generic + * picoknow_KnowledgeBase */ + +pico_status_t picoklex_specializeLexKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common) +{ + if (NULL == this) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + if (this->size > 0) { + this->subDeallocate = klexSubObjDeallocate; + this->subObj = picoos_allocate(common->mm, sizeof(klex_subobj_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + return klexInitialize(this, common); + } else { + /* some dummy klex */ + return PICO_OK; + } +} + +/* for now we don't need to do anything special for the main lex */ +/* +pico_status_t picoklex_specializeMainLexKnowledgeBase( + picoknow_KnowledgeBase this, + picoos_Common common) +{ + return picoklex_specializeLexKnowledgeBase(this,common); +} +*/ + + +/* ************************************************************/ +/* lexicon getLex */ +/* ************************************************************/ + +picoklex_Lex picoklex_getLex(picoknow_KnowledgeBase this) +{ + if (NULL == this) { + return NULL; + } else { + return (picoklex_Lex) this->subObj; + } +} + + +/* ************************************************************/ +/* functions on searchindex */ +/* ************************************************************/ + + +static picoos_uint32 klex_getSearchIndexVal(const klex_SubObj this, + picoos_uint16 index) +{ + picoos_uint32 pos, val; + pos = index * PICOKLEX_LEX_SIE_SIZE; + val = this->searchind[pos]; + val = (val << 8) + this->searchind[pos + 1]; + val = (val << 8) + this->searchind[pos + 2]; + return val; +} + + +/* Determine first lexblock containing entries for specified + grapheme. */ + +static picoos_uint16 klex_getLexblockNr(const klex_SubObj this, + const picoos_uint8 *graphsi) { + /* graphsi is of len PICOKLEX_LEX_SI_NGRAPHS */ + picoos_int32 low, mid, high; + picoos_uint32 searchval, indval; + + /* PICOKLEX_LEX_SIE_NRGRAPHS */ + + /* convert graph-prefix to number with 'lexicographic' ordering */ + searchval = graphsi[0]; + searchval = (searchval << 8) + graphsi[1]; + searchval = (searchval << 8) + graphsi[2]; + + low = 0; + high = this->nrblocks; + + /* do binary search */ + while (low < high) { + mid = (low + high) / 2; + indval = klex_getSearchIndexVal(this, mid); + if (indval < searchval) { + low = mid + 1; + } else { + high = mid; + } + } + PICODBG_ASSERT(high == low); + /* low points to the first entry greater than or equal to searchval */ + + if (low < this->nrblocks) { + indval = klex_getSearchIndexVal(this, low); + if (indval > searchval) { + low--; + /* if there are identical elements in the search index we have + to move to the first one */ + if (low > 0) { + indval = klex_getSearchIndexVal(this, low); + while (indval == klex_getSearchIndexVal(this, low-1)) { + low--; + } + } + } + } else { + low = this->nrblocks - 1; + } + +#if defined(PICO_DEBUG) + { + picoos_uint32 pos = low * PICOKLEX_LEX_SIE_SIZE; + PICODBG_DEBUG(("binary search result is %c%c%c (%d)", + this->searchind[pos], this->searchind[pos + 1], + this->searchind[pos + 2], low)); + } +#endif + + return (picoos_uint16) low; +} + + +/* Determine number of adjacent lexblocks containing entries for + the same grapheme search prefix (identified by search index). */ + +static picoos_uint16 klex_getLexblockRange(const klex_SubObj this, + picoos_uint16 index) +{ + picoos_uint16 count; + picoos_uint32 sval1, sval2; + + sval1 = klex_getSearchIndexVal(this, index); + +#if defined(PICO_DEBUG) + /* 'index' must point to first lexblock of its kind */ + if (index > 0) { + sval2 = klex_getSearchIndexVal(this, index - 1); + PICODBG_ASSERT(sval1 != sval2); + } +#endif + + index++; + sval2 = klex_getSearchIndexVal(this, index); + + count = 1; + while (sval1 == sval2) { + count++; + index++; + sval2 = klex_getSearchIndexVal(this, index); + } + + return count; +} + + +/* ************************************************************/ +/* functions on single lexblock */ +/* ************************************************************/ + +static picoos_int8 klex_lexMatch(picoos_uint8 *lexentry, + const picoos_uint8 *graph, + const picoos_uint16 graphlen) { + picoos_uint8 i; + picoos_uint8 lexlen; + picoos_uint8 *lexgraph; + + lexlen = lexentry[0] - 1; + lexgraph = &(lexentry[1]); + for (i=0; (i graph[i]) { + return 1; + } + } + if (graphlen == lexlen) { + return 0; + } else if (lexlen < graphlen) { + return -1; + } else { + return 1; + } +} + + +static void klex_setLexResult(const picoos_uint8 *lexentry, + const picoos_uint32 lexpos, + picoklex_lexl_result_t *lexres) { + picoos_uint8 i; + + /* check if :G2P */ + if ((lexentry[lexentry[0] + 2]) == PICOKLEX_NEEDS_G2P) { + /* set pos */ + lexres->posind[0] = lexentry[lexentry[0] + 1]; + /* set rest */ + lexres->phonfound = FALSE; + lexres->posindlen = 1; + lexres->nrres = 1; + PICODBG_DEBUG(("result %d :G2P", lexres->nrres)); + } else { + i = lexres->nrres * (PICOKLEX_POSIND_SIZE); + lexres->posindlen += PICOKLEX_POSIND_SIZE; + lexres->phonfound = TRUE; + /* set pos */ + lexres->posind[i++] = lexentry[lexentry[0] + 1]; + /* set ind, PICOKLEX_IND_SIZE */ + lexres->posind[i++] = 0x000000ff & (lexpos); + lexres->posind[i++] = 0x000000ff & (lexpos >> 8); + lexres->posind[i] = 0x000000ff & (lexpos >> 16); + lexres->nrres++; + PICODBG_DEBUG(("result %d", lexres->nrres)); + } +} + + +static void klex_lexblockLookup(klex_SubObj this, + const picoos_uint32 lexposStart, + const picoos_uint32 lexposEnd, + const picoos_uint8 *graph, + const picoos_uint16 graphlen, + picoklex_lexl_result_t *lexres) { + picoos_uint32 lexpos; + picoos_int8 rv; + + lexres->nrres = 0; + + lexpos = lexposStart; + rv = -1; + while ((rv < 0) && (lexpos < lexposEnd)) { + + rv = klex_lexMatch(&(this->lexblocks[lexpos]), graph, graphlen); + + if (rv == 0) { /* found */ + klex_setLexResult(&(this->lexblocks[lexpos]), lexpos, lexres); + if (lexres->phonfound) { + /* look for more results, up to MAX_NRRES, don't even + check if more results would be available */ + while ((lexres->nrres < PICOKLEX_MAX_NRRES) && + (lexpos < lexposEnd)) { + lexpos += this->lexblocks[lexpos]; + lexpos += this->lexblocks[lexpos]; + /* if there are no more entries in this block, advance + to next block by skipping all zeros */ + while ((this->lexblocks[lexpos] == 0) && + (lexpos < lexposEnd)) { + lexpos++; + } + if (lexpos < lexposEnd) { + if (klex_lexMatch(&(this->lexblocks[lexpos]), graph, + graphlen) == 0) { + klex_setLexResult(&(this->lexblocks[lexpos]), + lexpos, lexres); + } else { + /* no more results, quit loop */ + lexpos = lexposEnd; + } + } + } + } else { + /* :G2P mark */ + } + } else if (rv < 0) { + /* not found, goto next entry */ + lexpos += this->lexblocks[lexpos]; + lexpos += this->lexblocks[lexpos]; + /* if there are no more entries in this block, advance + to next block by skipping all zeros */ + while ((this->lexblocks[lexpos] == 0) && (lexpos < lexposEnd)) { + lexpos++; + } + } else { + /* rv > 0, not found, won't show up later in block */ + } + } +} + + +/* ************************************************************/ +/* lexicon lookup functions */ +/* ************************************************************/ + +picoos_uint8 picoklex_lexLookup(const picoklex_Lex this, + const picoos_uint8 *graph, + const picoos_uint16 graphlen, + picoklex_lexl_result_t *lexres) { + picoos_uint16 lbnr, lbc; + picoos_uint32 lexposStart, lexposEnd; + picoos_uint8 i; + picoos_uint8 tgraph[PICOKLEX_LEX_SIE_NRGRAPHS]; + klex_SubObj klex = (klex_SubObj) this; + + if (NULL == klex) { + PICODBG_ERROR(("no lexicon loaded")); + /* no exception here needed, already checked at initialization */ + return FALSE; + } + + lexres->nrres = 0; + lexres->posindlen = 0; + lexres->phonfound = FALSE; + + for (i = 0; inrblocks) == 0) { + /* no searchindex, no lexblock */ + PICODBG_WARN(("no searchindex, no lexblock")); + return FALSE; + } else { + lbnr = klex_getLexblockNr(klex, tgraph); + PICODBG_ASSERT(lbnr < klex->nrblocks); + lbc = klex_getLexblockRange(klex, lbnr); + PICODBG_ASSERT((lbc >= 1) && (lbc <= klex->nrblocks)); + } + PICODBG_DEBUG(("lexblock nr: %d (#%d)", lbnr, lbc)); + + lexposStart = lbnr * PICOKLEX_LEXBLOCK_SIZE; + lexposEnd = lexposStart + lbc * PICOKLEX_LEXBLOCK_SIZE; + + PICODBG_DEBUG(("lookup start, lexpos range %d..%d", lexposStart,lexposEnd)); + klex_lexblockLookup(klex, lexposStart, lexposEnd, graph, graphlen, lexres); + PICODBG_DEBUG(("lookup done, %d found", lexres->nrres)); + + return (lexres->nrres > 0); +} + + +picoos_uint8 picoklex_lexIndLookup(const picoklex_Lex this, + const picoos_uint8 *ind, + const picoos_uint8 indlen, + picoos_uint8 *pos, + picoos_uint8 **phon, + picoos_uint8 *phonlen) { + picoos_uint32 pentry; + klex_SubObj klex = (klex_SubObj) this; + + /* check indlen */ + if (indlen != PICOKLEX_IND_SIZE) { + return FALSE; + } + + /* PICOKLEX_IND_SIZE */ + pentry = 0x000000ff & (ind[0]); + pentry |= ((picoos_uint32)(ind[1]) << 8); + pentry |= ((picoos_uint32)(ind[2]) << 16); + + /* check ind if it is within lexblocks byte stream, if not, return FALSE */ + if (pentry >= ((picoos_uint32)klex->nrblocks * PICOKLEX_LEXBLOCK_SIZE)) { + return FALSE; + } + + pentry += (klex->lexblocks[pentry]); + *phonlen = (klex->lexblocks[pentry++]) - 2; + *pos = klex->lexblocks[pentry++]; + *phon = &(klex->lexblocks[pentry]); + + PICODBG_DEBUG(("pentry: %d, phonlen: %d", pentry, *phonlen)); + return TRUE; +} + +#ifdef __cplusplus +} +#endif + + +/* end */ diff --git a/pico/lib/picoklex.h b/pico/lib/picoklex.h new file mode 100644 index 0000000..e186393 --- /dev/null +++ b/pico/lib/picoklex.h @@ -0,0 +1,129 @@ +/* + * 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 picoklex.h + * + * knowledge base: lexicon + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#ifndef PICOKLEX_H_ +#define PICOKLEX_H_ + +#include "picoos.h" +#include "picoknow.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* ************************************************************/ +/* function to create specialized kb, */ +/* to be used by picorsrc only */ +/* ************************************************************/ + +pico_status_t picoklex_specializeLexKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common); + + +/* ************************************************************/ +/* lexicon type and getLex function */ +/* ************************************************************/ + +/* lexicon type */ +typedef struct picoklex_lex * picoklex_Lex; + +/* return kb lex for usage in PU */ +picoklex_Lex picoklex_getLex(picoknow_KnowledgeBase this); + + +/* ************************************************************/ +/* lexicon lookup result type */ +/* ************************************************************/ + +/* max nr of results */ +#define PICOKLEX_MAX_NRRES 4 + +/* nr of bytes used for pos and index, needs to fit in uint32, ie. max 4 */ +#define PICOKLEX_POSIND_SIZE 4 +/* nr of bytes used for index, needs to fit in uint32, ie. max 4 */ +#define PICOKLEX_IND_SIZE 3 +/* max len (in bytes) of ind, (PICOKLEX_MAX_NRRES * PICOKLEX_POSIND_SIZE) */ +#define PICOKLEX_POSIND_MAXLEN 16 + + +/* the lexicon lookup result(s) are stored in field posind, which + contains a sequence of + POS1-byte, IND1-bytes, POS2-byte, IND2-bytes, etc. + + the IND-bytes are the byte position(s) in the lexblocks part of the + lexicon byte stream, starting at picoklex_lex_t.lexblocks. + + for lexentries without phones only the POS (there can be only one) + is stored in posind, nrres equals one, and phonfound is FALSE. +*/ + +typedef struct { + picoos_uint8 nrres; /* number of results, 0 of no entry found */ + picoos_uint8 posindlen; /* number of posind bytes */ + picoos_uint8 phonfound; /* phones found flag, TRUE if found */ + picoos_uint8 posind[PICOKLEX_POSIND_MAXLEN]; /* sequence of multi-ind, + one per result */ +} picoklex_lexl_result_t; + + +/* ************************************************************/ +/* lexicon lookup functions */ +/* ************************************************************/ + +/** lookup lex by graph; result(s) are in lexres, ie. the phones are + not returned directly (because they are used later and space can be + saved using indices first), lexres contains an index (or several) + to the entry for later fast lookup once the phones are needed. + PICOKLEX_IND_SIZE bytes are used for the index, these ind bytes are + saved in the WORDINDEX items. If at least one entry is found TRUE + is returned, FALSE otherwise */ +picoos_uint8 picoklex_lexLookup(const picoklex_Lex this, + const picoos_uint8 *graph, + const picoos_uint16 graphlen, + picoklex_lexl_result_t *lexres); + +/** lookup lex entry by index ind; ind is a sequence of bytes with + length indlen (must be equal PICOKLEX_IND_SIZE) that is the content + of a WORDINDEX item. Returns TRUE if okay, FALSE otherwise */ +picoos_uint8 picoklex_lexIndLookup(const picoklex_Lex this, + const picoos_uint8 *ind, + const picoos_uint8 indlen, + picoos_uint8 *pos, + picoos_uint8 **phon, + picoos_uint8 *phonlen); + +#ifdef __cplusplus +} +#endif + + +#endif /*PICOKLEX_H_*/ diff --git a/pico/lib/picoknow.c b/pico/lib/picoknow.c new file mode 100644 index 0000000..70b471c --- /dev/null +++ b/pico/lib/picoknow.c @@ -0,0 +1,81 @@ +/* + * 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 picoknow.c + * + * 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 "picoknow.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/** class : KnowledgeBase + * shortcut : kb + * + */ +extern picoknow_KnowledgeBase picoknow_newKnowledgeBase(picoos_MemoryManager mm) +{ + picoknow_KnowledgeBase this; + PICODBG_TRACE(("start")); + + this = picoos_allocate(mm,sizeof(*this)); + if (NULL != this) { + PICODBG_TRACE(("allocated KnowledgeBase at address %i with size %i",(picoos_uint32)this,sizeof(*this))); + /* initialize */ + this->next = NULL; + this->id = PICOKNOW_KBID_NULL; + this->base = NULL; + this->size = 0; + this->subObj = NULL; + this->subDeallocate = NULL; + } + return this; +} + +extern void picoknow_disposeKnowledgeBase(picoos_MemoryManager mm, picoknow_KnowledgeBase * this) +{ + picoos_uint8 id; + if (NULL != (*this)) { + id = (*this)->id; + PICODBG_TRACE(("disposing KnowledgeBase id=%i",id)); + /* terminate */ + if ((*this)->subObj != NULL) { + (*this)->subDeallocate((*this),mm); + } + picoos_deallocate(mm,(void**)this); + } +} + +#ifdef __cplusplus +} +#endif + +/* End picoknow.c */ diff --git a/pico/lib/picoknow.h b/pico/lib/picoknow.h new file mode 100644 index 0000000..1444856 --- /dev/null +++ b/pico/lib/picoknow.h @@ -0,0 +1,190 @@ +/* + * 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 picoknow.h + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +/** + * @addtogroup picoknow + + * Pico knowledge base \n + * +*/ + +#ifndef PICOKNOW_H_ +#define PICOKNOW_H_ + +#include "picodefs.h" +#include "picoos.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +typedef enum picoknow_kb_id { + PICOKNOW_KBID_NULL = 0, + /* base / tpp 1 - 7 */ + PICOKNOW_KBID_TPP_MAIN = 1, + PICOKNOW_KBID_TAB_GRAPHS = 2, + PICOKNOW_KBID_TAB_PHONES = 3, + PICOKNOW_KBID_TAB_POS = 4, + PICOKNOW_KBID_FIXED_IDS = 7, + /* debug */ + PICOKNOW_KBID_DBG = 8, + + /* textana 9 - 32 */ + PICOKNOW_KBID_LEX_MAIN = 9, + PICOKNOW_KBID_DT_POSP = 10, + PICOKNOW_KBID_DT_POSD = 11, + PICOKNOW_KBID_DT_G2P = 12, + PICOKNOW_KBID_FST_WPHO_1 = 13, + PICOKNOW_KBID_FST_WPHO_2 = 14, + PICOKNOW_KBID_FST_WPHO_3 = 15, + PICOKNOW_KBID_FST_WPHO_4 = 16, + PICOKNOW_KBID_FST_WPHO_5 = 17, + PICOKNOW_KBID_DT_PHR = 18, + PICOKNOW_KBID_DT_ACC = 19, + PICOKNOW_KBID_FST_SPHO_1 = 20, + PICOKNOW_KBID_FST_SPHO_2 = 21, + PICOKNOW_KBID_FST_SPHO_3 = 22, + PICOKNOW_KBID_FST_SPHO_4 = 23, + PICOKNOW_KBID_FST_SPHO_5 = 24, + + PICOKNOW_KBID_FST_XSAMPA_PARSE = 25, + PICOKNOW_KBID_FST_SVOXPA_PARSE = 26, + PICOKNOW_KBID_FST_XSAMPA2SVOXPA = 27, + + PICOKNOW_KBID_FST_SPHO_6 = 28, + PICOKNOW_KBID_FST_SPHO_7 = 29, + PICOKNOW_KBID_FST_SPHO_8 = 30, + PICOKNOW_KBID_FST_SPHO_9 = 31, + PICOKNOW_KBID_FST_SPHO_10 = 32, + + + /* siggen 33 - 48 */ + PICOKNOW_KBID_DT_DUR = 34, + PICOKNOW_KBID_DT_LFZ1 = 35, + PICOKNOW_KBID_DT_LFZ2 = 36, + PICOKNOW_KBID_DT_LFZ3 = 37, + PICOKNOW_KBID_DT_LFZ4 = 38, + PICOKNOW_KBID_DT_LFZ5 = 39, + PICOKNOW_KBID_DT_MGC1 = 40, + PICOKNOW_KBID_DT_MGC2 = 41, + PICOKNOW_KBID_DT_MGC3 = 42, + PICOKNOW_KBID_DT_MGC4 = 43, + PICOKNOW_KBID_DT_MGC5 = 44, + PICOKNOW_KBID_PDF_DUR = 45, + PICOKNOW_KBID_PDF_LFZ = 46, + PICOKNOW_KBID_PDF_MGC = 47, + PICOKNOW_KBID_PDF_PHS = 48, + + /* user tpp 49 - 56 */ + PICOKNOW_KBID_TPP_USER_1 = 49, + PICOKNOW_KBID_TPP_USER_2 = 50, + + /* user lex 57 - 63 */ + PICOKNOW_KBID_LEX_USER_1 = 57, + PICOKNOW_KBID_LEX_USER_2 = 58, + + PICOKNOW_KBID_DUMMY = 127 + +} picoknow_kb_id_t; + +#define PICOKNOW_DEFAULT_RESOURCE_NAME (picoos_char *) "__PICO_DEF_RSRC" + +#define PICOKNOW_MAX_NUM_WPHO_FSTS 5 +#define PICOKNOW_MAX_NUM_SPHO_FSTS 10 +#define PICOKNOW_MAX_NUM_ULEX 2 +#define PICOKNOW_MAX_NUM_UTPP 2 + +#define PICOKNOW_KBID_WPHO_ARRAY { \ + PICOKNOW_KBID_FST_WPHO_1, \ + PICOKNOW_KBID_FST_WPHO_2, \ + PICOKNOW_KBID_FST_WPHO_3, \ + PICOKNOW_KBID_FST_WPHO_4, \ + PICOKNOW_KBID_FST_WPHO_5 \ +} + +#define PICOKNOW_KBID_SPHO_ARRAY { \ + PICOKNOW_KBID_FST_SPHO_1, \ + PICOKNOW_KBID_FST_SPHO_2, \ + PICOKNOW_KBID_FST_SPHO_3, \ + PICOKNOW_KBID_FST_SPHO_4, \ + PICOKNOW_KBID_FST_SPHO_5, \ + PICOKNOW_KBID_FST_SPHO_6, \ + PICOKNOW_KBID_FST_SPHO_7, \ + PICOKNOW_KBID_FST_SPHO_8, \ + PICOKNOW_KBID_FST_SPHO_9, \ + PICOKNOW_KBID_FST_SPHO_10 \ +} + +#define PICOKNOW_KBID_ULEX_ARRAY { \ + PICOKNOW_KBID_LEX_USER_1, \ + PICOKNOW_KBID_LEX_USER_2, \ +} + +#define PICOKNOW_KBID_UTPP_ARRAY { \ + PICOKNOW_KBID_TPP_USER_1, \ + PICOKNOW_KBID_TPP_USER_2, \ +} + +/* max size (including NULLC) of descriptive name corresponding to KBID */ +#define PICOKNOW_MAX_KB_NAME_SIZ 16 + +/* maximum number of kbs in one resource */ +#define PICOKNOW_MAX_NUM_RESOURCE_KBS 64 + + +/** class : KnowledgeBase + * shortcut : kb + * + */ +typedef struct picoknow_knowledge_base * picoknow_KnowledgeBase; + +typedef pico_status_t (* picoknow_kbSubDeallocate) (register picoknow_KnowledgeBase this, picoos_MemoryManager mm); + +typedef struct picoknow_knowledge_base { + /* public */ + picoknow_KnowledgeBase next; + picoknow_kb_id_t id; + picoos_uint8 * base; /* start address */ + picoos_uint32 size; /* size */ + + /* protected */ + picoknow_kbSubDeallocate subDeallocate; + void * subObj; +} picoknow_knowledge_base_t; + +extern picoknow_KnowledgeBase picoknow_newKnowledgeBase(picoos_MemoryManager mm); + +extern void picoknow_disposeKnowledgeBase(picoos_MemoryManager mm, picoknow_KnowledgeBase * this); + +#ifdef __cplusplus +} +#endif + + +#endif /*PICOKNOW_H_*/ diff --git a/pico/lib/picokpdf.c b/pico/lib/picokpdf.c new file mode 100644 index 0000000..bbdbec4 --- /dev/null +++ b/pico/lib/picokpdf.c @@ -0,0 +1,381 @@ +/* + * 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 picokpdf.c + * + * knowledge handling for pdf + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#include "picoos.h" +#include "picodbg.h" +#include "picoknow.h" +#include "picokpdf.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* ************************************************************/ +/* pdf */ +/* ************************************************************/ + +/* + * @addtogroup picokpdf + * + overview: format of knowledge base pdf file + + This is the format for the dur pdf file: + - Numframes: 1 uint16 + - Vecsize: 1 uint8 + - sampperframe: 1 uint8 + - Phonquantlen: 1 uint8 + - Phonquant: Phonquantlen uint8 + - Statequantlen: 1 uint8 + - Statequantlen: Statequantlen uint8 + - And then numframes x vecsize uint8 + + This is the format for mul (mgc and lfz) pdf files: + - numframes: 1 uint16 + - vecsize: 1 uint8 + - numstates: 1 uint8 + - numframesperstate: numstates uint16 + - ceporder: 1 uint8 + - numvuv 1 uint8 + - numdeltas: 1 uint8 + - scmeanpow: 1 uint8 + - maxbigpow: 1 uint8 + - scmeanpowum KPDF_NUMSTREAMS * ceporder uint8 + - scivarpow KPDF_NUMSTREAMS * ceporder uint8 + + And then numframes x vecsize uint8 + +*/ + + +/* ************************************************************/ +/* pdf data defines */ +/* may not be changed with current implementation */ +/* ************************************************************/ + + +#define KPDF_NUMSTREAMS 3 /* coeff, delta, deltadelta */ + + +/* ************************************************************/ +/* pdf loading */ +/* ************************************************************/ + +static pico_status_t kpdfDURInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) { + picokpdf_pdfdur_t *pdfdur; + picoos_uint16 pos; + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + pdfdur = (picokpdf_pdfdur_t *)this->subObj; + + pos = 0; + + pdfdur->numframes = ((picoos_uint16)(this->base[pos+1])) << 8 | + this->base[pos]; + pos += 2; + pdfdur->vecsize = this->base[pos++]; + pdfdur->sampperframe = this->base[pos++]; + pdfdur->phonquantlen = this->base[pos++]; + pdfdur->phonquant = &(this->base[pos]); + pos += pdfdur->phonquantlen; + pdfdur->statequantlen = this->base[pos++]; + pdfdur->statequant = &(this->base[pos]); + pos += pdfdur->statequantlen; + pdfdur->content = &(this->base[pos]); + PICODBG_DEBUG(("numframes %d, vecsize %d, phonquantlen %d, " + "statequantlen %d", pdfdur->numframes, pdfdur->vecsize, + pdfdur->phonquantlen, pdfdur->statequantlen)); + if ((picoos_uint32)(pos + (pdfdur->numframes * pdfdur->vecsize)) != this->size) { + PICODBG_DEBUG(("header-spec size %d, kb-size %d", + pos + (pdfdur->numframes * pdfdur->vecsize), + this->size)); + return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, + NULL, NULL); + } + PICODBG_DEBUG(("dur pdf initialized")); + return PICO_OK; +} + +static picoos_uint8 convScaleFactorToBig(picoos_uint8 pow, picoos_uint8 bigpow) +{ + if (pow > 0x0F) { + pow = bigpow + (0xFF - pow + 1); /* take 2's complement of negative pow */ + } else if (bigpow >= pow) { + pow = bigpow - pow; + } else { + /* error: bigpow is smaller than input pow */ + return 0; + } + return pow; +} + +static pico_status_t kpdfMULInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) { + picokpdf_pdfmul_t *pdfmul; + picoos_uint16 pos; + picoos_uint8 scmeanpow, maxbigpow, nummean; + picoos_uint8 i; + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + pdfmul = (picokpdf_pdfmul_t *)this->subObj; + + pos = 0; + + pdfmul->numframes = ((picoos_uint16)(this->base[pos+1])) << 8 | + this->base[pos]; + pos += 2; + pdfmul->vecsize = this->base[pos++]; + pdfmul->numstates = this->base[pos++]; + { + pdfmul->stateoffset[0] = (picoos_uint16) 0; + for (i=1; inumstates; i++) { + pdfmul->stateoffset[i] = pdfmul->stateoffset[i-1] + (this->base[pos] | ((picoos_uint16) this->base[pos+1] << 8)); + pos += 2; + } + pos += 2; /* we don't need the last number if we only need the offset (i.e. how to get to the vector start) */ + } + + pdfmul->ceporder = this->base[pos++]; + pdfmul->numvuv = this->base[pos++]; + pdfmul->numdeltas = this->base[pos++]; + scmeanpow = this->base[pos++]; + maxbigpow = this->base[pos++]; + if (maxbigpow < PICOKPDF_BIG_POW) { + PICODBG_ERROR(("bigpow %i is larger than maxbigpow %i defined in pdf lingware", PICOKPDF_BIG_POW, maxbigpow)); + return picoos_emRaiseException(common->em, PICO_EXC_MAX_NUM_EXCEED,NULL,NULL); + } + pdfmul->bigpow = PICOKPDF_BIG_POW; /* what we have to use is the smaller number! */ + + pdfmul->amplif = this->base[pos++]; + + /* bigpow corrected by scmeanpow, multiply means by 2^meanpow to obtain fixed point representation */ + pdfmul->meanpow = convScaleFactorToBig(scmeanpow, pdfmul->bigpow); + if (0 == pdfmul->meanpow) { + PICODBG_ERROR(("error in convScaleFactorToBig")); + return picoos_emRaiseException(common->em, PICO_EXC_MAX_NUM_EXCEED,NULL,NULL); + } + nummean = 3*pdfmul->ceporder; + + pdfmul->meanpowUm = picoos_allocate(common->mm,nummean*sizeof(picoos_uint8)); + pdfmul->ivarpow = picoos_allocate(common->mm,nummean*sizeof(picoos_uint8)); + if ((NULL == pdfmul->meanpowUm) || (NULL == pdfmul->ivarpow)) { + picoos_deallocate(common->mm,(void *) &(pdfmul->meanpowUm)); + picoos_deallocate(common->mm,(void *) &(pdfmul->ivarpow)); + return picoos_emRaiseException(common->em,PICO_EXC_OUT_OF_MEM,NULL,NULL); + } + + /* read meanpowUm and convert on the fly */ + /* meaning of meanpowUm becomes: multiply means from pdf stream by 2^meanpowUm + * to achieve fixed point scaling by big + */ + for (i=0; imeanpowUm[i] = convScaleFactorToBig(this->base[pos++], pdfmul->bigpow); + } + + /*read ivarpow and convert on the fly */ + for (i=0; iivarpow[i] = convScaleFactorToBig(this->base[pos++], pdfmul->bigpow); + } + + /* check numdeltas */ + if ((pdfmul->numdeltas == 0xFF) && (pdfmul->vecsize != (pdfmul->numvuv + pdfmul->ceporder * 3 * (2+1)))) { + PICODBG_ERROR(("header has inconsistent values for vecsize, ceporder, numvuv, and numdeltas")); + return picoos_emRaiseException(common->em,PICO_EXC_FILE_CORRUPT,NULL,NULL); + } + +/* vecsize: 1 uint8 for vuv + + ceporder short for static means + + numdeltas uint8 and short for sparse delta means + + ceporder*3 uint8 for static and delta inverse variances +*/ + if ((pdfmul->numdeltas != 0xFF) && (pdfmul->vecsize != pdfmul->numvuv+pdfmul->ceporder*2+pdfmul->numdeltas*3+pdfmul->ceporder*3)) { + PICODBG_ERROR(("header has inconsistent values for vecsize, ceporder, numvuv, and numdeltas\n" + "vecsize = %i while numvuv+ceporder*2 + numdeltas*3 + ceporder*3 = %i", + pdfmul->vecsize, pdfmul->numvuv + pdfmul->ceporder*2 + pdfmul->numdeltas * 3 + pdfmul->ceporder * 3)); + return picoos_emRaiseException(common->em,PICO_EXC_FILE_CORRUPT,NULL,NULL); + } + pdfmul->content = &(this->base[pos]); + PICODBG_DEBUG(("numframes %d, vecsize %d, numstates %d, ceporder %d, " + "numvuv %d, numdeltas %d, meanpow %d, bigpow %d", + pdfmul->numframes, pdfmul->vecsize, pdfmul->numstates, + pdfmul->ceporder, pdfmul->numvuv, pdfmul->numdeltas, + pdfmul->meanpow, pdfmul->bigpow)); + if ((picoos_uint32)(pos + (pdfmul->numframes * pdfmul->vecsize)) != this->size) { + PICODBG_DEBUG(("header-spec size %d, kb-size %d", + pos + (pdfmul->numframes * pdfmul->vecsize), + this->size)); + return picoos_emRaiseException(common->em, PICO_EXC_FILE_CORRUPT, + NULL, NULL); + } + PICODBG_DEBUG(("mul pdf initialized")); + return PICO_OK; +} + +static pico_status_t kpdfPHSInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) { + picokpdf_pdfphs_t *pdfphs; + picoos_uint16 pos; + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + pdfphs = (picokpdf_pdfphs_t *)this->subObj; + + pos = 0; + + pdfphs->numvectors = ((picoos_uint16)(this->base[pos+1])) << 8 | + this->base[pos]; + pos += 2; + pdfphs->indexBase = &(this->base[pos]); + pdfphs->contentBase = pdfphs->indexBase + pdfphs->numvectors * sizeof(picoos_uint32); + PICODBG_DEBUG(("phs pdf initialized")); + return PICO_OK; +} + + + +static pico_status_t kpdfMULSubObjDeallocate(register picoknow_KnowledgeBase this, + picoos_MemoryManager mm) { + + + picokpdf_pdfmul_t *pdfmul; + + if ((NULL != this) && (NULL != this->subObj)) { + pdfmul = (picokpdf_pdfmul_t *)this->subObj; + picoos_deallocate(mm,(void *) &(pdfmul->meanpowUm)); + picoos_deallocate(mm,(void *) &(pdfmul->ivarpow)); + picoos_deallocate(mm, (void *) &(this->subObj)); + } + return PICO_OK; +} + +static pico_status_t kpdfDURSubObjDeallocate(register picoknow_KnowledgeBase this, + picoos_MemoryManager mm) { + if (NULL != this) { + picoos_deallocate(mm, (void *) &this->subObj); + } + return PICO_OK; +} + +static pico_status_t kpdfPHSSubObjDeallocate(register picoknow_KnowledgeBase this, + picoos_MemoryManager mm) { + if (NULL != this) { + picoos_deallocate(mm, (void *) &this->subObj); + } + return PICO_OK; +} + +/* we don't offer a specialized constructor for a *KnowledgeBase but + * instead a "specializer" of an allready existing generic + * picoknow_KnowledgeBase */ + +pico_status_t picokpdf_specializePdfKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common, + const picokpdf_kpdftype_t kpdftype) { + pico_status_t status; + + if (NULL == this) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + switch (kpdftype) { + case PICOKPDF_KPDFTYPE_DUR: + this->subDeallocate = kpdfDURSubObjDeallocate; + this->subObj = picoos_allocate(common->mm,sizeof(picokpdf_pdfdur_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + status = kpdfDURInitialize(this, common); + break; + case PICOKPDF_KPDFTYPE_MUL: + this->subDeallocate = kpdfMULSubObjDeallocate; + this->subObj = picoos_allocate(common->mm,sizeof(picokpdf_pdfmul_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + status = kpdfMULInitialize(this, common); + break; + case PICOKPDF_KPDFTYPE_PHS: + this->subDeallocate = kpdfPHSSubObjDeallocate; + this->subObj = picoos_allocate(common->mm,sizeof(picokpdf_pdfphs_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + status = kpdfPHSInitialize(this, common); + break; + + default: + return picoos_emRaiseException(common->em, PICO_ERR_OTHER, + NULL, NULL); + } + + if (status != PICO_OK) { + picoos_deallocate(common->mm, (void *) &this->subObj); + return picoos_emRaiseException(common->em, status, NULL, NULL); + } + return PICO_OK; +} + + +/* ************************************************************/ +/* pdf getPdf* */ +/* ************************************************************/ + +picokpdf_PdfDUR picokpdf_getPdfDUR(picoknow_KnowledgeBase this) { + return ((NULL == this) ? NULL : ((picokpdf_PdfDUR) this->subObj)); +} + +picokpdf_PdfMUL picokpdf_getPdfMUL(picoknow_KnowledgeBase this) { + return ((NULL == this) ? NULL : ((picokpdf_PdfMUL) this->subObj)); +} + +picokpdf_PdfPHS picokpdf_getPdfPHS(picoknow_KnowledgeBase this) { + return ((NULL == this) ? NULL : ((picokpdf_PdfPHS) this->subObj)); +} + + +#ifdef __cplusplus +} +#endif + + +/* end */ diff --git a/pico/lib/picokpdf.h b/pico/lib/picokpdf.h new file mode 100644 index 0000000..f4508a1 --- /dev/null +++ b/pico/lib/picokpdf.h @@ -0,0 +1,160 @@ +/* + * 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 picokpdf.h + * + * knowledge handling for pdf + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#ifndef PICOKPDF_H_ +#define PICOKPDF_H_ + +#include "picoos.h" +#include "picoknow.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* ************************************************************/ +/** + * @addtogroup picokpdf + * + Two specialized pdf kb types are provided by this knowledge + handling module: + + - pdf dur: ...kpdf_DUR (for dur) + - pdf mul: ...kpdf_MUL (for lfz and mgc) + - pdf phs: ...kpdf_PHS (for phase) + +*/ +/* ************************************************************/ + + +/* ************************************************************/ +/* defines and functions to create specialized kb, */ +/* to be used by picorsrc only */ +/* ************************************************************/ + +#define PICOKPDF_MAX_NUM_STATES 10 + +#define PICOKPDF_MAX_MUL_LFZ_CEPORDER 1 +#define PICOKPDF_MAX_MUL_MGC_CEPORDER 25 + +/* trade accuracy against computation: more long multiplications. + * Maximum is 15 when invdiag0=(1<<(2*bigpow))/diag0 used + * currently observing instability in mlpg when bigpow >= 14, this needs to be investigated */ + +#define PICOKPDF_BIG_POW 12 + +typedef enum { + PICOKPDF_KPDFTYPE_DUR, + PICOKPDF_KPDFTYPE_MUL, + PICOKPDF_KPDFTYPE_PHS +} picokpdf_kpdftype_t; + +pico_status_t picokpdf_specializePdfKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common, + const picokpdf_kpdftype_t type); + + +/* ************************************************************/ +/* pdf types and get Pdf functions */ +/* ************************************************************/ + +/** object : PdfDur, PdfMUL + * shortcut : kpdf* + * derived from : picoknow_KnowledgeBase + */ + +typedef struct picokpdf_pdfdur *picokpdf_PdfDUR; +typedef struct picokpdf_pdfmul *picokpdf_PdfMUL; +typedef struct picokpdf_pdfphs *picokpdf_PdfPHS; + +/* subobj specific for pdf dur type */ +typedef struct picokpdf_pdfdur { + picoos_uint16 numframes; + picoos_uint8 vecsize; + picoos_uint8 sampperframe; + picoos_uint8 phonquantlen; + picoos_uint8 *phonquant; + picoos_uint8 statequantlen; + picoos_uint8 *statequant; + picoos_uint8 *content; +} picokpdf_pdfdur_t; + +/* subobj specific for pdf mul type */ +typedef struct picokpdf_pdfmul { + picoos_uint16 numframes; + picoos_uint8 vecsize; + picoos_uint8 numstates; + picoos_uint16 stateoffset[PICOKPDF_MAX_NUM_STATES]; /* offset within a phone to find the state ? */ + picoos_uint8 ceporder; + picoos_uint8 numvuv; + picoos_uint8 numdeltas; + picoos_uint8 meanpow; + picoos_uint8 bigpow; + picoos_uint8 amplif; + picoos_uint8 *meanpowUm; /* KPDF_NUMSTREAMS x ceporder values */ + picoos_uint8 *ivarpow; /* KPDF_NUMSTREAMS x ceporder values */ + picoos_uint8 *content; +} picokpdf_pdfmul_t; + +/* subobj specific for pdf phs type */ +typedef struct picokpdf_pdfphs { + picoos_uint16 numvectors; + picoos_uint8 *indexBase; + picoos_uint8 *contentBase; +} picokpdf_pdfphs_t; + +/* return kb pdf for usage in PU */ +picokpdf_PdfDUR picokpdf_getPdfDUR(picoknow_KnowledgeBase this); +picokpdf_PdfMUL picokpdf_getPdfMUL(picoknow_KnowledgeBase this); +picokpdf_PdfPHS picokpdf_getPdfPHS(picoknow_KnowledgeBase this); + + +/* ************************************************************/ +/* PDF DUR functions */ +/* ************************************************************/ + +/* e.g. */ +/*picoos_uint8 picokpdf_pdfDURgetEle(const picokpdf_PdfDUR this, + const picoos_uint16 row, + const picoos_uint16 col, + picoos_uint16 *val); +*/ + +/* ************************************************************/ +/* PDF MUL functions */ +/* ************************************************************/ + +#ifdef __cplusplus +} +#endif + + +#endif /*PICOKPDF_H_*/ diff --git a/pico/lib/picokpr.c b/pico/lib/picokpr.c new file mode 100644 index 0000000..956ae39 --- /dev/null +++ b/pico/lib/picokpr.c @@ -0,0 +1,652 @@ +/* + * 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 picokpr.c + * + * knowledge handling for text preprocessing + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +#include "picoos.h" +#include "picodbg.h" +#include "picodata.h" +#include "picoknow.h" +#include "picokpr.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* ************************************************************/ +/* preproc */ +/* ************************************************************/ + +/* + overview: +*/ + + +/* ************************************************************/ +/* preproc data defines */ +/* ************************************************************/ + +#define KPR_STR_SIZE 1 +#define KPR_LEXCAT_SIZE 2 +#define KPR_ATTRVAL_SIZE 4 +#define KPR_OUTITEM_SIZE 7 +#define KPR_TOK_SIZE 16 +#define KPR_PROD_SIZE 12 +#define KPR_CTX_SIZE 12 + +#define KPR_NETNAME_OFFSET 0 +#define KPR_STRARRLEN_OFFSET 4 +#define KPR_LEXCATARRLEN_OFFSET 8 +#define KPR_ATTRVALARRLEN_OFFSET 12 +#define KPR_OUTITEMARRLEN_OFFSET 16 +#define KPR_TOKARRLEN_OFFSET 20 +#define KPR_PRODARRLEN_OFFSET 24 +#define KPR_CTXARRLEN_OFFSET 28 + +#define KPR_ARRAY_START 32 + +#define KPR_MAX_INT32 2147483647 + +#define KPR_STR_OFS 0 + +#define KPR_LEXCAT_OFS 0 + +#define KPR_ATTRVAL_INT_OFS 0 +#define KPR_ATTRVAL_STROFS_OFS 0 +#define KPR_ATTRVAL_PRODOFS_OFS 0 +#define KPR_ATTRVAL_OUTITMOFS_OFS 0 +#define KPR_ATTRVAL_LEXCATOFS_OFS 0 + +#define KPR_OUTITEM_NEXTOFS_OFS 0 +#define KPR_OUTITEM_TYPE_OFS 2 +#define KPR_OUTITEM_STROFS_OFS 3 +#define KPR_OUTITEM_VAL_OFS 3 +#define KPR_OUTITEM_ARGOFS_OFS 3 + +#define KPR_TOK_SETWP_OFS 0 +#define KPR_TOK_SETNP_OFS 4 +#define KPR_TOK_NEXTOFS_OFS 8 +#define KPR_TOK_ALTLOFS_OFS 10 +#define KPR_TOK_ALTROFS_OFS 12 +#define KPR_TOK_ATTRIBOFS_OFS 14 + +#define KPR_PROD_PRODPREFCOST_OFS 0 +#define KPR_PROD_PRODNAMEOFS_OFS 4 +#define KPR_PROD_ATOKOFS_OFS 8 +#define KPR_PROD_ETOKOFS_OFS 10 + +#define KPR_CTX_CTXNAMEOFS_OFS 0 +#define KPR_CTX_NETNAMEOFS_OFS 4 +#define KPR_CTX_PRODNAMEOFS_OFS 8 + +/* ************************************************************/ +/* preproc type and loading */ +/* ************************************************************/ + +/* variable array element types */ +typedef picoos_uint8 picokpr_Str[KPR_STR_SIZE]; +typedef picoos_uint16 picokpr_LexCat2; +typedef picoos_uint8 picokpr_AttrVal[KPR_ATTRVAL_SIZE]; +typedef picoos_uint8 picokpr_OutItem[KPR_OUTITEM_SIZE]; +typedef picoos_uint8 picokpr_Tok[KPR_TOK_SIZE]; +typedef picoos_uint8 picokpr_Prod[KPR_PROD_SIZE]; +typedef picoos_uint8 picokpr_Ctx[KPR_CTX_SIZE]; + +/* variable array types */ +typedef picokpr_Str * picokpr_VarStrArr; +typedef picokpr_LexCat2 * picokpr_VarLexCatArr; +typedef picokpr_AttrVal * picokpr_VarAttrValArr; +typedef picokpr_OutItem * picokpr_VarOutItemArr; +typedef picokpr_Tok * picokpr_VarTokArr; +typedef picokpr_Prod * picokpr_VarProdArr; +typedef picokpr_Ctx * picokpr_VarCtxArr; + +/* ************************************************************/ +/* preproc type and loading */ +/* ************************************************************/ + +/** object : PreprocKnowledgeBase + * shortcut : kpr + * derived from : picoknow_KnowledgeBase + */ + +typedef struct kpr_subobj * kpr_SubObj; + +typedef struct kpr_subobj +{ + picoos_uchar * rNetName; + + picoos_int32 rStrArrLen; + picoos_int32 rLexCatArrLen; + picoos_int32 rAttrValArrLen; + picoos_int32 rOutItemArrLen; + picoos_int32 rTokArrLen; + picoos_int32 rProdArrLen; + picoos_int32 rCtxArrLen; + + picoos_uint8 * rStrArr; + picokpr_LexCat2 * rLexCatArr; + picokpr_AttrVal * rAttrValArr; + picokpr_OutItem * rOutItemArr; + picokpr_Tok * rTokArr; + picokpr_Prod * rProdArr; + picokpr_Ctx * rCtxArr; +} kpr_subobj_t; + + +static picoos_uint32 kpr_getUInt32(picoos_uint8 * p) +{ + return p[0] + 256*p[1] + 256*256*p[2] + 256*256*256*p[3]; +} + + +static pico_status_t kprInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) +{ + picoos_uint32 offset = 0; + kpr_subobj_t * kpr; + + PICODBG_DEBUG(("start")); + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + kpr = (kpr_subobj_t *) this->subObj; + + kpr->rStrArrLen = kpr_getUInt32(&(this->base[KPR_STRARRLEN_OFFSET])); + kpr->rLexCatArrLen = kpr_getUInt32(&(this->base[KPR_LEXCATARRLEN_OFFSET])); + kpr->rAttrValArrLen = kpr_getUInt32(&(this->base[KPR_ATTRVALARRLEN_OFFSET])); + kpr->rOutItemArrLen = kpr_getUInt32(&(this->base[KPR_OUTITEMARRLEN_OFFSET])); + kpr->rTokArrLen = kpr_getUInt32(&(this->base[KPR_TOKARRLEN_OFFSET])); + kpr->rProdArrLen = kpr_getUInt32(&(this->base[KPR_PRODARRLEN_OFFSET])); + kpr->rCtxArrLen = kpr_getUInt32(&(this->base[KPR_CTXARRLEN_OFFSET])); + + offset = KPR_ARRAY_START; + kpr->rStrArr = &(this->base[offset]); + PICODBG_DEBUG(("rStrArr : cs: %i, ss: %i, offset: %i", sizeof(picokpr_Str), KPR_STR_SIZE, offset)); + offset = offset + kpr->rStrArrLen * 1; + + kpr->rLexCatArr = (picokpr_LexCat2 *)&(this->base[offset]); + PICODBG_DEBUG(("rLexCatArr : cs: %i, ss: %i, offset: %i", KPR_LEXCAT_SIZE, sizeof(picokpr_LexCat2), offset)); + offset = offset + kpr->rLexCatArrLen * KPR_LEXCAT_SIZE; + + kpr->rAttrValArr = (picokpr_AttrVal *)&(this->base[offset]); + PICODBG_DEBUG(("rAttrValArr : cs: %i, ss: %i, offset: %i", KPR_ATTRVAL_SIZE, sizeof(picokpr_AttrVal), offset)); + offset = offset + kpr->rAttrValArrLen * KPR_ATTRVAL_SIZE; + + kpr->rOutItemArr = (picokpr_OutItem *)&(this->base[offset]); + PICODBG_DEBUG(("rOutItemArr : cs: %i, ss: %i, offset: %i", KPR_OUTITEM_SIZE, sizeof(picokpr_OutItem), offset)); + offset = offset + kpr->rOutItemArrLen * KPR_OUTITEM_SIZE; + + kpr->rTokArr = (picokpr_Tok *)&(this->base[offset]); + PICODBG_DEBUG(("rTokArr : cs: %i, ss: %i, offset: %i", KPR_TOK_SIZE, sizeof(picokpr_Tok), offset)); + offset = offset + kpr->rTokArrLen * KPR_TOK_SIZE; + + kpr->rProdArr = (picokpr_Prod *)&(this->base[offset]); + PICODBG_DEBUG(("rProdArr : cs: %i, ss: %i, offset: %i", KPR_PROD_SIZE, sizeof(picokpr_Prod), offset)); + offset = offset + kpr->rProdArrLen * KPR_PROD_SIZE; + + kpr->rCtxArr = (picokpr_Ctx *)&(this->base[offset]); + PICODBG_DEBUG(("rCtxArr : cs: %i, ss: %i, offset: %i", KPR_CTX_SIZE, sizeof(picokpr_Ctx), offset)); + offset = offset + kpr->rCtxArrLen * KPR_CTX_SIZE; + + kpr->rNetName = &(kpr->rStrArr[kpr_getUInt32(&(this->base[KPR_NETNAME_OFFSET]))]); + + return PICO_OK; +} + + +static pico_status_t kprSubObjDeallocate(register picoknow_KnowledgeBase this, + picoos_MemoryManager mm) +{ + if (NULL != this) { + picoos_deallocate(mm, (void *) &this->subObj); + } + return PICO_OK; +} + + +/* we don't offer a specialized constructor for a PreprocKnowledgeBase but + * instead a "specializer" of an allready existing generic + * picoknow_KnowledgeBase */ + +pico_status_t picokpr_specializePreprocKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common) +{ + if (NULL == this) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + this->subDeallocate = kprSubObjDeallocate; + this->subObj = picoos_allocate(common->mm, sizeof(kpr_subobj_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + return kprInitialize(this, common); +} + +/* ************************************************************/ +/* preproc getPreproc */ +/* ************************************************************/ + +picokpr_Preproc picokpr_getPreproc(picoknow_KnowledgeBase this) +{ + if (NULL == this) { + return NULL; + } else { + return (picokpr_Preproc) this->subObj; + } +} + + +/* *****************************************************************************/ +/* knowledge base access routines for strings in StrArr */ +/* *****************************************************************************/ + +extern picokpr_VarStrPtr picokpr_getVarStrPtr(picokpr_Preproc preproc, picokpr_StrArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rStrArr[ofs]); + + return p; +} + +/* *****************************************************************************/ + +extern picoos_bool picokpr_isEqual (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__9, picokpr_StrArrOffset str2) +{ + picokpr_VarStrPtr lstrp; + len__9 = len__9; /*PP 13.10.08 : fix warning "var not used in this function"*/ + lstrp = (picokpr_VarStrPtr)&((kpr_SubObj)preproc)->rStrArr[str2]; + return picoos_strcmp((picoos_char*)lstrp,(picoos_char*)str) == 0; +} + + + +extern picoos_bool picokpr_isEqualHead (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__10, picokpr_StrArrOffset head) +{ + picokpr_VarStrPtr lstrp; + len__10 = len__10; /*PP 13.10.08 : fix warning "var not used in this function"*/ + lstrp = (picokpr_VarStrPtr)&((kpr_SubObj)preproc)->rStrArr[head]; + return (picoos_strstr((picoos_char*)str, (picoos_char*)lstrp) == (picoos_char*)str); +} + + + +extern picoos_bool picokpr_isEqualMid (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__11, picokpr_StrArrOffset mid) +{ + picokpr_VarStrPtr lstrp; + len__11 = len__11; /*PP 13.10.08 : fix warning "var not used in this function"*/ + lstrp = (picokpr_VarStrPtr)(void *) &((kpr_SubObj)preproc)->rStrArr[mid]; + return (picoos_strstr((picoos_char*)str, (picoos_char*)lstrp) != NULL); +} + + + +extern picoos_bool picokpr_isEqualTail (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__12, picokpr_StrArrOffset tail) +{ + picoos_int32 lstart; + picokpr_VarStrPtr lstrp; + len__12 = len__12; /* avoid warning "var not used in this function"*/ + lstrp = (picokpr_VarStrPtr)&((kpr_SubObj)preproc)->rStrArr[tail]; + lstart = picoos_strlen((picoos_char*)str) - picoos_strlen((picoos_char*)lstrp); + if (lstart >= 0) { + return (picoos_strstr((picoos_char*)&(str[lstart]), (picoos_char*)lstrp) != NULL); + } else { + return FALSE; + } +} + +/* *****************************************************************************/ +/* knowledge base access routines for lexical categories in LexCatArr */ +/* *****************************************************************************/ + +extern picokpr_LexCat picokpr_getLexCat(picokpr_Preproc preproc, picokpr_LexCatArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rLexCatArr[ofs]); + + return p[0] + 256*p[1]; +} + +/* *****************************************************************************/ +/* knowledge base access routines for AttrVal fields in AttrValArr */ +/* *****************************************************************************/ + +extern picoos_int32 picokpr_getAttrValArrInt32(picokpr_Preproc preproc, picokpr_AttrValArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rAttrValArr[ofs]); + picoos_uint32 c = p[KPR_ATTRVAL_INT_OFS] + + 256*p[KPR_ATTRVAL_INT_OFS+1] + + 256*256*p[KPR_ATTRVAL_INT_OFS+2] + + 256*256*256*p[KPR_ATTRVAL_INT_OFS+3]; + + if (c > KPR_MAX_INT32) { + return (c - KPR_MAX_INT32) - 1; + } else { + return (((int)c + (int) -(KPR_MAX_INT32)) - 1); + } +} + +/* *****************************************************************************/ +/* knowledge base access routines for AttrVal fields in AttrValArr */ +/* *****************************************************************************/ + +extern picokpr_OutItemArrOffset picokpr_getOutItemNextOfs(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rOutItemArr[ofs]); + + return p[KPR_OUTITEM_NEXTOFS_OFS+0] + 256*p[KPR_OUTITEM_NEXTOFS_OFS+1]; +} + + +extern picoos_int32 picokpr_getOutItemType(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rOutItemArr[ofs]); + + return p[KPR_OUTITEM_TYPE_OFS+0]; +} + + +extern picokpr_StrArrOffset picokpr_getOutItemStrOfs(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rOutItemArr[ofs]); + + return p[KPR_OUTITEM_STROFS_OFS+0] + + 256*p[KPR_OUTITEM_STROFS_OFS+1] + + 256*256*p[KPR_OUTITEM_STROFS_OFS+2] + + 256*256*256*p[KPR_OUTITEM_STROFS_OFS+3]; +} + + +extern picokpr_VarStrPtr picokpr_getOutItemStr(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rOutItemArr[ofs]); + picoos_uint32 c = p[KPR_OUTITEM_STROFS_OFS+0] + + 256*p[KPR_OUTITEM_STROFS_OFS+1] + + 256*256*p[KPR_OUTITEM_STROFS_OFS+2] + + 256*256*256*p[KPR_OUTITEM_STROFS_OFS+3]; + + return (picoos_uint8 *)&(((kpr_SubObj)preproc)->rStrArr[c]); +} + +extern picoos_int32 picokpr_getOutItemVal(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rOutItemArr[ofs]); + picoos_uint32 c = p[KPR_OUTITEM_VAL_OFS+0] + + 256*p[KPR_OUTITEM_VAL_OFS+1] + + 256*256*p[KPR_OUTITEM_VAL_OFS+2] + + 256*256*256*p[KPR_OUTITEM_VAL_OFS+3]; + + if (c > KPR_MAX_INT32) { + return (c - KPR_MAX_INT32) - 1; + } else { + return (((int)c + (int) -(KPR_MAX_INT32)) - 1); + } +} + + +extern picokpr_OutItemArrOffset picokpr_getOutItemArgOfs(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rOutItemArr[ofs]); + + return p[KPR_OUTITEM_ARGOFS_OFS+0] + + 256*p[KPR_OUTITEM_ARGOFS_OFS+1] + + 256*256*p[KPR_OUTITEM_ARGOFS_OFS+2] + + 256*256*256*p[KPR_OUTITEM_ARGOFS_OFS+3]; +} + + +/* *****************************************************************************/ +/* knowledge base access routines for tokens in TokArr */ +/* *****************************************************************************/ + +extern picokpr_TokSetNP picokpr_getTokSetNP(picokpr_Preproc preproc, picokpr_TokArrOffset ofs) +{ + picoos_uint32 c/*, b*/; + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]) + KPR_TOK_SETNP_OFS; + /*picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]);*/ + picoos_uint32 p0, p1, p2, p3; + + p0 = *(p++); + p1 = *(p++); + p2 = *(p++); + p3 = *p; + + c = p0 + (p1<<8) + (p2<<16) + (p3<<24); + + return c; + + /* + c = p[KPR_TOK_SETNP_OFS+0] + + 256*p[KPR_TOK_SETNP_OFS+1] + + 256*256*p[KPR_TOK_SETNP_OFS+2] + + 256*256*256*p[KPR_TOK_SETNP_OFS+3]; + + b = 0; + i = 0; + while ((i <= 31) && (c > 0)) { + if (c % 2 == 1) { + b |= (1<rTokArr[ofs]);*/ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]) + KPR_TOK_SETWP_OFS; + picoos_uint32 p0, p1, p2, p3; + + p0 = *(p++); + p1 = *(p++); + p2 = *(p++); + p3 = *p; + + c = p0 + (p1<<8) + (p2<<16) + (p3<<24); + return c; + + /* + c = p[KPR_TOK_SETWP_OFS+0] + + 256*p[KPR_TOK_SETWP_OFS+1] + + 256*256*p[KPR_TOK_SETWP_OFS+2] + + 256*256*256*p[KPR_TOK_SETWP_OFS+3]; + + b = 0; + i = 0; + while ((i <= 31) && (c > 0)) { + if (c % 2 == 1) { + b |= (1<rTokArr[ofs]); + + return p[KPR_TOK_NEXTOFS_OFS+0] + 256*p[KPR_TOK_NEXTOFS_OFS+1]; +} + + +extern picokpr_TokArrOffset picokpr_getTokAltLOfs(picokpr_Preproc preproc, picokpr_TokArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]) + KPR_TOK_ALTLOFS_OFS; + picokpr_TokArrOffset c = *p++; + return c + 256**p; + + /*picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]); + + return p[KPR_TOK_ALTLOFS_OFS+0] + 256*p[KPR_TOK_ALTLOFS_OFS+1]; + */ +} + + +extern picokpr_TokArrOffset picokpr_getTokAltROfs(picokpr_Preproc preproc, picokpr_TokArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]) + KPR_TOK_ALTROFS_OFS; + picokpr_TokArrOffset c = *p++; + return c + 256**p; + + /*picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]); + + return p[KPR_TOK_ALTROFS_OFS+0] + 256*p[KPR_TOK_ALTROFS_OFS+1];*/ +} + + +extern picokpr_AttrValArrOffset picokpr_getTokAttribOfs(picokpr_Preproc preproc, picokpr_TokArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rTokArr[ofs]); + + return p[KPR_TOK_ATTRIBOFS_OFS+0] + 256*p[KPR_TOK_ATTRIBOFS_OFS+1]; +} + +/* *****************************************************************************/ +/* knowledge base access routines for productions in ProdArr */ +/* *****************************************************************************/ + +extern picoos_int32 picokpr_getProdArrLen(picokpr_Preproc preproc) +{ + return ((kpr_SubObj)preproc)->rProdArrLen; +} + +extern picoos_int32 picokpr_getProdPrefCost(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rProdArr[ofs]); + picoos_uint32 c = p[KPR_PROD_PRODPREFCOST_OFS+0] + + 256*p[KPR_PROD_PRODPREFCOST_OFS+1] + + 256*256*p[KPR_PROD_PRODPREFCOST_OFS+2] + + 256*256*256*p[KPR_PROD_PRODPREFCOST_OFS+3]; + + + if (c > KPR_MAX_INT32) { + return (c - KPR_MAX_INT32) - 1; + } else { + return (((int)c + (int) -(KPR_MAX_INT32)) - 1); + } +} + + +extern picokpr_StrArrOffset picokpr_getProdNameOfs(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rProdArr[ofs]); + + return p[KPR_PROD_PRODNAMEOFS_OFS+0] + + 256*p[KPR_PROD_PRODNAMEOFS_OFS+1] + + 256*256*p[KPR_PROD_PRODNAMEOFS_OFS+2] + + 256*256*256*p[KPR_PROD_PRODNAMEOFS_OFS+3]; + +} + + +extern picokpr_TokArrOffset picokpr_getProdATokOfs(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rProdArr[ofs]); + + return p[KPR_PROD_ATOKOFS_OFS+0] + 256*p[KPR_PROD_ATOKOFS_OFS+1]; +} + + +extern picokpr_TokArrOffset picokpr_getProdETokOfs(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rProdArr[ofs]); + + return p[KPR_PROD_ETOKOFS_OFS+0] + 256*p[KPR_PROD_ETOKOFS_OFS+1]; +} + +/* *****************************************************************************/ +/* knowledge base access routines for contexts in CtxArr */ +/* *****************************************************************************/ + +extern picoos_int32 picokpr_getCtxArrLen(picokpr_Preproc preproc) +{ + return ((kpr_SubObj)preproc)->rCtxArrLen; +} + +extern picokpr_StrArrOffset picokpr_getCtxCtxNameOfs(picokpr_Preproc preproc, picokpr_CtxArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rCtxArr[ofs]); + + return p[KPR_CTX_CTXNAMEOFS_OFS+0] + + 256*p[KPR_CTX_CTXNAMEOFS_OFS+1] + + 256*256*p[KPR_CTX_CTXNAMEOFS_OFS+2] + + 256*256*256*p[KPR_CTX_CTXNAMEOFS_OFS+3]; +} + + +extern picokpr_StrArrOffset picokpr_getCtxNetNameOfs(picokpr_Preproc preproc, picokpr_CtxArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rCtxArr[ofs]); + + return p[KPR_CTX_NETNAMEOFS_OFS+0] + + 256*p[KPR_CTX_NETNAMEOFS_OFS+1] + + 256*256*p[KPR_CTX_NETNAMEOFS_OFS+2] + + 256*256*256*p[KPR_CTX_NETNAMEOFS_OFS+3]; +} + + +extern picokpr_StrArrOffset picokpr_getCtxProdNameOfs(picokpr_Preproc preproc, picokpr_CtxArrOffset ofs) +{ + picoos_uint8 * p = (picoos_uint8 *)&(((kpr_SubObj)preproc)->rCtxArr[ofs]); + + return p[KPR_CTX_PRODNAMEOFS_OFS+0] + + 256*p[KPR_CTX_PRODNAMEOFS_OFS+1] + + 256*256*p[KPR_CTX_PRODNAMEOFS_OFS+2] + + 256*256*256*p[KPR_CTX_PRODNAMEOFS_OFS+3]; +} + +/* *****************************************************************************/ +/* knowledge base access routines for networks */ +/* *****************************************************************************/ + +extern picokpr_VarStrPtr picokpr_getPreprocNetName(picokpr_Preproc preproc) +{ + return ((kpr_SubObj)preproc)->rNetName; +} + + +#ifdef __cplusplus +} +#endif + + +/* end */ diff --git a/pico/lib/picokpr.h b/pico/lib/picokpr.h new file mode 100644 index 0000000..0532b49 --- /dev/null +++ b/pico/lib/picokpr.h @@ -0,0 +1,147 @@ +/* + * 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 picokpr.h + * + * knowledge handling for text preprocessing + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +/** + * @addtogroup picokpr + + * Knowledge handling for text preprocessing \n + * +*/ + +#ifndef PICOKPR_H_ +#define PICOKPR_H_ + +#include "picoos.h" +#include "picoknow.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* ************************************************************/ +/* function to create specialized kb, */ +/* to be used by picorsrc only */ +/* ************************************************************/ + +pico_status_t picokpr_specializePreprocKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common); + + +/* ************************************************************/ +/* preproc type and getPreproc function */ +/* ************************************************************/ + +/* maximal array length in preproc knowledge */ +#define NPPMaxStrArrLen 100000000 +#define NPPMaxLexCatArrLen 65536 +#define NPPMaxAttrValLen 65536 +#define NPPMaxOutItemArrLen 65536 +#define NPPMaxTokArrLen 65536 +#define NPPMaxProdArrLen 65536 +#define NPPMaxCtxArrLen 65536 + +/* array offset types */ +typedef picoos_uint32 picokpr_StrArrOffset; +typedef picoos_uint16 picokpr_LexCatArrOffset; +typedef picoos_uint16 picokpr_AttrValArrOffset; +typedef picoos_uint16 picokpr_OutItemArrOffset; +typedef picoos_uint16 picokpr_TokArrOffset; +typedef picoos_uint16 picokpr_ProdArrOffset; +typedef picoos_uint16 picokpr_CtxArrOffset; + +typedef picoos_uchar * picokpr_VarStrPtr; + +typedef picoos_int16 picokpr_LexCat; +typedef picoos_uint32 picokpr_TokSetNP; +typedef picoos_uint32 picokpr_TokSetWP; + +/* preproc types */ +typedef struct picokpr_preproc * picokpr_Preproc; + +/* return kb preproc for usage in PU */ +picokpr_Preproc picokpr_getPreproc(picoknow_KnowledgeBase this); + + +/* *****************************************************************************/ +/* access routines */ +/* *****************************************************************************/ + +/* knowledge base access routines for strings in StrArr */ +extern picokpr_VarStrPtr picokpr_getVarStrPtr(picokpr_Preproc preproc, picokpr_StrArrOffset ofs); +extern picoos_bool picokpr_isEqual (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__9, picokpr_StrArrOffset str2); +extern picoos_bool picokpr_isEqualHead (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__10, picokpr_StrArrOffset head); +extern picoos_bool picokpr_isEqualMid (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__11, picokpr_StrArrOffset mid); +extern picoos_bool picokpr_isEqualTail (picokpr_Preproc preproc, picoos_uchar str[], picoos_int32 len__12, picokpr_StrArrOffset tail); + +/* knowledge base access routines for lexical categories in LexCatArr */ +extern picokpr_LexCat picokpr_getLexCat(picokpr_Preproc preproc, picokpr_LexCatArrOffset ofs); + +/* knowledge base access routines for AttrVal fields in AttrValArr */ +extern picoos_int32 picokpr_getAttrValArrInt32(picokpr_Preproc preproc, picokpr_AttrValArrOffset ofs); + +/* knowledge base access routines for out items fields in OutItemArr */ +extern picokpr_StrArrOffset picokpr_getOutItemStrOfs(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs); +extern picokpr_VarStrPtr picokpr_getOutItemStr(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs); +extern picoos_int32 picokpr_getOutItemType(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs); +extern picoos_int32 picokpr_getOutItemVal(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs); +extern picokpr_OutItemArrOffset picokpr_getOutItemArgOfs(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs); +extern picokpr_OutItemArrOffset picokpr_getOutItemNextOfs(picokpr_Preproc preproc, picokpr_OutItemArrOffset ofs); + +/* knowledge base access routines for tokens in TokArr */ +extern picokpr_TokSetNP picokpr_getTokSetNP(picokpr_Preproc preproc, picokpr_TokArrOffset ofs); +extern picokpr_TokSetWP picokpr_getTokSetWP(picokpr_Preproc preproc, picokpr_TokArrOffset ofs); +extern picokpr_TokArrOffset picokpr_getTokNextOfs(picokpr_Preproc preproc, picokpr_TokArrOffset ofs); +extern picokpr_TokArrOffset picokpr_getTokAltLOfs(picokpr_Preproc preproc, picokpr_TokArrOffset ofs); +extern picokpr_TokArrOffset picokpr_getTokAltROfs(picokpr_Preproc preproc, picokpr_TokArrOffset ofs); +extern picokpr_AttrValArrOffset picokpr_getTokAttribOfs(picokpr_Preproc preproc, picokpr_TokArrOffset ofs); + +/* knowledge base access routines for productions in ProdArr */ +extern picoos_int32 picokpr_getProdArrLen(picokpr_Preproc preproc); +extern picoos_int32 picokpr_getProdPrefCost(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs); +extern picokpr_StrArrOffset picokpr_getProdNameOfs(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs); +extern picokpr_TokArrOffset picokpr_getProdATokOfs(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs); +extern picokpr_TokArrOffset picokpr_getProdETokOfs(picokpr_Preproc preproc, picokpr_ProdArrOffset ofs); + +/* knowledge base access routines for contexts in CtxArr */ +extern picoos_int32 picokpr_getCtxArrLen(picokpr_Preproc preproc); +extern picokpr_StrArrOffset picokpr_getCtxCtxNameOfs(picokpr_Preproc preproc, picokpr_CtxArrOffset ofs); +extern picokpr_StrArrOffset picokpr_getCtxNetNameOfs(picokpr_Preproc preproc, picokpr_CtxArrOffset ofs); +extern picokpr_StrArrOffset picokpr_getCtxProdNameOfs(picokpr_Preproc preproc, picokpr_CtxArrOffset ofs); + +/* knowledge base access routines for preprocs */ +extern picokpr_VarStrPtr picokpr_getPreprocNetName(picokpr_Preproc preproc); + +#ifdef __cplusplus +} +#endif + + +#endif /*PICOKPR_H_*/ diff --git a/pico/lib/picoktab.c b/pico/lib/picoktab.c new file mode 100644 index 0000000..ca8b470 --- /dev/null +++ b/pico/lib/picoktab.c @@ -0,0 +1,1118 @@ +/* + * 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 picoktab.c + * + * symbol tables needed at runtime + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#include "picoos.h" +#include "picodbg.h" +#include "picoknow.h" +#include "picobase.h" +#include "picoktab.h" +#include "picodata.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/** @todo : the following would be better part of a knowledge base. + * Make sure it is consistent with the phoneme symbol table used in the lingware */ + +/* PLANE_PHONEMES */ + +/* PLANE_POS */ + +/* PLANE_PB_STRENGTHS */ + +/* PLANE_ACCENTS */ + +/* PLANE_INTERN */ +#define PICOKTAB_TMPID_PHONSTART '\x26' /* 38 '&' */ +#define PICOKTAB_TMPID_PHONTERM '\x23' /* 35 '#' */ + + +/* ************************************************************/ +/* fixed ids */ +/* ************************************************************/ + + +static pico_status_t ktabIdsInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) +{ + picoktab_FixedIds ids; + + PICODBG_DEBUG(("start")); + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + ids = (picoktab_FixedIds) this->subObj; + + ids->phonStartId = PICOKTAB_TMPID_PHONSTART; + ids->phonTermId = PICOKTAB_TMPID_PHONTERM; + return PICO_OK; +} + + +static pico_status_t ktabIdsSubObjDeallocate(register picoknow_KnowledgeBase this, + picoos_MemoryManager mm) +{ + if (NULL != this) { + picoos_deallocate(mm, (void *) &this->subObj); + } + return PICO_OK; +} + +pico_status_t picoktab_specializeIdsKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common) +{ + if (NULL == this) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + this->subDeallocate = ktabIdsSubObjDeallocate; + this->subObj = picoos_allocate(common->mm, sizeof(picoktab_fixed_ids_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + return ktabIdsInitialize(this, common); +} + +picoktab_FixedIds picoktab_getFixedIds(picoknow_KnowledgeBase this) +{ + return ((NULL == this) ? NULL : ((picoktab_FixedIds) this->subObj)); +} + + +picoktab_FixedIds picoktab_newFixedIds(picoos_MemoryManager mm) +{ + picoktab_FixedIds this = (picoktab_FixedIds) picoos_allocate(mm,sizeof(*this)); + if (NULL != this) { + /* initialize */ + } + return this; +} + + +void picoktab_disposeFixedIds(picoos_MemoryManager mm, picoktab_FixedIds * this) +{ + if (NULL != (*this)) { + /* terminate */ + picoos_deallocate(mm,(void *)this); + } +} + + + +/* ************************************************************/ +/* Graphs */ +/* ************************************************************/ + +/* overview binary file format for graphs kb: + + graphs-kb = NROFSENTRIES SIZEOFSENTRY ofstable graphs + + NROFSENTRIES : 2 bytes, number of entries in offset table + SIZEOFSENTRY : 1 byte, size of one entry in offset table + + ofstable = {OFFSET}=NROFSENTRIES (contains NROFSENTRIES entries of OFFSET) + + OFFSET: SIZEOFSENTRY bytes, offset to baseaddress of graphs-kb to entry in graphs + + graphs = {graph}=NROFSENTRIES (contains NROFSENTRIES entries of graph) + + graph = PROPSET FROM TO [TOKENTYPE] [TOKENSUBTYPE] [VALUE] [LOWERCASE] [GRAPHSUBS1] [GRAPHSUBS2] + + FROM : 1..4 unsigned bytes, UTF8 character without terminating 0 + TO : 1..4 unsigned bytes, UTF8 character without terminating 0 + PROPSET : 1 unsigned byte, least significant bit : has TO field + next bit : has TOKENTYPE + next bit : has TOKENSUBTYPE + next bit : has VALUE + next bit : has LOWERCASE + next bit : has GRAPHSUBS1 + next bit : has GRAPHSUBS2 + next bit : has PUNC + + TOKENTYPE : 1 unsigned byte + TOKENSUBTYPE : 1 unsigned byte + VALUE : 1 unsigned byte + LOWERCASE : 1..4 unsigned bytes, UTF8 character without terminating 0 + GRAPHSUBS1 : 1..4 unsigned bytes, UTF8 character without terminating 0 + GRAPHSUBS2 : 1..4 unsigned bytes, UTF8 character without terminating 0 + PUNC : 1 unsigned byte +*/ + +static picoos_uint32 ktab_propOffset (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uint32 prop); + +#define KTAB_START_GRAPHS_NR_OFFSET 0 +#define KTAB_START_GRAPHS_SIZE_OFFSET 2 +#define KTAB_START_GRAPHS_OFFSET_TABLE 3 +#define KTAB_START_GRAPHS_GRAPH_TABLE 0 + +/* bitmasks to extract the grapheme properties info from the property set */ +#define KTAB_GRAPH_PROPSET_TO ((picoos_uint8)'\x01') +#define KTAB_GRAPH_PROPSET_TOKENTYPE ((picoos_uint8)'\x02') +#define KTAB_GRAPH_PROPSET_TOKENSUBTYPE ((picoos_uint8)'\x04') +#define KTAB_GRAPH_PROPSET_VALUE ((picoos_uint8)'\x08') +#define KTAB_GRAPH_PROPSET_LOWERCASE ((picoos_uint8)'\x010') +#define KTAB_GRAPH_PROPSET_GRAPHSUBS1 ((picoos_uint8)'\x020') +#define KTAB_GRAPH_PROPSET_GRAPHSUBS2 ((picoos_uint8)'\x040') +#define KTAB_GRAPH_PROPSET_PUNCT ((picoos_uint8)'\x080') + + +typedef struct ktabgraphs_subobj *ktabgraphs_SubObj; + +typedef struct ktabgraphs_subobj { + picoos_uint16 nrOffset; + picoos_uint16 sizeOffset; + + picoos_uint8 * offsetTable; + picoos_uint8 * graphTable; +} ktabgraphs_subobj_t; + + + +static pico_status_t ktabGraphsInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) { + ktabgraphs_subobj_t * ktabgraphs; + + PICODBG_DEBUG(("start")); + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + ktabgraphs = (ktabgraphs_subobj_t *) this->subObj; + ktabgraphs->nrOffset = ((int)(this->base[KTAB_START_GRAPHS_NR_OFFSET])) + 256*(int)(this->base[KTAB_START_GRAPHS_NR_OFFSET+1]); + ktabgraphs->sizeOffset = (int)(this->base[KTAB_START_GRAPHS_SIZE_OFFSET]); + ktabgraphs->offsetTable = &(this->base[KTAB_START_GRAPHS_OFFSET_TABLE]); + ktabgraphs->graphTable = &(this->base[KTAB_START_GRAPHS_GRAPH_TABLE]); + return PICO_OK; +} + +static pico_status_t ktabGraphsSubObjDeallocate(register picoknow_KnowledgeBase this, + picoos_MemoryManager mm) { + if (NULL != this) { + picoos_deallocate(mm, (void *) &this->subObj); + } + return PICO_OK; +} + + +pico_status_t picoktab_specializeGraphsKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common) { + if (NULL == this) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + this->subDeallocate = ktabGraphsSubObjDeallocate; + this->subObj = picoos_allocate(common->mm, sizeof(ktabgraphs_subobj_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + return ktabGraphsInitialize(this, common); +} + + +picoktab_Graphs picoktab_getGraphs(picoknow_KnowledgeBase this) { + if (NULL == this) { + return NULL; + } else { + return (picoktab_Graphs) this->subObj; + } +} + + +/* Graphs methods */ + +picoos_uint8 picoktab_hasVowellikeProp(const picoktab_Graphs this, + const picoos_uint8 *graph, + const picoos_uint8 graphlenmax) { + + picoos_uint8 ui8App; + picoos_uint32 graphsOffset; + ktabgraphs_subobj_t * g = (ktabgraphs_SubObj)this; + + ui8App = graphlenmax; /* avoid warning "var not used in this function"*/ + + graphsOffset = picoktab_graphOffset (this, (picoos_uchar *)graph); + return g->graphTable[graphsOffset + ktab_propOffset (this, graphsOffset, KTAB_GRAPH_PROPSET_TOKENTYPE)] == PICODATA_ITEMINFO1_TOKTYPE_LETTERV; +} + + +static void ktab_getStrProp (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uint32 propOffset, picoos_uchar * str) +{ + ktabgraphs_subobj_t * g = (ktabgraphs_SubObj)this; + picoos_uint32 i, l; + + i = 0; + l = picobase_det_utf8_length(g->graphTable[graphsOffset+propOffset]); + while (igraphTable[graphsOffset+propOffset+i]; + i++; + } + str[l] = 0; +} + + +static picoos_uint32 ktab_propOffset(const picoktab_Graphs this, + picoos_uint32 graphsOffset, picoos_uint32 prop) +/* Returns offset of property 'prop' inside the graph with offset 'graphsOffset' in graphs table; + If the property is found, a value > 0 is returned otherwise 0 */ +{ + picoos_uint32 n = 0; + ktabgraphs_subobj_t * g = (ktabgraphs_SubObj) this; + + if ((g->graphTable[graphsOffset] & prop) == prop) { + n = n + 1; /* overread PROPSET field */ + n = n + picobase_det_utf8_length(g->graphTable[graphsOffset+n]); /* overread FROM field */ + if (prop > KTAB_GRAPH_PROPSET_TO) { + if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_TO) + == KTAB_GRAPH_PROPSET_TO) { + n = n + picobase_det_utf8_length(g->graphTable[graphsOffset+n]); /* overread TO field */ + } + } else { + return n; + } + if (prop > KTAB_GRAPH_PROPSET_TOKENTYPE) { + if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_TOKENTYPE) + == KTAB_GRAPH_PROPSET_TOKENTYPE) { + n = n + 1; /* overread TOKENTYPE field */ + } + } else { + return n; + } + if (prop > KTAB_GRAPH_PROPSET_TOKENSUBTYPE) { + if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_TOKENSUBTYPE) + == KTAB_GRAPH_PROPSET_TOKENSUBTYPE) { + n = n + 1; /* overread stokentype field */ + } + } else { + return n; + } + if (prop > KTAB_GRAPH_PROPSET_VALUE) { + if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_VALUE) + == KTAB_GRAPH_PROPSET_VALUE) { + n = n + 1; /* overread value field */ + } + } else { + return n; + } + if (prop > KTAB_GRAPH_PROPSET_LOWERCASE) { + if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_LOWERCASE) + == KTAB_GRAPH_PROPSET_LOWERCASE) { + n = n + picobase_det_utf8_length(g->graphTable[graphsOffset+n]); /* overread lowercase field */ + } + } else { + return n; + } + if (prop > KTAB_GRAPH_PROPSET_GRAPHSUBS1) { + if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_GRAPHSUBS1) + == KTAB_GRAPH_PROPSET_GRAPHSUBS1) { + n = n + picobase_det_utf8_length(g->graphTable[graphsOffset+n]); /* overread graphsubs1 field */ + } + } else { + return n; + } + if (prop > KTAB_GRAPH_PROPSET_GRAPHSUBS2) { + if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_GRAPHSUBS2) + == KTAB_GRAPH_PROPSET_GRAPHSUBS2) { + n = n + picobase_det_utf8_length(g->graphTable[graphsOffset+n]); /* overread graphsubs2 field */ + } + } else { + return n; + } + if (prop > KTAB_GRAPH_PROPSET_PUNCT) { + if ((g->graphTable[graphsOffset] & KTAB_GRAPH_PROPSET_PUNCT) + == KTAB_GRAPH_PROPSET_PUNCT) { + n = n + 1; /* overread value field */ + } + } else { + return n; + } + } + + return n; +} + + +picoos_uint32 picoktab_graphOffset (const picoktab_Graphs this, picoos_uchar * utf8graph) +{ ktabgraphs_subobj_t * g = (ktabgraphs_SubObj)this; + picoos_int32 a, b, m; + picoos_uint32 graphsOffset; + picoos_uint32 propOffset; + picobase_utf8char from; + picobase_utf8char to; + picoos_bool utfGEfrom; + picoos_bool utfLEto; + + if (g->nrOffset > 0) { + a = 0; + b = g->nrOffset-1; + do { + m = (a+b) / 2; + + /* get offset to graph[m] */ + if (g->sizeOffset == 1) { + graphsOffset = g->offsetTable[g->sizeOffset*m]; + } + else { + graphsOffset = g->offsetTable[g->sizeOffset*m ] + + 256*g->offsetTable[g->sizeOffset*m + 1]; + /* PICODBG_DEBUG(("picoktab_graphOffset: %i %i %i %i", m, g->offsetTable[g->sizeOffset*m], g->offsetTable[g->sizeOffset*m + 1], graphsOffset)); + */ + } + + /* get FROM and TO field of graph[m] */ + ktab_getStrProp(this, graphsOffset, 1, from); + propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_TO); + if (propOffset > 0) { + ktab_getStrProp(this, graphsOffset, propOffset, to); + } + else { + picoos_strcpy((picoos_char *)to, (picoos_char *)from); + } + + /* PICODBG_DEBUG(("picoktab_graphOffset: %i %i %i '%s' '%s' '%s'", a, m, b, from, utf8graph, to)); + */ + utfGEfrom = picoos_strcmp((picoos_char *)utf8graph, (picoos_char *)from) >= 0; + utfLEto = picoos_strcmp((picoos_char *)utf8graph, (picoos_char *)to) <= 0; + + if (utfGEfrom && utfLEto) { + /* PICODBG_DEBUG(("picoktab_graphOffset: utf char '%s' found", utf8graph)); + */ + return graphsOffset; + } + if (!utfGEfrom) { + b = m-1; + } + else if (!utfLEto) { + a = m+1; + } + } while (a<=b); + } + PICODBG_DEBUG(("picoktab_graphOffset: utf char '%s' not found", utf8graph)); + return 0; +} + + + + +picoos_bool picoktab_getIntPropTokenType (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uint8 * stokenType) +{ + picoos_uint32 propOffset; + ktabgraphs_subobj_t * g = (ktabgraphs_SubObj)this; + + propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_TOKENTYPE); + if (propOffset > 0) { + *stokenType = (picoos_uint8)(g->graphTable[graphsOffset+propOffset]); + return TRUE; + } + else { + return FALSE; + } +} + + +picoos_bool picoktab_getIntPropTokenSubType (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_int8 * stokenSubType) +{ + picoos_uint32 propOffset; + ktabgraphs_subobj_t * g = (ktabgraphs_SubObj)this; + + propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_TOKENSUBTYPE); + if (propOffset > 0) { + *stokenSubType = (picoos_int8)(g->graphTable[graphsOffset+propOffset]); + return TRUE; + } + else { + return FALSE; + } +} + +picoos_bool picoktab_getIntPropValue (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uint32 * value) +{ + picoos_uint32 propOffset; + ktabgraphs_subobj_t * g = (ktabgraphs_SubObj)this; + + propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_VALUE); + if (propOffset > 0) { + *value = (picoos_uint32)(g->graphTable[graphsOffset+propOffset]); + return TRUE; + } + else { + return FALSE; + } +} + + +picoos_bool picoktab_getIntPropPunct (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uint8 * info1, picoos_uint8 * info2) +{ + picoos_uint32 propOffset; + ktabgraphs_subobj_t * g = (ktabgraphs_SubObj)this; + + propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_PUNCT); + if (propOffset > 0) { + if (g->graphTable[graphsOffset+propOffset] == 2) { + *info1 = PICODATA_ITEMINFO1_PUNC_SENTEND; + } + else { + *info1 = PICODATA_ITEMINFO1_PUNC_PHRASEEND; + } + if (g->graphTable[graphsOffset+1] == '.') { + *info2 = PICODATA_ITEMINFO2_PUNC_SENT_T; + } + else if (g->graphTable[graphsOffset+1] == '?') { + *info2 = PICODATA_ITEMINFO2_PUNC_SENT_Q; + } + else if (g->graphTable[graphsOffset+1] == '!') { + *info2 = PICODATA_ITEMINFO2_PUNC_SENT_E; + } + else { + *info2 = PICODATA_ITEMINFO2_PUNC_PHRASE; + } + return TRUE; + } + else { + return FALSE; + } +} + + +picoos_bool picoktab_getStrPropLowercase (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uchar * lowercase) +{ + picoos_uint32 propOffset; + + propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_LOWERCASE); + if (propOffset > 0) { + ktab_getStrProp(this, graphsOffset, propOffset, lowercase); + return TRUE; + } + else { + return FALSE; + } +} + + +picoos_bool picoktab_getStrPropGraphsubs1 (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uchar * graphsubs1) +{ + picoos_uint32 propOffset; + + propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_GRAPHSUBS1); + if (propOffset > 0) { + ktab_getStrProp(this, graphsOffset, propOffset, graphsubs1); + return TRUE; + } + else { + return FALSE; + } +} + + +picoos_bool picoktab_getStrPropGraphsubs2 (const picoktab_Graphs this, picoos_uint32 graphsOffset, picoos_uchar * graphsubs2) +{ + picoos_uint32 propOffset; + + propOffset = ktab_propOffset(this, graphsOffset, KTAB_GRAPH_PROPSET_GRAPHSUBS2); + if (propOffset > 0) { + ktab_getStrProp(this, graphsOffset, propOffset, graphsubs2); + return TRUE; + } + else { + return FALSE; + } +} +/* *****************************************************************/ +/* used for tools */ + +static void ktab_getUtf8 (picoos_uchar ** pos, picoos_uchar * to) +{ + picoos_uint32 l; + l = picobase_det_utf8_length(**pos); + while (l>0) { + *(to++) = *((*pos)++); + l--; + } + *to = 0; +} + +picoos_uint16 picoktab_graphsGetNumEntries(const picoktab_Graphs this) +{ + ktabgraphs_subobj_t * g = (ktabgraphs_SubObj) this; + return g->nrOffset; +} + +void picoktab_graphsGetGraphInfo(const picoktab_Graphs this, + picoos_uint16 graphIndex, picoos_uchar * from, picoos_uchar * to, + picoos_uint8 * propset, + picoos_uint8 * stokenType, picoos_uint8 * stokenSubType, + picoos_uint8 * value, picoos_uchar * lowercase, + picoos_uchar * graphsubs1, picoos_uchar * graphsubs2, + picoos_uint8 * punct) { + ktabgraphs_subobj_t * g = (ktabgraphs_SubObj) this; + picoos_uint32 graphsOffset; + picoos_uint8 * pos; + + /* calculate offset of graph[graphIndex] */ + if (g->sizeOffset == 1) { + graphsOffset = g->offsetTable[graphIndex]; + } else { + graphsOffset = g->offsetTable[2 * graphIndex] + + (g->offsetTable[2 * graphIndex + 1] << 8); + } + pos = &(g->graphTable[graphsOffset]); + *propset = *pos; + + pos++; /* advance to FROM */ + ktab_getUtf8(&pos, from); /* get FROM and advance */ + if ((*propset) & KTAB_GRAPH_PROPSET_TO) { + ktab_getUtf8(&pos, to); /* get TO and advance */ + } else { + picoos_strcpy((picoos_char *)to, (picoos_char *)from); + } + if ((*propset) & KTAB_GRAPH_PROPSET_TOKENTYPE) { + (*stokenType) = *(pos++); /* get TOKENTYPE and advance */ + } else { + (*stokenType) = -1; + } + if ((*propset) & KTAB_GRAPH_PROPSET_TOKENSUBTYPE) { + (*stokenSubType) = *(pos++); /* get TOKENSUBTYPE and advance */ + } else { + (*stokenSubType) = -1; + } + if ((*propset) & KTAB_GRAPH_PROPSET_VALUE) { + (*value) = *(pos++); /* get VALUE and advance */ + } else { + (*value) = -1; + } + if ((*propset) & KTAB_GRAPH_PROPSET_LOWERCASE) { + ktab_getUtf8(&pos, lowercase); /* get LOWERCASE and advance */ + } else { + lowercase[0] = NULLC; + } + if ((*propset) & KTAB_GRAPH_PROPSET_GRAPHSUBS1) { + ktab_getUtf8(&pos, graphsubs1); /* get GRAPHSUBS1 and advance */ + } else { + graphsubs1[0] = NULLC; + } + if ((*propset) & KTAB_GRAPH_PROPSET_GRAPHSUBS2) { + ktab_getUtf8(&pos, graphsubs2); /* get GRAPHSUBS2 and advance */ + } else { + graphsubs2[0] = NULLC; + } + if ((*propset) & KTAB_GRAPH_PROPSET_PUNCT) { + (*punct) = *(pos++); /* get PUNCT and advance */ + } else { + (*punct) = -1; + } +} + +/* ************************************************************/ +/* Phones */ +/* ************************************************************/ + +/* overview binary file format for phones kb: + + phones-kb = specids propertytable + + specids = PRIMSTRESSID1 SECSTRESSID1 SYLLBOUNDID1 PAUSEID1 WORDBOUNDID1 + RESERVE1 RESERVE1 RESERVE1 + + propertytable = {PHONEPROP2}=256 + + PRIMSTRESSID1: one byte, ID of primary stress + SECSTRESSID1: one byte, ID of secondary stress + SYLLBOUNDID1: one byte, ID of syllable boundary + PAUSEID1: one byte, ID of pause + RESERVE1: reserved for future use + + PHONEPROP2: one byte, max. of 256 phones directly access this table + to check a property for a phone; binary properties + encoded (1 bit per prop) + least significant bit: vowel + next bit: diphth + next bit: glott + next bit: nonsyllvowel + next bit: syllcons + 3 bits spare + */ + +#define KTAB_START_SPECIDS 0 +#define KTAB_IND_PRIMSTRESS 0 +#define KTAB_IND_SECSTRESS 1 +#define KTAB_IND_SYLLBOUND 2 +#define KTAB_IND_PAUSE 3 +#define KTAB_IND_WORDBOUND 4 + +#define KTAB_START_PROPS 8 + + +typedef struct ktabphones_subobj *ktabphones_SubObj; + +typedef struct ktabphones_subobj { + picoos_uint8 *specids; + picoos_uint8 *props; +} ktabphones_subobj_t; + + +/* bitmasks to extract the property info from props */ +#define KTAB_PPROP_VOWEL '\x01' +#define KTAB_PPROP_DIPHTH '\x02' +#define KTAB_PPROP_GLOTT '\x04' +#define KTAB_PPROP_NONSYLLVOWEL '\x08' +#define KTAB_PPROP_SYLLCONS '\x10' + + +static pico_status_t ktabPhonesInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) { + ktabphones_subobj_t * ktabphones; + + PICODBG_DEBUG(("start")); + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + ktabphones = (ktabphones_subobj_t *) this->subObj; + ktabphones->specids = &(this->base[KTAB_START_SPECIDS]); + ktabphones->props = &(this->base[KTAB_START_PROPS]); + return PICO_OK; +} + +static pico_status_t ktabPhonesSubObjDeallocate(register picoknow_KnowledgeBase this, + picoos_MemoryManager mm) { + if (NULL != this) { + picoos_deallocate(mm, (void *) &this->subObj); + } + return PICO_OK; +} + +pico_status_t picoktab_specializePhonesKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common) { + if (NULL == this) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + this->subDeallocate = ktabPhonesSubObjDeallocate; + this->subObj = picoos_allocate(common->mm, sizeof(ktabphones_subobj_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + return ktabPhonesInitialize(this, common); +} + +picoktab_Phones picoktab_getPhones(picoknow_KnowledgeBase this) { + if (NULL == this) { + return NULL; + } else { + return (picoktab_Phones) this->subObj; + } +} + + +/* Phones methods */ + +picoos_uint8 picoktab_hasVowelProp(const picoktab_Phones this, + const picoos_uint8 ch) { + return (KTAB_PPROP_VOWEL & ((ktabphones_SubObj)this)->props[ch]); +} +picoos_uint8 picoktab_hasDiphthProp(const picoktab_Phones this, + const picoos_uint8 ch) { + return (KTAB_PPROP_DIPHTH & ((ktabphones_SubObj)this)->props[ch]); +} +picoos_uint8 picoktab_hasGlottProp(const picoktab_Phones this, + const picoos_uint8 ch) { + return (KTAB_PPROP_GLOTT & ((ktabphones_SubObj)this)->props[ch]); +} +picoos_uint8 picoktab_hasNonsyllvowelProp(const picoktab_Phones this, + const picoos_uint8 ch) { + return (KTAB_PPROP_NONSYLLVOWEL & ((ktabphones_SubObj)this)->props[ch]); +} +picoos_uint8 picoktab_hasSyllconsProp(const picoktab_Phones this, + const picoos_uint8 ch) { + return (KTAB_PPROP_SYLLCONS & ((ktabphones_SubObj)this)->props[ch]); +} + +picoos_bool picoktab_isSyllCarrier(const picoktab_Phones this, + const picoos_uint8 ch) { + picoos_uint8 props; + props = ((ktabphones_SubObj)this)->props[ch]; + return (((KTAB_PPROP_VOWEL & props) && + !(KTAB_PPROP_NONSYLLVOWEL & props)) + || (KTAB_PPROP_SYLLCONS & props)); +} + +picoos_bool picoktab_isPrimstress(const picoktab_Phones this, + const picoos_uint8 ch) { + return (ch == ((ktabphones_SubObj)this)->specids[KTAB_IND_PRIMSTRESS]); +} +picoos_bool picoktab_isSecstress(const picoktab_Phones this, + const picoos_uint8 ch) { + return (ch == ((ktabphones_SubObj)this)->specids[KTAB_IND_SECSTRESS]); +} +picoos_bool picoktab_isSyllbound(const picoktab_Phones this, + const picoos_uint8 ch) { + return (ch == ((ktabphones_SubObj)this)->specids[KTAB_IND_SYLLBOUND]); +} +picoos_bool picoktab_isWordbound(const picoktab_Phones this, + const picoos_uint8 ch) { + return (ch == ((ktabphones_SubObj)this)->specids[KTAB_IND_WORDBOUND]); +} +picoos_bool picoktab_isPause(const picoktab_Phones this, + const picoos_uint8 ch) { + return (ch == ((ktabphones_SubObj)this)->specids[KTAB_IND_PAUSE]); +} + +picoos_uint8 picoktab_getPrimstressID(const picoktab_Phones this) { + return ((ktabphones_SubObj)this)->specids[KTAB_IND_PRIMSTRESS]; +} +picoos_uint8 picoktab_getSecstressID(const picoktab_Phones this) { + return ((ktabphones_SubObj)this)->specids[KTAB_IND_SECSTRESS]; +} +picoos_uint8 picoktab_getSyllboundID(const picoktab_Phones this) { + return ((ktabphones_SubObj)this)->specids[KTAB_IND_SYLLBOUND]; +} +picoos_uint8 picoktab_getWordboundID(const picoktab_Phones this) { + return ((ktabphones_SubObj)this)->specids[KTAB_IND_WORDBOUND]; +} +picoos_uint8 picoktab_getPauseID(const picoktab_Phones this) { + return ((ktabphones_SubObj)this)->specids[KTAB_IND_PAUSE]; +} + +/* ************************************************************/ +/* Pos */ +/* ************************************************************/ + +/* overview binary file format for pos kb: + + pos-kb = header posids + header = {COUNT2 OFFS2}=8 + posids = {POSID1 {PARTID1}0:8}1: + + where POSID1 is the value of the (combined) part-of-speech symbol, + and {PARTID1} are the symbol values of its components (empty if it + is not a combined symbol). The {PARTID1} list is sorted. + Part-of-speech symbols with equal number of components are grouped + together. + + The header contains information about these groups: + + COUNT2 specifies the number of elements in the group, and OFFS2 + specifies the offset (relative to the beginning of the kb) where + the group data starts, i.e.: + + 25 32 -> 25 not-combined elements, starting at offset 32 + 44 57 -> 44 elements composed of 2 symbols, starting at offset 57 + 23 189 -> 23 elements composed of 3 symbols, starting at offset 189 + ... + + Currently, each symbol may be composed of up to 8 other symbols. + Therefore, the header has 8 entries, too. The header starts with + the unique POS list, and then in increasing order, 2 symbols, 3 + symbols,... + +Zur Anschauung die ge-printf-te Version: + + 25 32 + 44 57 + 23 189 + 12 281 + 4 341 + 1 365 + 0 0 + 0 0 + 33 | + 34 | + 35 | + 60 | + etc. + 36 | 35 60 + 50 | 35 95 + 51 | 35 97 + 58 | 35 120 + 59 | 35 131 + 61 | 60 75 + 63 | 60 95 + 64 | 60 97 + etc. + 42 | 35 60 117 + 44 | 35 60 131 + 45 | 35 73 97 + 48 | 35 84 97 + 54 | 35 97 131 + 56 | 35 113 120 + 57 | 35 117 120 + 62 | 60 84 122 + etc. + */ + +typedef struct ktabpos_subobj *ktabpos_SubObj; + +typedef struct ktabpos_subobj { + picoos_uint16 nrcomb[PICOKTAB_MAXNRPOS_IN_COMB]; + picoos_uint8 *nrcombstart[PICOKTAB_MAXNRPOS_IN_COMB]; +} ktabpos_subobj_t; + + +static pico_status_t ktabPosInitialize(register picoknow_KnowledgeBase this, + picoos_Common common) { + ktabpos_subobj_t *ktabpos; + picoos_uint16 osprev; + picoos_uint16 os, pos; + picoos_uint8 i; + + PICODBG_DEBUG(("start")); + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + ktabpos = (ktabpos_subobj_t *)this->subObj; + + os = 0; + for (i = 0, pos = 0; i < PICOKTAB_MAXNRPOS_IN_COMB; i++, pos += 4) { + ktabpos->nrcomb[i] = ((picoos_uint16)(this->base[pos+1])) << 8 | + this->base[pos]; + if (ktabpos->nrcomb[i] > 0) { + osprev = os; + os = ((picoos_uint16)(this->base[pos+3])) << 8 | this->base[pos+2]; + ktabpos->nrcombstart[i] = &(this->base[os]); + PICODBG_TRACE(("i %d, pos %d, nr %d, osprev %d, os %d", i, pos, + ktabpos->nrcomb[i], osprev, os)); + if (osprev >= os) { + /* cannot be, in a valid kb */ + return picoos_emRaiseException(common->em, + PICO_EXC_FILE_CORRUPT, + NULL, NULL); + } + } else { + if (i == 0) { + /* cannot be, in a valid kb */ + return picoos_emRaiseException(common->em, + PICO_EXC_FILE_CORRUPT, + NULL, NULL); + } + ktabpos->nrcombstart[i] = NULL; + } + } + return PICO_OK; +} + +static pico_status_t ktabPosSubObjDeallocate(register picoknow_KnowledgeBase this, + picoos_MemoryManager mm) { + if (NULL != this) { + picoos_deallocate(mm, (void *) &this->subObj); + } + return PICO_OK; +} + +pico_status_t picoktab_specializePosKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common) { + if (NULL == this) { + return picoos_emRaiseException(common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + this->subDeallocate = ktabPosSubObjDeallocate; + this->subObj = picoos_allocate(common->mm, sizeof(ktabpos_subobj_t)); + if (NULL == this->subObj) { + return picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, + NULL, NULL); + } + return ktabPosInitialize(this, common); +} + +picoktab_Pos picoktab_getPos(picoknow_KnowledgeBase this) { + if (NULL == this) { + return NULL; + } else { + return (picoktab_Pos) this->subObj; + } +} + + +/* Pos methods */ + +static picoos_int16 ktab_isEqualPosGroup(const picoos_uint8 *grp1, + const picoos_uint8 *grp2, + picoos_uint8 len) +{ + /* if both, grp1 and grp2 would be sorted in ascending order + we could implement a function picoktab_comparePosGroup in + a similar manner as strcmp */ + + picoos_uint16 i, j, equal; + + equal = 1; + + i = 0; + while (equal && (i < len)) { + /* search grp1[i] in grp2 */ + j = 0; + while ((j < len) && (grp1[i] != grp2[j])) { + j++; + } + equal = (j < len); + i++; + } + + return equal; +} + + +picoos_bool picoktab_isUniquePos(const picoktab_Pos this, + const picoos_uint8 pos) { + ktabpos_subobj_t *ktabpos; + picoos_uint16 i; + + /* speed-up possible with e.g. binary search */ + + ktabpos = (ktabpos_subobj_t *)this; + PICODBG_TRACE(("pos %d, nrcombinations %d", pos, ktabpos->nrcomb[0])); + i = 0; + while ((i < ktabpos->nrcomb[0]) && (pos > ktabpos->nrcombstart[0][i])) { + PICODBG_TRACE(("compare with pos %d at position %d", + ktabpos->nrcombstart[0][i], pos, i)); + i++; + } + return ((i < ktabpos->nrcomb[0]) && (pos == ktabpos->nrcombstart[0][i])); +} + + +picoos_bool picoktab_isPartOfPosGroup(const picoktab_Pos this, + const picoos_uint8 pos, + const picoos_uint8 posgroup) +{ + ktabpos_subobj_t *ktabpos; + picoos_uint8 *grp; + picoos_uint16 i, j, n, s, grplen; + picoos_uint8 *e; + picoos_uint8 found; + + ktabpos = (ktabpos_subobj_t *) this; + + grp = NULL; + found = FALSE; + grplen = 0; + + /* currently, a linear search is required to find 'posgroup'; the + knowledge base should be extended to allow for a faster search */ + + /* treat case i==0, grplen==0, ie. pos == posgroup */ + if (pos == posgroup) { + found = TRUE; + } + + i = 1; + while ((grp == NULL) && (i < PICOKTAB_MAXNRPOS_IN_COMB)) { + n = ktabpos->nrcomb[i]; /* number of entries */ + e = ktabpos->nrcombstart[i]; /* ptr to first entry */ + s = i + 2; /* size of an entry in bytes */ + /* was with while starting at 0: + s = i > 0 ? i + 2 : 1; + */ + j = 0; + while ((grp == NULL) && (j < n)) { + if (posgroup == e[0]) { + grp = e + 1; + grplen = s - 1; + } + e += s; + j++; + } + i++; + } + + /* test if 'pos' is contained in the components of 'posgroup' */ + if (grp != NULL) { + for (i = 0; !found && (i < grplen); i++) { + if (pos == grp[i]) { + found = TRUE; + } + } + + /* just a way to test picoktab_getPosGroup */ + /* + PICODBG_ASSERT(picoktab_getPosGroup(this, grp, grplen) == posgroup); + */ + } + + return found; +} + + +picoos_uint8 picoktab_getPosGroup(const picoktab_Pos this, + const picoos_uint8 *poslist, + const picoos_uint8 poslistlen) +{ + picoos_uint8 poscomb; + ktabpos_subobj_t *ktabpos; + picoos_uint16 i, j, n, s; + picoos_uint8 *e; + + ktabpos = (ktabpos_subobj_t *) this; + poscomb = 0; + + if ((poslistlen > 0) && (poslistlen <= PICOKTAB_MAXNRPOS_IN_COMB)) { + i = poslistlen - 1; + if (i > 0) { + n = ktabpos->nrcomb[i]; /* number of entries */ + e = ktabpos->nrcombstart[i]; /* ptr to first entry */ + s = i + 2; /* size of an entry in bytes */ + j = 0; + while (!poscomb && (j < n)) { + if (ktab_isEqualPosGroup(poslist, e + 1, poslistlen)) { + poscomb = *e; + } + e += s; + j++; + } + if (!poscomb) { + /* combination not found; shouldn't occur if lingware OK! */ + /* contingency solution: take first */ + PICODBG_WARN(("dynamically created POS combination not found in table; taking first (%i)",poslist[0])); + poscomb = poslist[0]; + } + } else { /* not a composed POS */ + poscomb = poslist[0]; + } + } + + return poscomb; +} + +#ifdef __cplusplus +} +#endif + + +/* end */ diff --git a/pico/lib/picoktab.h b/pico/lib/picoktab.h new file mode 100644 index 0000000..71ba2ab --- /dev/null +++ b/pico/lib/picoktab.h @@ -0,0 +1,224 @@ +/* + * 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 picoktab.h + * + * symbol tables needed at runtime + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +/** + * @addtogroup picoktab + + * Symbol tables needed at runtime \n + * +*/ + +#ifndef PICOKTAB_H_ +#define PICOKTAB_H_ + +#include "picoos.h" +#include "picoknow.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* ************************************************************/ +/* fixed IDs type and functions */ +/* ************************************************************/ + +/** object : FixedIds + * shortcut : ids + */ +typedef struct picoktab_fixed_ids * picoktab_FixedIds; + +typedef struct picoktab_fixed_ids { + picoos_uint8 phonStartId; + picoos_uint8 phonTermId; +} picoktab_fixed_ids_t; + +/* to be used by picorsrc only */ +pico_status_t picoktab_specializeIdsKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common); + +picoktab_FixedIds picoktab_getFixedIds(picoknow_KnowledgeBase this); + + +/* ************************************************************/ +/* Graphs type and functions */ +/* ************************************************************/ + +typedef struct picoktab_graphs *picoktab_Graphs; + +/* to be used by picorsrc only */ +pico_status_t picoktab_specializeGraphsKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common); + +/* return kb graphs for usage in PU */ +picoktab_Graphs picoktab_getGraphs(picoknow_KnowledgeBase this); + +/* graph access routine: if the desired graph 'utf8graph' exists in + the graph table a graph offset > 0 is returned, which then can be + used to access the properties */ +picoos_uint32 picoktab_graphOffset(const picoktab_Graphs this, + picoos_uchar * utf8graph); + + +/* check if UTF8 char 'graph' has property vowellike, return non-zero + if 'ch' has the property, 0 otherwise */ +picoos_uint8 picoktab_hasVowellikeProp(const picoktab_Graphs this, + const picoos_uint8 *graph, + const picoos_uint8 graphlenmax); + +/* graph properties access routines: if graph with offset 'graphsOffset' has the + desired property, returns TRUE if 'ch' has the property, FALSE otherwise */ +picoos_bool picoktab_getIntPropTokenType(const picoktab_Graphs this, + picoos_uint32 graphsOffset, + picoos_uint8 *stokenType); +picoos_bool picoktab_getIntPropTokenSubType(const picoktab_Graphs this, + picoos_uint32 graphsOffset, + picoos_int8 *stokenSubType); +picoos_bool picoktab_getIntPropValue(const picoktab_Graphs this, + picoos_uint32 graphsOffset, + picoos_uint32 *value); +picoos_bool picoktab_getStrPropLowercase(const picoktab_Graphs this, + picoos_uint32 graphsOffset, + picoos_uchar *lowercase); +picoos_bool picoktab_getStrPropGraphsubs1(const picoktab_Graphs this, + picoos_uint32 graphsOffset, + picoos_uchar *graphsubs1); +picoos_bool picoktab_getStrPropGraphsubs2(const picoktab_Graphs this, + picoos_uint32 graphsOffset, + picoos_uchar *graphsubs2); +picoos_bool picoktab_getIntPropPunct(const picoktab_Graphs this, + picoos_uint32 graphsOffset, + picoos_uint8 *info1, + picoos_uint8 *info2); + +picoos_uint16 picoktab_graphsGetNumEntries(const picoktab_Graphs this); +void picoktab_graphsGetGraphInfo(const picoktab_Graphs this, + picoos_uint16 graphIndex, picoos_uchar * from, picoos_uchar * to, + picoos_uint8 * propset, + picoos_uint8 * stokenType, picoos_uint8 * stokenSubType, + picoos_uint8 * value, picoos_uchar * lowercase, + picoos_uchar * graphsubs1, picoos_uchar * graphsubs2, + picoos_uint8 * punct); + + +/* ************************************************************/ +/* Phones type and functions */ +/* ************************************************************/ + +/* to be used by picorsrc only */ +pico_status_t picoktab_specializePhonesKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common); + +typedef struct picoktab_phones *picoktab_Phones; + +/* return kb Phones for usage in PU */ +picoktab_Phones picoktab_getPhones(picoknow_KnowledgeBase this); + +/* check if 'ch' has a property, return non-zero if 'ch' has the + property, 0 otherwise */ +picoos_uint8 picoktab_hasVowelProp(const picoktab_Phones this, + const picoos_uint8 ch); +picoos_uint8 picoktab_hasDiphthProp(const picoktab_Phones this, + const picoos_uint8 ch); +picoos_uint8 picoktab_hasGlottProp(const picoktab_Phones this, + const picoos_uint8 ch); +picoos_uint8 picoktab_hasNonsyllvowelProp(const picoktab_Phones this, + const picoos_uint8 ch); +picoos_uint8 picoktab_hasSyllconsProp(const picoktab_Phones this, + const picoos_uint8 ch); + +/* to speed up processing for often used combinations of properties + the following functions are provided, which check if the property + combination is true for 'ch' */ +picoos_bool picoktab_isSyllCarrier(const picoktab_Phones this, + const picoos_uint8 ch); + +/* some properties can be assigned to a single sym only, check if 'ch' + is a special sym, return TRUE if it is the special sym, FALSE + otherwise */ +picoos_bool picoktab_isPrimstress(const picoktab_Phones this, + const picoos_uint8 ch); +picoos_bool picoktab_isSecstress(const picoktab_Phones this, + const picoos_uint8 ch); +picoos_bool picoktab_isSyllbound(const picoktab_Phones this, + const picoos_uint8 ch); +picoos_bool picoktab_isWordbound(const picoktab_Phones this, + const picoos_uint8 ch); +picoos_bool picoktab_isPause(const picoktab_Phones this, + const picoos_uint8 ch); + +/* get specific sym values */ +picoos_uint8 picoktab_getPrimstressID(const picoktab_Phones this); +picoos_uint8 picoktab_getSecstressID(const picoktab_Phones this); +picoos_uint8 picoktab_getSyllboundID(const picoktab_Phones this); +picoos_uint8 picoktab_getWordboundID(const picoktab_Phones this); +picoos_uint8 picoktab_getPauseID(const picoktab_Phones this); + +/* ************************************************************/ +/* Pos type and functions */ +/* ************************************************************/ + +/* to be used by picorsrc only */ +pico_status_t picoktab_specializePosKnowledgeBase(picoknow_KnowledgeBase this, + picoos_Common common); + +typedef struct picoktab_pos *picoktab_Pos; + +#define PICOKTAB_MAXNRPOS_IN_COMB 8 + +/* return kb Pos for usage in PU */ +picoktab_Pos picoktab_getPos(picoknow_KnowledgeBase this); + +/* returns TRUE if 'pos' is the ID of a unique (ie. non-combined) POS, + returns FALSE otherwise */ +picoos_bool picoktab_isUniquePos(const picoktab_Pos this, + const picoos_uint8 pos); + +/* returns TRUE if the non-combined 'pos' is one of the POSes in the + combined POS group 'posgroup, returns FALSE otherwise. Note: if + 'posgroup' is itself non-combined, this function returns TRUE if it + matches with 'pos', and FALSE otherwise */ +picoos_bool picoktab_isPartOfPosGroup(const picoktab_Pos this, + const picoos_uint8 pos, + const picoos_uint8 posgroup); + +/* return the combined POS group ID that is a representative ID for + all the 'poslistlen' POSes (which can be combined themselves) in + poslist. Returns '0' in case of error. */ +picoos_uint8 picoktab_getPosGroup(const picoktab_Pos this, + const picoos_uint8 *poslist, + const picoos_uint8 poslistlen); + +#ifdef __cplusplus +} +#endif + + +#endif /*PICOKTAB_H_*/ diff --git a/pico/lib/picoos.c b/pico/lib/picoos.c new file mode 100644 index 0000000..4e2b439 --- /dev/null +++ b/pico/lib/picoos.c @@ -0,0 +1,2309 @@ +/* + * 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 picoos.c + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#include +#include "picodefs.h" +#include "picopal.h" +#include "picoos.h" +#include "picodbg.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +#define picoos_SVOXFileHeader (picoos_char *)" (C) SVOX AG " + +/* ********************************************** + * default error and warning messages + * **********************************************/ + + +#define PICOOS_MSG_EXC_NUMBER_FORMAT (picoos_char *) "wrong number format" +#define PICOOS_MSG_EXC_MAX_NUM_EXCEED (picoos_char *) "number exceeded" +#define PICOOS_MSG_EXC_NAME_CONFLICT (picoos_char *) "name conflict" +#define PICOOS_MSG_EXC_NAME_UNDEFINED (picoos_char *) "name undefined" +#define PICOOS_MSG_EXC_NAME_ILLEGAL (picoos_char *) "illegal name" + +/* buffer interaction */ +#define PICOOS_MSG_EXC_BUF_OVERFLOW (picoos_char *) "buffer overflow" +#define PICOOS_MSG_EXC_BUF_UNDERFLOW (picoos_char *) "buffer underflow" +#define PICOOS_MSG_EXC_BUF_IGNORE (picoos_char *) "buffer error" + +/* memory allocation */ +#define PICOOS_MSG_EXC_OUT_OF_MEM (picoos_char *) "out of memory" + +/* files */ +#define PICOOS_MSG_EXC_CANT_OPEN_FILE (picoos_char *) "cannot open file" +#define PICOOS_MSG_EXC_UNEXPECTED_FILE_TYPE (picoos_char *) "unexpected file type" +#define PICOOS_MSG_EXC_FILE_CORRUPT (picoos_char *) "corrupt file" +#define PICOOS_MSG_EXC_FILE_NOT_FOUND (picoos_char *) "file not found" + +/* resources */ +#define PICOOS_MSG_EXC_RESOURCE_BUSY (picoos_char *) "resource is busy" +#define PICOOS_MSG_EXC_RESOURCE_MISSING (picoos_char *) "cannot find resource" + +/* knowledge bases */ +#define PICOOS_MSG_EXC_KB_MISSING (picoos_char *) "knowledge base missing" + +/* runtime exceptions (programming problems, usually a bug. E.g. trying to access null pointer) */ +#define PICOOS_MSG_ERR_NULLPTR_ACCESS (picoos_char *) "access violation" +#define PICOOS_MSG_ERR_INVALID_HANDLE (picoos_char *) "invalid handle value" +#define PICOOS_MSG_ERR_INVALID_ARGUMENT (picoos_char *) "invalid argument supplied" +#define PICOOS_MSG_ERR_INDEX_OUT_OF_RANGE (picoos_char *) "index out of range" + + +/* errors ("external" errors, e.g. hardware failure. Usually cannot be dealt with from inside pico.) */ +#define PICOOS_MSG_ERR_OTHER (picoos_char *) "other error" + +#define PICOOS_MSG_ERR_PU (picoos_char *) "error in processing unit" + +/* WARNINGS */ + +/* general */ +#define PICOOS_MSG_WARN_INCOMPLETE (picoos_char *) "incomplete output" +#define PICOOS_MSG_WARN_FALLBACK (picoos_char *) "using fall-back" +#define PICOOS_MSG_WARN_OTHER (picoos_char *) "other warning" + +/* resources */ +#define PICOOS_MSG_WARN_KB_OVERWRITE (picoos_char *) "overwriting knowledge base" +#define PICOOS_MSG_WARN_RESOURCE_DOUBLE_LOAD (picoos_char *) "resource already loaded" + +/* decision trees */ +#define PICOOS_MSG_WARN_INVECTOR (picoos_char *) "input vector not constructed" +#define PICOOS_MSG_WARN_CLASSIFICATION (picoos_char *) "output not classified" +#define PICOOS_MSG_WARN_OUTVECTOR (picoos_char *) "output vector not decomposed" + +/* processing units */ +#define PICOOS_MSG_WARN_PU_IRREG_ITEM (picoos_char *) "irregular item in processing unit" +#define PICOOS_MSG_WARN_PU_DISCARD_BUF (picoos_char *) "discarding processing unit buffer" + + +/* ********************************************** + * wrappers for picopal functions + * **********************************************/ + +picoos_int32 picoos_atoi(const picoos_char *s) +{ + return (picoos_int32)picopal_atoi((const picoos_char *)s); +} + + +picoos_int8 picoos_strcmp(const picoos_char *a, const picoos_char *b) +{ + picopal_int32 res = picopal_strcmp((const picopal_char *)a, + (const picopal_char *)b); + return (picoos_int8) ((res < 0) ? -1 : (res > 0) ? 1 : 0); +} +picoos_int8 picoos_strncmp(const picoos_char *a, const picoos_char *b, picoos_objsize_t siz) +{ + picopal_int32 res = picopal_strncmp((const picopal_char *)a, + (const picopal_char *)b, siz); + return (picoos_int8) ((res < 0) ? -1 : (res > 0) ? 1 : 0); +} + +picoos_uint32 picoos_strlen(const picoos_char *s) +{ + return (picoos_uint32)picopal_strlen((const picopal_char *)s); +} + +picoos_char *picoos_strchr(const picoos_char *s, picoos_char c) +{ + return (picoos_char *)picopal_strchr((const picopal_char *)s, + (picopal_char)c); +} + +picoos_char *picoos_strstr(const picoos_char *s, const picoos_char * substr) +{ + return (picoos_char *)picopal_strstr((const picopal_char *)s, + (const picopal_char *)substr); +} + +picoos_int16 picoos_slprintf(picoos_char * b, picoos_uint32 bsize, const picoos_char *f, ...) +{ + picopal_int16 i; + va_list args; + + va_start(args, (char *)f); + i = (picoos_int16)picopal_vslprintf((picoos_char *) b, bsize, (const picoos_char *)f, args); + va_end(args); + return i; +} + +picoos_char *picoos_strcpy(picoos_char *d, const picoos_char *s) +{ + return (picoos_char *)picopal_strcpy((picopal_char *)d, + (const picopal_char *)s); +} + +picoos_char *picoos_strcat(picoos_char *d, const picoos_char *s) +{ + return (picoos_char *)picopal_strcat((picopal_char *)d, + (const picopal_char *)s); +} + +picoos_objsize_t picoos_strlcpy(picoos_char *dst, const picoos_char *src, picoos_objsize_t siz) +{ + return (picoos_objsize_t) picopal_strlcpy((picopal_char *) dst, (const picopal_char *) src, (picopal_objsize_t) siz); +} + +/* copies 'length' bytes from 'src' to 'dest'. (regions may be overlapping) no error checks! */ +void * picoos_mem_copy(const void * src, void * dst, picoos_objsize_t length) +{ + return picopal_mem_copy(src,dst,(picopal_objsize_t) length); +} + +/* sets 'length' bytes starting at dest[0] to 'byte_val' */ +void * picoos_mem_set(void * dest, picoos_uint8 byte_val, picoos_objsize_t length) { + return picopal_mem_set(dest,(picopal_uint8)byte_val, (picopal_objsize_t)length); +} + + +picoos_double picoos_cos (const picoos_double cos_arg) +{ + return (picoos_double) picopal_cos ((picopal_double) cos_arg); +} + + +picoos_double picoos_sin (const picoos_double sin_arg) +{ + return (picoos_double) picopal_sin((picopal_double) sin_arg); +} +picoos_double picoos_fabs (const picoos_double fabs_arg) +{ + return (picoos_double) picopal_fabs((picopal_double) fabs_arg); +} + +picoos_double picoos_quick_exp(const picoos_double y) { + return (picoos_double) picopal_quick_exp ((picopal_double)y); +} + + +/* *****************************************************************/ +/* "Common" */ +/* *****************************************************************/ +/* picoos_common is a collection of basic functionalities that must be globally + * accessible from every "big" function. It includes pointers to the MemoryManasger, + * ExceptionManager and a system-wide list of open files. */ + +picoos_Common picoos_newCommon(picoos_MemoryManager mm) +{ + picoos_Common this = (picoos_Common) picoos_allocate(mm,sizeof(*this)); + if (NULL != this) { + /* initialize */ + this->em = NULL; + this->mm = NULL; + this->fileList = NULL; + } + return this; +} + +void picoos_disposeCommon(picoos_MemoryManager mm, picoos_Common * this) +{ + if (NULL != (*this)) { + /* terminate */ + picoos_deallocate(mm,(void *)this); + } +} + + +/* *****************************************************************/ +/* Memory Management */ +/* *****************************************************************/ + +typedef struct mem_block_hdr * MemBlockHdr; +typedef struct mem_block_hdr +{ + MemBlockHdr next; + byte_ptr_t data; + picoos_objsize_t size; +} mem_block_hdr_t; + +typedef struct mem_cell_hdr * MemCellHdr; +typedef struct mem_cell_hdr +{ + /* size may be <0 if used */ + picoos_ptrdiff_t size; + MemCellHdr leftCell; + MemCellHdr prevFree, nextFree; +} mem_cell_hdr_t; + +typedef struct memory_manager +{ + MemBlockHdr firstBlock, lastBlock; /* memory blockList */ + MemCellHdr freeCells, lastFree; /* free memory cells (first/last sentinel */ + /* "constants" */ + picoos_objsize_t fullCellHdrSize; /* aligned size of full cell header, including free-links */ + picoos_objsize_t usedCellHdrSize; /* aligned size of header part without free-links */ + picoos_objsize_t minContSize; /* minimum requestable application content size for allocation; + must hold free-list info; = fullCellHdrSize-usedCellHdrSize */ + picoos_objsize_t minCellSize; /* minimum remaining cell size when a free cell is split */ + picoos_bool protMem; /* true if memory protection is enabled */ + picoos_ptrdiff_t usedSize; + picoos_ptrdiff_t prevUsedSize; + picoos_ptrdiff_t maxUsedSize; +} memory_manager_t; + +/** allocates 'alloc_size' bytes at start of raw memory block ('raw_mem',raw_mem_size) + * and returns pointer to allocated region. Returns remaining (correctly aligned) raw memory block + * in ('rest_mem','rest_mem_size'). + * The allocated memory is not subject to memory management, so that it can never be freed again! + * + */ +void * picoos_raw_malloc(byte_ptr_t raw_mem, + picoos_objsize_t raw_mem_size, picoos_objsize_t alloc_size, + byte_ptr_t * rest_mem, picoos_objsize_t * rest_mem_size) +{ + picoos_ptrdiff_t rest; + if (raw_mem == NULL) { + return NULL; + } else { + if (alloc_size < 1) { + alloc_size = 1; + } + alloc_size = ((alloc_size + PICOOS_ALIGN_SIZE - 1) / PICOOS_ALIGN_SIZE) + * PICOOS_ALIGN_SIZE; + + rest = raw_mem_size - alloc_size; + if (rest < 0) { + return NULL; + } else { + *rest_mem_size = rest; + *rest_mem = raw_mem + alloc_size; + return (void *) raw_mem; + } + } +} + +/** initializes the last block of mm */ +static int os_init_mem_block(picoos_MemoryManager this) +{ + int isFirstBlock; + void * newBlockAddr; + picoos_objsize_t size; + MemCellHdr cbeg, cmid, cend; + + isFirstBlock = (this->freeCells == NULL); + newBlockAddr = (void *) this->lastBlock->data; + size = this->lastBlock->size; + cbeg = (MemCellHdr) newBlockAddr; + cmid = (MemCellHdr)((picoos_objsize_t)newBlockAddr + this->fullCellHdrSize); + cend = (MemCellHdr)((picoos_objsize_t)newBlockAddr + size + - this->fullCellHdrSize); + cbeg->size = 0; + + cbeg->leftCell = NULL; + cmid->size = size - 2 * this->fullCellHdrSize; + cmid->leftCell = cbeg; + cend->size = 0; + cend->leftCell = cmid; + if (isFirstBlock) { + cbeg->nextFree = cmid; + cbeg->prevFree = NULL; + cmid->nextFree = cend; + cmid->prevFree = cbeg; + cend->nextFree = NULL; + cend->prevFree = cmid; + this->freeCells = cbeg; + this->lastFree = cend; + } else { + /* add cmid to free cell list */ + cbeg->nextFree = NULL; + cbeg->prevFree = NULL; + cmid->nextFree = this->freeCells->nextFree; + cmid->prevFree = this->freeCells; + cmid->nextFree->prevFree = cmid; + cmid->prevFree->nextFree = cmid; + cend->nextFree = NULL; + cbeg->prevFree = NULL; + } + return PICO_OK; +} + + +picoos_MemoryManager picoos_newMemoryManager( + void *raw_memory, + picoos_objsize_t size, + picoos_bool enableMemProt) +{ + byte_ptr_t rest_mem; + picoos_objsize_t rest_mem_size; + picoos_MemoryManager this; + picoos_objsize_t size2; + mem_cell_hdr_t test_cell; + + this = picoos_raw_malloc(raw_memory, size, sizeof(memory_manager_t), + &rest_mem, &rest_mem_size); + if (this == NULL) { + return NULL; + } + + /* test if memory protection functionality is available on the current + platform (if not, picopal_mpr_alloc() always returns NULL) */ + if (enableMemProt) { + void *addr = picopal_mpr_alloc(100); + if (addr == NULL) { + enableMemProt = FALSE; + } else { + picopal_mpr_free(&addr); + } + } + + this->firstBlock = NULL; + this->lastBlock = NULL; + this->freeCells = NULL; + this->lastFree = NULL; + + this->protMem = enableMemProt; + this->usedSize = 0; + this->prevUsedSize = 0; + this->maxUsedSize = 0; + + /* get aligned full header size */ + this->fullCellHdrSize = ((sizeof(mem_cell_hdr_t) + PICOOS_ALIGN_SIZE - 1) + / PICOOS_ALIGN_SIZE) * PICOOS_ALIGN_SIZE; + /* get aligned size of header without free-list fields; the result may be compiler-dependent; + the size is therefore computed by inspecting the end addresses of the fields 'size' and 'leftCell'; + the higher of the ending addresses is used to get the (aligned) starting address + of the application contents */ + this->usedCellHdrSize = (picoos_objsize_t) &test_cell.size + - (picoos_objsize_t) &test_cell + sizeof(picoos_objsize_t); + size2 = (picoos_objsize_t) &test_cell.leftCell - (picoos_objsize_t) + &test_cell + sizeof(MemCellHdr); + if (size2 > this->usedCellHdrSize) { + this->usedCellHdrSize = size2; + } + /* get minimum application-usable size; must be large enough to hold remainder of + cell header (free-list links) when in free-list */ + this->minContSize = this->fullCellHdrSize - this->usedCellHdrSize; + /* get minimum required size of a cell remaining after a cell split */ + this->minCellSize = this->fullCellHdrSize + PICOOS_ALIGN_SIZE; + + /* install remainder of raw memory block as first block */ + raw_memory = rest_mem; + size = rest_mem_size; + this->firstBlock = this->lastBlock = picoos_raw_malloc(raw_memory, size, + sizeof(mem_block_hdr_t), &rest_mem, &rest_mem_size); + if (this->lastBlock == NULL) { + return NULL; + } + this->lastBlock->next = NULL; + this->lastBlock->data = rest_mem; + this->lastBlock->size = rest_mem_size; + + os_init_mem_block(this); + + return this; +} + +void picoos_disposeMemoryManager(picoos_MemoryManager * mm) +{ + *mm = NULL; +} + + +/* the following memory manager routines are for testing and + debugging purposes */ + + +void *picoos_allocProtMem(picoos_MemoryManager mm, picoos_objsize_t byteSize) +{ + if (mm->protMem) { + return picopal_mpr_alloc(byteSize); + } else { + return picoos_allocate(mm, byteSize); + } +} + + +void picoos_deallocProtMem(picoos_MemoryManager mm, void **addr) +{ + if (mm->protMem) { + picopal_mpr_free(addr); + } else { + picoos_deallocate(mm, addr); + } +} + + +void picoos_protectMem( + picoos_MemoryManager mm, + void *addr, + picoos_objsize_t len, + picoos_bool enable) +{ + if (mm->protMem) { + int prot = PICOPAL_PROT_READ; + if (!enable) { + prot |= PICOPAL_PROT_WRITE; + } + picopal_mpr_protect(addr, len, prot); + } else { + /* memory protection disabled; nothing to do */ + } +} + +#define PICOPAL_PROT_NONE 0 /* the memory cannot be accessed at all */ +#define PICOPAL_PROT_READ 1 /* the memory can be read */ +#define PICOPAL_PROT_WRITE 2 /* the memory can be written to */ + +void picoos_getMemUsage( + picoos_MemoryManager this, + picoos_bool resetIncremental, + picoos_int32 *usedBytes, + picoos_int32 *incrUsedBytes, + picoos_int32 *maxUsedBytes) +{ + *usedBytes = (picoos_int32) this->usedSize; + *incrUsedBytes = (picoos_int32) (this->usedSize - this->prevUsedSize); + *maxUsedBytes = (picoos_int32) this->maxUsedSize; + if (resetIncremental) { + this->prevUsedSize = this->usedSize; + } +} + + +void picoos_showMemUsage(picoos_MemoryManager this, picoos_bool incremental, + picoos_bool resetIncremental) +{ + picoos_int32 usedBytes, incrUsedBytes, maxUsedBytes; + + picoos_getMemUsage(this, resetIncremental, &usedBytes, &incrUsedBytes, + &maxUsedBytes); + if (incremental) { + PICODBG_DEBUG(("additional memory used: %d", incrUsedBytes)); + } else { + PICODBG_DEBUG(("memory used: %d, maximally used: %d", usedBytes, maxUsedBytes)); + } +} + + +void * picoos_allocate(picoos_MemoryManager this, + picoos_objsize_t byteSize) +{ + + picoos_objsize_t cellSize; + MemCellHdr c, c2, c2r; + void * adr; + + if (byteSize < this->minContSize) { + byteSize = this->minContSize; + } + byteSize = ((byteSize + PICOOS_ALIGN_SIZE - 1) / PICOOS_ALIGN_SIZE) + * PICOOS_ALIGN_SIZE; + + cellSize = byteSize + this->usedCellHdrSize; + /*PICODBG_TRACE(("allocating %d", cellSize));*/ + c = this->freeCells->nextFree; + while ( + (c != NULL) && + (c->size != (picoos_ptrdiff_t) cellSize) && + (c->size < (picoos_ptrdiff_t)(cellSize+ this->minCellSize))) { + c = c->nextFree; + } + if (c == NULL) { + return NULL; + } + if ((c->size == (picoos_ptrdiff_t) cellSize)) { + c->prevFree->nextFree = c->nextFree; + c->nextFree->prevFree = c->prevFree; + } else { + c2 = (MemCellHdr)((picoos_objsize_t)c + cellSize); + c2->size = c->size - cellSize; + c->size = cellSize; + c2->leftCell = c; + c2r = (MemCellHdr)((picoos_objsize_t)c2 + c2->size); + c2r->leftCell = c2; + c2->nextFree = c->nextFree; + c2->nextFree->prevFree = c2; + c2->prevFree = c->prevFree; + c2->prevFree->nextFree = c2; + } + + /* statistics */ + this->usedSize += cellSize; + if (this->usedSize > this->maxUsedSize) { + this->maxUsedSize = this->usedSize; + } + + c->size = -(c->size); + adr = (void *)((picoos_objsize_t)c + this->usedCellHdrSize); + return adr; +} + +void picoos_deallocate(picoos_MemoryManager this, void * * adr) +{ + MemCellHdr c; + MemCellHdr cr; + MemCellHdr cl; + MemCellHdr crr; + + + if ((*adr) != NULL) { + c = (MemCellHdr)((picoos_objsize_t)(*adr) - this->usedCellHdrSize); + c->size = -(c->size); + + /*PICODBG_TRACE(("deallocating %d", c->size));*/ + /* statistics */ + this->usedSize -= c->size; + + cr = (MemCellHdr)((picoos_objsize_t)c + c->size); + cl = c->leftCell; + if (cl->size > 0) { + if (cr->size > 0) { + crr = (MemCellHdr)((picoos_objsize_t)cr + cr->size); + crr->leftCell = cl; + cl->size = ((cl->size + c->size) + cr->size); + cr->nextFree->prevFree = cr->prevFree; + cr->prevFree->nextFree = cr->nextFree; + } else { + cl->size = (cl->size + c->size); + cr->leftCell = cl; + } + } else { + if ((cr->size > 0)) { + crr = (MemCellHdr)((picoos_objsize_t)cr + cr->size); + crr->leftCell = c; + c->size = (c->size + cr->size); + c->nextFree = cr->nextFree; + c->prevFree = cr->prevFree; + c->nextFree->prevFree = c; + c->prevFree->nextFree = c; + } else { + c->nextFree = this->freeCells->nextFree; + c->prevFree = this->freeCells; + c->nextFree->prevFree = c; + c->prevFree->nextFree = c; + } + } + } + *adr = NULL; +} + +/* *****************************************************************/ +/* Exception Management */ +/* *****************************************************************/ +/** object : exceptionManager + * shortcut : em + * + */ + +typedef picoos_char picoos_exc_msg[PICOOS_MAX_EXC_MSG_LEN]; +typedef picoos_char picoos_warn_msg[PICOOS_MAX_WARN_MSG_LEN]; + +typedef struct picoos_exception_manager +{ + picoos_int32 curExceptionCode; + picoos_exc_msg curExceptionMessage; + + picoos_uint8 curNumWarnings; + picoos_int32 curWarningCode[PICOOS_MAX_NUM_WARNINGS]; + picoos_warn_msg curWarningMessage[PICOOS_MAX_NUM_WARNINGS]; + +} picoos_exception_manager_t; + +void picoos_emReset(picoos_ExceptionManager this) +{ + this->curExceptionCode = PICO_OK; + this->curExceptionMessage[0] = '\0'; + this->curNumWarnings = 0; +} + +picoos_ExceptionManager picoos_newExceptionManager(picoos_MemoryManager mm) +{ + picoos_ExceptionManager this = (picoos_ExceptionManager) picoos_allocate( + mm, sizeof(*this)); + if (NULL != this) { + /* initialize */ + picoos_emReset(this); + } + return this; +} + +void picoos_disposeExceptionManager(picoos_MemoryManager mm, + picoos_ExceptionManager * this) +{ + if (NULL != (*this)) { + /* terminate */ + picoos_deallocate(mm, (void *)this); + } +} + +static void picoos_vSetErrorMsg(picoos_char * dst, picoos_objsize_t siz, + picoos_int16 code, picoos_char * base, const picoos_char *fmt, va_list args) +{ + picoos_uint16 bsize; + + if (NULL == base) { + switch (code) { + case PICO_EXC_NUMBER_FORMAT: + base = PICOOS_MSG_EXC_NUMBER_FORMAT; + break; + case PICO_EXC_MAX_NUM_EXCEED: + base = PICOOS_MSG_EXC_MAX_NUM_EXCEED; + break; + case PICO_EXC_NAME_CONFLICT: + base = PICOOS_MSG_EXC_NAME_CONFLICT; + break; + case PICO_EXC_NAME_UNDEFINED: + base = PICOOS_MSG_EXC_NAME_UNDEFINED; + break; + case PICO_EXC_NAME_ILLEGAL: + base = PICOOS_MSG_EXC_NAME_ILLEGAL; + break; + + /* buffer interaction */ + case PICO_EXC_BUF_OVERFLOW: + base = PICOOS_MSG_EXC_BUF_OVERFLOW; + break; + case PICO_EXC_BUF_UNDERFLOW: + base = PICOOS_MSG_EXC_BUF_UNDERFLOW; + break; + case PICO_EXC_BUF_IGNORE: + base = PICOOS_MSG_EXC_BUF_IGNORE; + break; + + /* memory allocation */ + case PICO_EXC_OUT_OF_MEM: + base = PICOOS_MSG_EXC_OUT_OF_MEM; + break; + + /* files */ + case PICO_EXC_CANT_OPEN_FILE: + base = PICOOS_MSG_EXC_CANT_OPEN_FILE; + break; + case PICO_EXC_UNEXPECTED_FILE_TYPE: + base = PICOOS_MSG_EXC_UNEXPECTED_FILE_TYPE; + break; + case PICO_EXC_FILE_CORRUPT: + base = PICOOS_MSG_EXC_FILE_CORRUPT; + break; + + case PICO_EXC_FILE_NOT_FOUND: + base = PICOOS_MSG_EXC_FILE_NOT_FOUND; + break; + + /* resources */ + case PICO_EXC_RESOURCE_BUSY: + base = PICOOS_MSG_EXC_RESOURCE_BUSY; + break; + case PICO_EXC_RESOURCE_MISSING: + base = PICOOS_MSG_EXC_RESOURCE_MISSING; + break; + + /* knowledge bases */ + case PICO_EXC_KB_MISSING: + fmt = PICOOS_MSG_EXC_KB_MISSING; + break; + + /* runtime exceptions (programming problems, usually a bug. E.g. trying to access null pointer) */ + case PICO_ERR_NULLPTR_ACCESS: + base = PICOOS_MSG_ERR_NULLPTR_ACCESS; + break; + case PICO_ERR_INVALID_HANDLE: + base = PICOOS_MSG_ERR_INVALID_HANDLE; + break; + case PICO_ERR_INVALID_ARGUMENT: + base = PICOOS_MSG_ERR_INVALID_ARGUMENT; + break; + case PICO_ERR_INDEX_OUT_OF_RANGE: + base = PICOOS_MSG_ERR_INDEX_OUT_OF_RANGE; + break; + + /* errors ("external" errors, e.g. hardware failure. Usually cannot be dealt with from inside pico.) */ + case PICO_ERR_OTHER: + base = PICOOS_MSG_ERR_OTHER; + break; + + /* other error inside pu */ + case PICO_STEP_ERROR: + base = PICOOS_MSG_ERR_PU; + break; + + /* WARNINGS */ + + /* general */ + case PICO_WARN_INCOMPLETE: + base = PICOOS_MSG_WARN_INCOMPLETE; + break; + case PICO_WARN_FALLBACK: + base = PICOOS_MSG_WARN_FALLBACK; + break; + + case PICO_WARN_OTHER: + base = PICOOS_MSG_WARN_OTHER; + break; + + /* resources */ + case PICO_WARN_KB_OVERWRITE: + base = PICOOS_MSG_WARN_KB_OVERWRITE; + break; + case PICO_WARN_RESOURCE_DOUBLE_LOAD: + base = PICOOS_MSG_WARN_RESOURCE_DOUBLE_LOAD; + break; + + /* decision trees */ + case PICO_WARN_INVECTOR: + base = PICOOS_MSG_WARN_INVECTOR; + break; + case PICO_WARN_CLASSIFICATION: + base = PICOOS_MSG_WARN_CLASSIFICATION; + break; + case PICO_WARN_OUTVECTOR: + base = PICOOS_MSG_WARN_OUTVECTOR; + break; + + /* processing units */ + case PICO_WARN_PU_IRREG_ITEM: + base = PICOOS_MSG_WARN_PU_IRREG_ITEM; + break; + case PICO_WARN_PU_DISCARD_BUF: + base = PICOOS_MSG_WARN_PU_DISCARD_BUF; + break; + + default: + base = (picoos_char *) "unknown error"; + break; + } + } + bsize = picoos_strlcpy(dst,base,siz); + if ((NULL != fmt) && (bsize < siz)) { /* there is something to add and more space to add it */ + if (bsize > 0) { + dst += bsize; + siz -= bsize; + bsize = picoos_strlcpy(dst,(picoos_char *)": ",siz); + } + if (bsize < siz) { + picopal_vslprintf((picopal_char *) dst + bsize, siz - bsize, (picopal_char *)fmt, args); + } + } +} + +void picoos_setErrorMsg(picoos_char * dst, picoos_objsize_t siz, + picoos_int16 code, picoos_char * base, const picoos_char *fmt, ...) +{ + va_list args; + va_start(args, (char *)fmt); + picoos_vSetErrorMsg(dst,siz, code, base, fmt,args); + va_end(args); +} + +/* For convenience, this function returns the resulting current exception code. The return value therefore is NOT the status of raising + * the error! */ +pico_status_t picoos_emRaiseException(picoos_ExceptionManager this, + pico_status_t exceptionCode, picoos_char * baseMessage, picoos_char * fmt, ...) +{ + va_list args; + + + if (PICO_OK == this->curExceptionCode && PICO_OK != exceptionCode) { + this->curExceptionCode = exceptionCode; + va_start(args, (char *)fmt); + picoos_vSetErrorMsg(this->curExceptionMessage,PICOOS_MAX_EXC_MSG_LEN, exceptionCode, baseMessage, fmt,args); + PICODBG_DEBUG(( + "exit with exception code=%i, exception message='%s'", + this->curExceptionCode, this->curExceptionMessage)); + + va_end(args); + + } + return this->curExceptionCode; +} + +pico_status_t picoos_emGetExceptionCode(picoos_ExceptionManager this) +{ + return this->curExceptionCode; +} + +void picoos_emGetExceptionMessage(picoos_ExceptionManager this, picoos_char * msg, picoos_uint16 maxsize) +{ + picoos_strlcpy(msg,this->curExceptionMessage,maxsize); +} + +void picoos_emRaiseWarning(picoos_ExceptionManager this, + pico_status_t warningCode, picoos_char * baseMessage, picoos_char * fmt, ...) +{ + va_list args; + if ((this->curNumWarnings < PICOOS_MAX_NUM_WARNINGS) && (PICO_OK != warningCode)) { + if (PICOOS_MAX_NUM_WARNINGS-1 == this->curNumWarnings) { + this->curWarningCode[this->curNumWarnings] = PICO_EXC_MAX_NUM_EXCEED; + picoos_strlcpy(this->curWarningMessage[this->curNumWarnings],(picoos_char *) "too many warnings",PICOOS_MAX_WARN_MSG_LEN); + } else { + this->curWarningCode[this->curNumWarnings] = warningCode; + va_start(args, (char *)fmt); + picoos_vSetErrorMsg(this->curWarningMessage[this->curNumWarnings],PICOOS_MAX_WARN_MSG_LEN, warningCode, baseMessage, fmt,args); + va_end(args); + } + this->curNumWarnings++; + } + PICODBG_DEBUG(( + "exit with code=%i and message='%s', resulting in #warnings=%i", + this->curWarningCode[this->curNumWarnings-1], + this->curWarningMessage[this->curNumWarnings-1], + this->curNumWarnings)); +} + +picoos_uint8 picoos_emGetNumOfWarnings(picoos_ExceptionManager this) +{ + return this->curNumWarnings; +} + +pico_status_t picoos_emGetWarningCode(picoos_ExceptionManager this, picoos_uint8 index) +{ + if (index < this->curNumWarnings) { + return this->curWarningCode[index]; + } else { + return PICO_OK; + } +} + +void picoos_emGetWarningMessage(picoos_ExceptionManager this, picoos_uint8 index, picoos_char * msg, picoos_uint16 maxsize) +{ + if (index < this->curNumWarnings) { + picoos_strlcpy(msg,this->curWarningMessage[index],maxsize); + } else { + msg[0] = NULLC; + } +} + + + + +/* *****************************************************************/ +/* File Access */ +/* *****************************************************************/ + +#define picoos_MagicNumber 192837465 +#define picoos_MaxBufSize 1000000 +#define picoos_MaxNrOfBuffers 1000000 +#define picoos_MaxBufLen 8192 +#define picoos_HashFuncId0 0 +#define picoos_HashTableSize0 101 +#define picoos_HashTableSize1 1731 +#define picoos_MaxHashTableSize HashTableSize1 + +#define cardinal_ptr_t picoos_uint32 * + +typedef struct picoos_buffer +{ + picoos_char * data; + int start; /* denotes the file position of the buffer beginning */ + int len; /* denotes the length of the buffer; -1 means invalid buffer */ + int pos; /* denotes the position in the buffer */ +} picoos_buffer_t; + +typedef picoos_buffer_t picoos_buffer_array_t[picoos_MaxNrOfBuffers]; +typedef picoos_int32 picoos_buffer_index_array_t[picoos_MaxNrOfBuffers]; + +/** object : File + * shortcut : f + * + */ +typedef struct picoos_file +{ + picoos_FileName name; + picoos_uint8 binary; + picoos_uint8 write; + + picopal_File nf; + + picoos_uint32 lFileLen; + picoos_uint32 lPos; + + picoos_File next; + picoos_File prev; + +} picoos_file_t; + +picoos_File picoos_newFile(picoos_MemoryManager mm) +{ + picoos_File this = (picoos_File) picoos_allocate(mm, sizeof(*this)); + if (NULL != this) { + /* initialize */ + } + return this; +} + +void picoos_disposeFile(picoos_MemoryManager mm, picoos_File * this) +{ + if (NULL != (*this)) { + /* terminate */ + picoos_deallocate(mm, (void *)this); + } +} + + +/* ************************************************************ + * low-level file operations + **************************************************************/ + +static picoos_int32 os_min(const picoos_int32 x, const picoos_int32 y) +{ + return (x < y) ? x : y; +} + +/* + static picoos_uint8 LReadChar (picoos_File f, picoos_char * ch); + + + static picoos_uint8 LSetPos (picoos_File f, unsigned int pos); + + + static picoos_uint8 LGetPos (picoos_File f, picoos_uint32 * pos); + + + static picoos_uint8 LEof (picoos_File f); + */ + +static picoos_bool LOpen(picoos_Common g, picoos_File * f, + picoos_char fileName[], picopal_access_mode mode) +{ + picoos_bool done = TRUE; + + *f = picoos_newFile(g->mm); + picopal_strcpy((*f)->name, fileName); + (*f)->write = ((mode == PICOPAL_TEXT_WRITE) || (mode + == PICOPAL_BINARY_WRITE)); + (*f)->binary = (mode + == PICOPAL_BINARY_WRITE); + (*f)->next = NULL; + (*f)->prev = NULL; + (*f)->nf = picopal_get_fnil(); + (*f)->lFileLen = 0; + (*f)->lPos = 0; + if (picopal_strlen((*f)->name)) { + (*f)->nf = picopal_fopen((*f)->name, mode); + done = !(picopal_is_fnil((*f)->nf)); + if (done) { + (*f)->lFileLen = picopal_flength((*f)->nf); + } + } + if (done) { + (*f)->next = g->fileList; + if (g->fileList != NULL) { + g->fileList->prev = (*f); + } + g->fileList = (*f); + } else { + picoos_disposeFile(g->mm, f); + (*f) = NULL; + } + return done; +} + +static picoos_bool LClose(picoos_Common g, picoos_File * f) +{ + + picoos_bool done; + + if (((*f) != NULL)) { + done = (PICO_OK == picopal_fclose((*f)->nf)); + if (((*f)->next != NULL)) { + (*f)->next->prev = (*f)->prev; + } + if (((*f)->prev != NULL)) { + (*f)->prev->next = (*f)->next; + } else { + g->fileList = (*f)->next; + } + picoos_disposeFile(g->mm, f); + + done = TRUE; + } else { + done = FALSE; + } + return done; + +} + +/* caller must ensure that bytes[] has at least len allocated bytes */ +static picoos_bool LReadBytes(picoos_File f, picoos_uint8 bytes[], + picoos_uint32 * len) +{ + picoos_bool done; + picoos_int32 res; + + PICODBG_TRACE(("trying to read %i bytes",*len)); + if ((f != NULL)) { + res = picopal_fread_bytes(f->nf, (void *) &bytes[(0)], 1, (*len)); + PICODBG_TRACE(("res = %i",res)); + if (res < 0) { /* non-ansi */ + (*len) = 0; + done = FALSE; + } else if (((picoos_uint32)res != (*len))) { + (*len) = res; + done = FALSE; + } else { + done = TRUE; + } + f->lPos = (f->lPos + (*len)); + } else { + (*len) = 0; + done = FALSE; + } + return done; +} + + static picoos_bool LWriteBytes(picoos_File f, const picoos_char bytes[], int * len) { + picoos_bool done; + int res; + /*int n; + void * bptr; */ + + if (f != NULL) { + res = picopal_fwrite_bytes(f->nf, (void *) bytes, 1, *len); + if ((res < 0)) { + (*len) = 0; + done = FALSE; + } else if ((res != (*len))) { + (*len) = res; + done = FALSE; + } else { + done = TRUE; + } + f->lPos = (f->lPos + (unsigned int) (*len)); + if ((f->lPos > f->lFileLen)) { + f->lFileLen = f->lPos; + } + } else { + (*len) = 0; + done = FALSE; + } + return done; +} + + +static picoos_bool LSetPos(picoos_File f, unsigned int pos) +{ + + picoos_bool done; + + if ((f != NULL)) { + if ((pos == f->lPos)) { + done = TRUE; + } else { + done = (PICO_OK == picopal_fseek(f->nf, pos, PICOPAL_SEEK_SET)); + if (done) { + f->lPos = pos; + } + } + } else { + done = FALSE; + } + return done; +} + +static picoos_bool LGetPos(picoos_File f, picoos_uint32 * pos) +{ + picoos_bool done = TRUE; + if ((f != NULL)) { + (*pos) = f->lPos; + } else { + done = FALSE; + (*pos) = 0; + } + return done; + +} + +static picoos_bool LEof(picoos_File f) +{ + picoos_bool isEof; + + if ((f != NULL)) { + isEof = picopal_feof(f->nf); + } else { + isEof = TRUE; + } + return isEof; + +} + +/* **************************************************************************************/ + + + +/* read a given string 'str' from file. If no match was found, the read position is advanced until and including the first + * non-matching character */ +static picoos_bool picoos_StrRead (picoos_File f, picoos_char str[]) +{ + picoos_uint32 i = 0; + picoos_bool done = TRUE; + picoos_char b; + + while (done && (str[i] != NULLC)) { + done = done && picoos_ReadByte(f,(picoos_char *)&b); + done = done && (b == str[i]); + i++; + } + return done; +} + +/* write 'str' to file */ +static picoos_bool picoos_WriteStr (picoos_File f, picoos_char str[]) +{ + picoos_uint32 i = 0; + picoos_bool done = TRUE; + + while (done && (str[i] != NULLC)) { + done = done && picoos_WriteByte(f,str[i]); + i++; + } + return done; +} + + + +/* **** Sequential binary file access ******/ + +/* Remark: 'ReadByte', 'ReadBytes' and 'ReadVar' may be mixed; + 'WriteByte', 'WriteBytes' and 'WriteVar' may be mixed. */ + +/* Open existing binary file for read access. Reading is buffered + * with 'nrOfBufs' buffers of size 'bufSize'. If 'nrOfBufs' or + * 'bufSize' is 0 reading is not buffered. + * If 'key' is not empty, the file is decrypted with 'key'. + * If the opened file is in an encrypted archive file, it + */ +picoos_uint8 picoos_OpenBinary(picoos_Common g, picoos_File * f, + picoos_char fileName[]) +{ + return LOpen(g, f, fileName, PICOPAL_BINARY_READ); +} + + +/* Read next byte from file 'f'. */ +picoos_bool picoos_ReadByte(picoos_File f, picoos_uint8 * by) +{ + picoos_uint32 n = 1; + + return picoos_ReadBytes(f, by, &n) && (n == 1); + +} + +/* Read next 'len' bytes from 'f' into 'bytes'; 'len' returns the + number of bytes actually read (may be smaller than requested + length if at end of file). bytes[] must be big enough to hold at least len bytes. +*/ +picoos_bool picoos_ReadBytes(picoos_File f, picoos_uint8 bytes[], + picoos_uint32 * len) +{ + picoos_bool done = TRUE; + /* unsigned int origPos; */ + + if ((f != NULL)) { + done = LReadBytes(f, bytes, len); + /*if ((f->keyLen > 0)) { + DecryptBytes(f->key,picoos_MaxKeyLen,f->keyLen,origPos,bytes,(*len)); + }*/ + } + + return done; +} + + +/* Create new binary file. + If 'key' is not empty, the file is encrypted with 'key'. */ +picoos_bool picoos_CreateBinary(picoos_Common g, picoos_File * f, + picoos_char fileName[]) +{ + return LOpen(g, f, fileName, PICOPAL_BINARY_WRITE); + +} + + +picoos_uint8 picoos_WriteByte(picoos_File f, picoos_char by) +{ + int n = 1; + + return picoos_WriteBytes(f, (picoos_char *) &by, &n); +} + + +/* Writes 'len' bytes from 'bytes' onto file 'f'; 'len' returns + the number of bytes actually written. */ +picoos_bool picoos_WriteBytes(picoos_File f, const picoos_char bytes[], picoos_int32 * len) { + picoos_bool done = FALSE; + + if (f != NULL) { + done = LWriteBytes(f, bytes, len); + } + + return done; +} + + + +/* Close previously opened binary file. */ +picoos_uint8 picoos_CloseBinary(picoos_Common g, picoos_File * f) +{ + return LClose(g, f); + +} + +/* **************************************************************************************/ +/* *** general routines *****/ + + +/* Returns whether end of file was encountered in previous + read operation. */ +picoos_bool picoos_Eof(picoos_File f) +{ + if ((NULL != f)) { + return LEof(f); + } else { + return TRUE; + } + +} + +/* sets the file pointer to + 'pos' bytes from beginning (first byte = byte 0). This + routine should only be used for binary files. */ +picoos_bool picoos_SetPos(picoos_File f, picoos_int32 pos) +{ + picoos_bool done = TRUE; + if ((NULL != f)) { + done = LSetPos(f, pos); + } else { + done = FALSE; + } + return done; + +} + +/* Get position from file 'f'. */ +picoos_bool picoos_GetPos(picoos_File f, picoos_uint32 * pos) +{ + if (NULL != f) { + /* if (f->bFile) { + (*pos) = BGetPos(f); + } else { */ + (*pos) = LGetPos(f, pos); + /* } */ + return TRUE; + } else { + (*pos) = 0; + return FALSE; + } +} + +/* Returns the length of the file in bytes. */ +picoos_bool picoos_FileLength(picoos_File f, picoos_uint32 * len) +{ + + if (NULL != f) { + *len = f->lFileLen; + return TRUE; + } else { + *len = 0; + return FALSE; + } +} + +/* Return full name of file 'f'. maxsize is the size of 'name[]' in bytes */ +picoos_bool picoos_Name(picoos_File f, picoos_char name[], picoos_uint32 maxsize) +{ + picoos_bool done = TRUE; + + if (NULL != f) { + done = (picoos_strlcpy(name, f->name,maxsize) < maxsize); + } else { + name[0] = (picoos_char)NULLC; + done = FALSE; + } + + return done; +} + +/* Returns whether file 'name' exists or not. */ +picoos_bool picoos_FileExists(picoos_Common g, picoos_char name[]) +{ + picoos_File f; + + if (picoos_OpenBinary(g, & f,name)) { + picoos_CloseBinary(g, & f); + return TRUE; + } else { + return FALSE; + } +} + + +/* ******************************************************************/ +/* Array conversion operations: all procedures convert 'nrElems' values from + 'src' starting with index 'srcStartInd' into corresponding (possibly + rounded) values in 'dst' starting at 'dstStartInd'. */ + +/* taking pi to be le, these are just the array versions of read_mem_pi_*int16 */ +typedef picoos_uint8 two_byte_t[2]; + +static void arr_conv_le_int16 (picoos_uint8 src[], picoos_uint32 srcShortStartInd, picoos_uint32 nrElems, picoos_int16 dst[], picoos_uint32 dstStartInd) +{ + two_byte_t * src_p = (two_byte_t *) (src + (srcShortStartInd * 2)); + picoos_int16 * dst_p = dst + dstStartInd; + picoos_uint32 i; + + for (i=0; i>8); + dst_p++; + } +} + +/* *****************************************************************/ +/* Sampled Data Files */ +/* *****************************************************************/ + +#define PICOOS_SDF_BUF_LEN 1024 + +#define PICOOS_INT16_MIN -32768 +#define PICOOS_INT16_MAX 32767 +#define PICOOS_UINT16_MAX 0xffff +#define PICOOS_INT32_MIN -2147483648 +#define PICOOS_INT32_MAX 2147483647 +#define PICOOS_UINT32_MAX 0xffffffff + +/** object : SDFile + * shortcut : sdf + * + */ +/* typedef struct picoos_sd_file * picoos_SDFile */ +typedef struct picoos_sd_file +{ + picoos_uint32 sf; + wave_file_type_t fileType; /* (acoustic) wav, au, raw, other */ + picoos_uint32 hdrSize; + picoos_encoding_t enc; + picoos_File file; + picoos_uint32 nrFileSamples; + picoos_int16 buf[PICOOS_SDF_BUF_LEN]; + picoos_int32 bufPos; + picoos_uint8 bBuf[2*PICOOS_SDF_BUF_LEN]; + picoos_bool aborted; +} picoos_sd_file_t; + + +/* Tries to read wav header at beginning of file 'f'; + returns sampling rate 'sf', encoding type 'enc', + nr of samples in file 'nrSamples', header size 'hdrSize', + and byte order 'bOrder'; returns whether a supported + wav header and format was found. */ +static picoos_bool picoos_readWavHeader(picoos_File f, picoos_uint32 * sf, + picoos_encoding_t * enc, picoos_uint32 * nrSamples, + picoos_uint32 * hdrSize) { + picoos_uint16 n16; + picoos_uint32 n32; + picoos_uint16 formatTag; + picoos_uint32 sampleRate; + picoos_uint32 bytesPerSec; + picoos_uint16 blockAlign; + picoos_uint16 sampleSize; + picoos_uint32 dataLength; + picoos_uint32 fileLen; + picoos_uint32 nrFileSamples; + picoos_bool done; + + + picoos_SetPos(f, 0); + picoos_FileLength(f, &fileLen); + done = picoos_StrRead(f, (picoos_char *) "RIFF"); + done = done && (PICO_OK == picoos_read_le_uint32(f, &n32)); /* length of riff chunk, unused */ + done = done && picoos_StrRead(f, (picoos_char *) "WAVE"); + done = done && picoos_StrRead(f, (picoos_char *) "fmt "); + done = done && (PICO_OK == picoos_read_le_uint32(f, &n32)); /* length of fmt chunk in bytes; must be 16 */ + done = done && (n32 == 16); + done = done && (PICO_OK == picoos_read_le_uint16(f, &formatTag)); + done = done && (PICO_OK == picoos_read_le_uint16(f, &n16)); /* number of channels; must be mono */ + done = done && (n16 == 1); + done = done && (PICO_OK == picoos_read_le_uint32(f, &sampleRate)); + done = done && (PICO_OK == picoos_read_le_uint32(f, &bytesPerSec)); + done = done && (PICO_OK == picoos_read_le_uint16(f, &blockAlign)); + done = done && (PICO_OK == picoos_read_le_uint16(f, &sampleSize)); + done = done && picoos_StrRead(f, (picoos_char *) "data"); + done = done && (PICO_OK == picoos_read_le_uint32(f, &dataLength)); /* length of data chunk in bytes */ + (*hdrSize) = 44; + if (done) { + (*sf) = sampleRate; + (*nrSamples) = 0; + switch (formatTag) { + case FORMAT_TAG_LIN: + (*enc) = PICOOS_ENC_LIN; + done = ((blockAlign == 2) && (sampleSize == 16)); + (*nrSamples) = (dataLength / 2); + nrFileSamples = ((fileLen - (*hdrSize)) / 2); + break; + case FORMAT_TAG_ULAW: + (*enc) = PICOOS_ENC_ULAW; + done = ((blockAlign == 1) && (sampleSize == 8)); + (*nrSamples) = dataLength; + nrFileSamples = (fileLen - (*hdrSize)); + break; + case FORMAT_TAG_ALAW: + (*enc) = PICOOS_ENC_ALAW; + done = ((blockAlign == 1) && (sampleSize == 8)); + (*nrSamples) = dataLength; + nrFileSamples = (fileLen - (*hdrSize)); + break; + default: + done = FALSE; + break; + } + if (!done) { + /* communicate "unsupported format" */ + PICODBG_WARN(("unsupported wav format")); + } else { + if (nrFileSamples != (*nrSamples)) { + /* warn "inconsistent number of samples" */ + PICODBG_WARN(("inconsistent number of samples in wav file: %d vs. %d",nrFileSamples,(*nrSamples))); + (*nrSamples) = nrFileSamples; + } + } + } + return done; +} + + + +extern picoos_bool picoos_sdfOpenIn(picoos_Common g, picoos_SDFile * sdFile, + picoos_char fileName[], picoos_uint32 * sf, picoos_encoding_t * enc, + picoos_uint32 * numSamples) +{ + picoos_bool done = FALSE; + picoos_sd_file_t * sdf = NULL; + wave_file_type_t fileType = FILE_TYPE_OTHER; + + (*sf) = 0; + (*numSamples) = 0; + (*enc) = PICOOS_ENC_LIN; + (*sdFile) = NULL; + + sdf = picoos_allocate(g->mm,sizeof(picoos_sd_file_t)); + if (NULL == sdf) { + picoos_emRaiseWarning(g->em,PICO_EXC_OUT_OF_MEM,NULL,NULL); + return FALSE; + } + + /* buffered access not supported, yet */ + if (picoos_OpenBinary(g,&(sdf->file),fileName)) { + if (picoos_has_extension(fileName,(picoos_char *) ".wav")) { + fileType = FILE_TYPE_WAV; + done = picoos_readWavHeader(sdf->file,&(sdf->sf),&(sdf->enc),&(sdf->nrFileSamples),&(sdf->hdrSize)); + } else { + /* we prefer not to treat other formats, rather than treat it as raw */ + /* fileType = FILE_TYPE_RAW; */ + fileType = FILE_TYPE_OTHER; + done = FALSE; + } + + if (FILE_TYPE_OTHER == fileType) { + picoos_emRaiseWarning(g->em,PICO_EXC_UNEXPECTED_FILE_TYPE,(picoos_char *)"unsupported filename suffix",NULL); + } else if (!done) { + picoos_emRaiseWarning(g->em,PICO_EXC_UNEXPECTED_FILE_TYPE,(picoos_char *)"non-conforming header",NULL); + } else { + (*numSamples) = sdf->nrFileSamples; + (*sf) = sdf->sf; + (*enc) = sdf->enc; + /* check whether sd file properties are supported */ + if (PICOOS_ENC_LIN != sdf->enc) { + done = FALSE; + picoos_emRaiseWarning(g->em,PICO_EXC_UNEXPECTED_FILE_TYPE,NULL,(picoos_char *)"encoding not supported"); + } + if (SAMPLE_FREQ_16KHZ != sdf->sf) { + done = FALSE; + picoos_emRaiseWarning(g->em,PICO_EXC_UNEXPECTED_FILE_TYPE,NULL,(picoos_char *)"sample frequency not supported"); + } + (*sdFile) = sdf; + } + if (!done){ + picoos_CloseBinary(g,&(sdf->file)); + } + } else { + picoos_emRaiseException(g->em,PICO_EXC_CANT_OPEN_FILE,NULL,NULL); + } + if (!done) { + picoos_deallocate(g->mm,(void *)&sdf); + (*sdFile) = NULL; + } + return done; +} + + +static void picoos_sdfLoadSamples(picoos_SDFile sdFile, + picoos_uint32 * nrSamples) { + picoos_uint32 len; + picoos_sd_file_t * sdf = sdFile; + + switch (sdFile->enc) { + case PICOOS_ENC_LIN: + if ((*nrSamples) > PICOOS_SDF_BUF_LEN) { + (*nrSamples) = PICOOS_SDF_BUF_LEN; + } + len = 2 * (*nrSamples); + picoos_ReadBytes(sdf->file, sdf->bBuf, &len); + (*nrSamples) = len / 2; + arr_conv_le_int16(sdf->bBuf, 0, (*nrSamples), sdf->buf, 0); + break; + /* @todo : may be useful */ + case PICOOS_ENC_ULAW: + case PICOOS_ENC_ALAW: + default: + (*nrSamples) = 0; + } + +} + +extern picoos_bool picoos_sdfGetSamples ( + picoos_SDFile sdFile, + picoos_uint32 start, + picoos_uint32 * nrSamples, + picoos_int16 samples[]) +{ + picoos_uint32 b; + picoos_uint32 rem; + picoos_uint32 n; + picoos_uint32 i; + picoos_uint32 j; + picoos_bool done = FALSE; + + if (NULL == sdFile) { + (*nrSamples) = 0; + } else { + if (start >= sdFile->nrFileSamples) { + if (start > sdFile->nrFileSamples) { + PICODBG_WARN(("start has to be <= sdFile->nrFileSamples")); + } + (*nrSamples) = 0; + } else { + if (((start + (*nrSamples)) > sdFile->nrFileSamples)) { + (*nrSamples) = (sdFile->nrFileSamples - start); + } + if ((sdFile->enc == PICOOS_ENC_LIN)) { + b = 2; + } else { + b = 1; + } + picoos_SetPos(sdFile->file,(sdFile->hdrSize + (b * start))); + j = 0; + rem = (*nrSamples); + n = rem; + while ((rem > 0) && (n > 0)) { + /* set n=min(rem,buffer_length) and try loading next n samples */ + n = (rem < PICOOS_SDF_BUF_LEN) ? rem : PICOOS_SDF_BUF_LEN; + picoos_sdfLoadSamples(sdFile, &n); + /* n may be smaller now */ + for (i = 0; i < n; i++) { + samples[j] = sdFile->buf[i]; + j++; + } + rem -= n; + start += n; + } + (*nrSamples) = j; + done = ((*nrSamples) > 0); + } + } + return done; +} + + +extern picoos_bool picoos_sdfCloseIn (picoos_Common g, picoos_SDFile * sdFile) +{ + if (NULL != (*sdFile)) { + picoos_CloseBinary(g,&((*sdFile)->file)); + picoos_deallocate(g->mm,(void *)sdFile); + } + return TRUE; +} + + +static picoos_bool picoos_writeWavHeader(picoos_File f, picoos_uint32 sf, + picoos_encoding_t enc, picoos_uint32 nrSamples, + picoos_uint32 * hdrSize) { + picoos_uint16 formatTag = FORMAT_TAG_LIN; + picoos_uint32 sampleRate; + picoos_uint32 bytesPerSec; + picoos_uint32 bytesPerSample = 2; + picoos_uint16 blockAlign; + picoos_uint16 sampleSize = 16; + picoos_uint32 dataLength; + picoos_bool done = TRUE; + + picoos_SetPos(f, 0); + + switch (enc) { + case PICOOS_ENC_LIN: + formatTag = FORMAT_TAG_LIN; + bytesPerSample = 2; + sampleSize = 16; + break; + case PICOOS_ENC_ULAW: + formatTag = FORMAT_TAG_ULAW; + bytesPerSample = 1; + sampleSize = 8; + break; + case PICOOS_ENC_ALAW: + formatTag = FORMAT_TAG_ALAW; + bytesPerSample = 1; + sampleSize = 8; + break; + default: + done = FALSE; + break; + } + + bytesPerSec = (sf * bytesPerSample); + blockAlign = bytesPerSample; + sampleRate = sf; + dataLength = (bytesPerSample * nrSamples); + done = done && picoos_WriteStr(f,(picoos_char *)"RIFF"); + done = done && picoos_write_le_uint32(f,dataLength + 36); + done = done && picoos_WriteStr(f,(picoos_char *)"WAVE"); + done = done && picoos_WriteStr(f,(picoos_char *)"fmt "); + done = done && picoos_write_le_uint32(f,16); + done = done && picoos_write_le_uint16(f,formatTag); + done = done && picoos_write_le_uint16(f,1); + done = done && picoos_write_le_uint32(f,sampleRate); + done = done && picoos_write_le_uint32(f,bytesPerSec); + done = done && picoos_write_le_uint16(f,blockAlign); + done = done && picoos_write_le_uint16(f,sampleSize); + done = done && picoos_WriteStr(f,(picoos_char *)"data"); + done = done && picoos_write_le_uint32(f,dataLength); + (*hdrSize) = 44; + return done; +} + + +#define DummyLen 100000000 + +extern picoos_bool picoos_sdfOpenOut(picoos_Common g, picoos_SDFile * sdFile, + picoos_char fileName[], int sf, picoos_encoding_t enc) +{ + picoos_bool done = TRUE; + picoos_sd_file_t * sdf = NULL; + + (*sdFile) = NULL; + sdf = picoos_allocate(g->mm, sizeof(picoos_sd_file_t)); + if (NULL == sdf) { + picoos_emRaiseWarning(g->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); + return FALSE; + } + sdf->sf = sf; + sdf->enc = enc; + /* check whether sd file properties are supported */ + if (PICOOS_ENC_LIN != sdf->enc) { + done = FALSE; + picoos_emRaiseWarning(g->em, PICO_EXC_UNEXPECTED_FILE_TYPE, NULL, + (picoos_char *) "encoding not supported"); + } + if (SAMPLE_FREQ_16KHZ != sdf->sf) { + done = FALSE; + picoos_emRaiseWarning(g->em, PICO_EXC_UNEXPECTED_FILE_TYPE, NULL, + (picoos_char *) "sample frequency not supported"); + } + if (done) { + sdf->nrFileSamples = 0; + sdf->bufPos = 0; + sdf->aborted = FALSE; + if (picoos_CreateBinary(g, &(sdf->file), fileName)) { + if (picoos_has_extension(fileName, (picoos_char *) ".wav")) { + sdf->fileType = FILE_TYPE_WAV; + done = picoos_writeWavHeader(sdf->file, sdf->sf, sdf->enc, + DummyLen, &(sdf->hdrSize)); + } else { + /* we prefer not to treat other formats, rather than treat it as raw */ + /* fileType = FILE_TYPE_RAW; */ + sdf->fileType = FILE_TYPE_OTHER; + done = FALSE; + } + + if (FILE_TYPE_OTHER == sdf->fileType) { + picoos_emRaiseWarning(g->em, PICO_EXC_UNEXPECTED_FILE_TYPE, + (picoos_char *) "unsupported filename suffix", NULL); + } else if (!done) { + picoos_emRaiseWarning(g->em, PICO_EXC_UNEXPECTED_FILE_TYPE, + (picoos_char *) "non-conforming header", NULL); + } else { + (*sdFile) = sdf; + } + if (!done) { + picoos_CloseBinary(g, &(sdf->file)); + } + } else { + picoos_emRaiseException(g->em, PICO_EXC_CANT_OPEN_FILE, NULL, NULL); + } + } + if (!done) { + picoos_deallocate(g->mm, (void *) &sdf); + (*sdFile) = NULL; + } + return done; +} + +static picoos_bool picoos_sdfFlushOutBuf(picoos_SDFile sdFile) +{ + picoos_bool done = FALSE; + picoos_int32 len; + picoos_int32 nrSamples; + + if (!(sdFile->aborted)) { + nrSamples = sdFile->bufPos; + switch (sdFile->enc) { + case PICOOS_ENC_LIN: + arr_conv_int16_le(sdFile->buf, 0, nrSamples, sdFile->bBuf, 0); + len = (nrSamples * 2); + done = picoos_WriteBytes(sdFile->file, sdFile->bBuf, &len) + && ((nrSamples * 2) == len); + break; + case PICOOS_ENC_ULAW: + case PICOOS_ENC_ALAW: + default: + nrSamples = 0; + break; + } + sdFile->nrFileSamples = (sdFile->nrFileSamples + nrSamples); + } + + sdFile->bufPos = 0; + return done; +} + +extern picoos_bool picoos_sdfFlushOutput(picoos_SDFile sdFile) +{ + if ((sdFile != NULL) && !(sdFile->aborted) && (sdFile->bufPos > 0)) { + return picoos_sdfFlushOutBuf(sdFile); + } + return TRUE; +} + + + +extern picoos_bool picoos_sdfPutSamples (picoos_SDFile sdFile, picoos_uint32 nrSamples, picoos_int16 samples[]) +{ + picoos_uint32 i; + picoos_int32 s; + picoos_bool done = FALSE; + + if ((sdFile != NULL) && !(sdFile->aborted)) { + done = TRUE; + for (i = 0; i < nrSamples; i++) { + s = samples[i]; + if ((s > PICOOS_INT16_MAX)) { + s = PICOOS_INT16_MAX; + } else if (s < PICOOS_INT16_MIN) { + s = PICOOS_INT16_MIN; + } + sdFile->buf[sdFile->bufPos++] = s; + if (sdFile->bufPos >= PICOOS_SDF_BUF_LEN) { + done = picoos_sdfFlushOutBuf(sdFile); + } + } + } else { + done = FALSE; + } + return done; +} + + +extern picoos_bool picoos_sdfCloseOut (picoos_Common g, picoos_SDFile * sdFile) +{ + + picoos_bool done = TRUE; + picoos_uint32 hdrSize; + + if (NULL != (*sdFile)) { + if (!((*sdFile)->aborted) && ((*sdFile)->bufPos > 0)) { + done = picoos_sdfFlushOutBuf(*sdFile); + } + if (FILE_TYPE_WAV == (*sdFile)->fileType) { + done = picoos_writeWavHeader((*sdFile)->file, (*sdFile)->sf, + (*sdFile)->enc, (*sdFile)->nrFileSamples, &hdrSize); + } + done = picoos_CloseBinary(g, &((*sdFile)->file)); + picoos_deallocate(g->mm, (void *) sdFile); + } + return done; +} + + +/* *****************************************************************/ +/* FileHeader */ +/* *****************************************************************/ + + + +pico_status_t picoos_clearHeader(picoos_FileHeader header) +{ + picoos_uint8 i; + for (i=0; i < PICOOS_MAX_NUM_HEADER_FIELDS; i++) { + header->field[i].key[0] = NULLC; + header->field[i].value[0] = NULLC; + header->field[i].op = PICOOS_FIELD_IGNORE; + } + header->numFields = 0; + return PICO_OK; +} + +pico_status_t picoos_setHeaderField(picoos_FileHeader header, + picoos_uint8 index, picoos_char * key, picoos_char * value, + picoos_compare_op_t op) +{ + if (index >= header->numFields) { + return PICO_ERR_INDEX_OUT_OF_RANGE; + } + header->field[index].op = op; + if ((picoos_strlcpy(header->field[index].key, key, + PICOOS_MAX_FIELD_STRING_LEN) < PICOOS_MAX_FIELD_STRING_LEN) + && (picoos_strlcpy(header->field[index].value, value, + PICOOS_MAX_FIELD_STRING_LEN)) < PICOOS_MAX_FIELD_STRING_LEN) { + return PICO_OK; + } else { + return PICO_ERR_INDEX_OUT_OF_RANGE; + } +} + + +/* caller has to make sure allocated space at key and value are large enough to hold a picoos_field_string */ +pico_status_t picoos_getHeaderField(picoos_FileHeader header, picoos_uint8 index, picoos_field_string_t key, picoos_field_string_t value, picoos_compare_op_t * op) +{ + if (index >= header->numFields) { + return PICO_ERR_INDEX_OUT_OF_RANGE; + } + *op = header->field[index].op; + if ((picoos_strlcpy(key,header->field[index].key, + PICOOS_MAX_FIELD_STRING_LEN) < PICOOS_MAX_FIELD_STRING_LEN) + && (picoos_strlcpy(value,header->field[index].value, + PICOOS_MAX_FIELD_STRING_LEN)) < PICOOS_MAX_FIELD_STRING_LEN) { + return PICO_OK; + } else { + return PICO_ERR_INDEX_OUT_OF_RANGE; + } + return PICO_OK; +} + + +/* check whether 'str' of length strlen matches contents in circular buffer buf, located in the first strlen bytes and ending + * position bufpos. */ +static picoos_uint8 os_matched( picoos_char * str, picoos_uint32 strlen, picoos_char * buf, picoos_int32 bufpos) { + picoos_int32 i = strlen-1; + while (i >= 0 && buf[bufpos] == str[i]) { + i--; + bufpos--; + if (bufpos < 0) { + bufpos = strlen-1; + } + } + return (i<0); +} + +pico_status_t picoos_getSVOXHeaderString(picoos_char * str, picoos_uint8 * len, picoos_uint32 maxlen) +{ + picoos_char * ch; + *len = picoos_strlcpy(str,picoos_SVOXFileHeader,maxlen); + if (*len < maxlen) { + ch = str; + /* SVOX header is made less readable */ + while (*ch) { + *ch -= ' '; + ch++; + } + return PICO_OK; + } else { + return PICO_ERR_OTHER; + } +} + +pico_status_t picoos_readPicoHeader(picoos_File f, picoos_uint32 * headerlen) +{ + picoos_char str[32]; + picoos_char buf[32]; + picoos_uint8 strlen, bufpos; + picoos_uint32 n; + picoos_uint8 done; + + picoos_getSVOXHeaderString(str,&strlen,32); + /* search for svox header somewhere near the file start. This allows for initial + * non-svox-header bytes for a customer-specific header and/or filling bytes for alignment */ + *headerlen = 0; + /* read in initial chunk of length strlen */ + n = strlen; + done = picoos_ReadBytes(f,(picoos_uint8 *)buf,&n) && (n == strlen); + if (done) { + *headerlen = n; + bufpos = strlen-1; /* last legal buf position */ + done = os_matched(str,strlen,buf,bufpos); + while (!done && *headerlen < PICO_MAX_FOREIGN_HEADER_LEN) { + n = 1; + bufpos = (bufpos + 1) % strlen; + done = picoos_ReadBytes(f,(picoos_uint8 *)buf+bufpos,&n) && 1 == n; + done = done && os_matched(str,strlen,buf,bufpos); + headerlen++; + } + } + if (done) { + return PICO_OK; + } else { + return PICO_EXC_UNEXPECTED_FILE_TYPE; + } +} + +picoos_uint8 picoos_get_str (picoos_char * fromStr, picoos_uint32 * pos, picoos_char * toStr, picoos_objsize_t maxsize) +{ + picoos_uint8 i = 0; + /* skip non-printables */ + + while ((fromStr[*pos] != NULLC) && (fromStr[*pos] <= ' ')) { + (*pos)++; + } + /* copy printable portion */ + while ((fromStr[*pos] != NULLC) && (fromStr[*pos] > ' ') && (i < maxsize-1)) { + toStr[i++] = fromStr[(*pos)++]; + } + toStr[i] = NULLC; + return (i > 0) && (fromStr[*pos] <= ' '); +} + +pico_status_t picoos_hdrParseHeader(picoos_FileHeader header, picoos_header_string_t str) +{ + picoos_uint32 curpos = 0; + picoos_uint8 i, numFields; + + + /* read number of fields */ + numFields = str[curpos++]; + numFields = os_min(numFields,PICOOS_MAX_NUM_HEADER_FIELDS); + /* read in all field pairs */ + PICODBG_DEBUG(("number of fields = %i", numFields)); + for (i = 0; i < numFields; i++) { + picoos_get_str(str,&curpos,header->field[i].key,PICOOS_MAX_FIELD_STRING_LEN); + picoos_get_str(str,&curpos,header->field[i].value,PICOOS_MAX_FIELD_STRING_LEN); + } + return PICO_OK; +} + + + + + +/* **************************************************************************/ +/* Read little-endian / platform-independent integers from file or memory */ +/* **************************************************************************/ + +/* read little-endian */ +pico_status_t picoos_read_le_uint16 (picoos_File file, picoos_uint16 * val) +{ + picoos_uint8 by[2]; + picoos_uint32 n = 2; + if (picoos_ReadBytes(file, by, &n) && 2 == n) { + /* little-endian */ + *val = (picoos_uint16) by[1] << 8 | (picoos_uint16) by[0]; + return PICO_OK; + } else { + *val = 0; + return PICO_ERR_OTHER; + } +} + +pico_status_t picoos_read_le_int16 (picoos_File file, picoos_int16 * val) +{ + return picoos_read_le_uint16(file, (picoos_uint16 *)val); +} + +pico_status_t picoos_read_le_uint32 (picoos_File file, picoos_uint32 * val) +{ + picoos_uint8 by[4]; + picoos_uint32 n = 4; + if (picoos_ReadBytes(file, by, &n) && (4 == n)) { + /* little-endian */ + PICODBG_TRACE(("reading uint 32: %i %i %i %i", + by[0], by[1], by[2], by[3])); + *val = (((picoos_uint32) by[3] << 8 | (picoos_uint32) by[2]) << 8 | (picoos_uint32) by[1]) << 8 | (picoos_uint32) by[0]; + PICODBG_TRACE(("uint 32: %i %i %i %i corresponds %i", + by[0], by[1], by[2], by[3], *val)); + return PICO_OK; + } else { + *val = 0; + return PICO_ERR_OTHER; + } +} + +/* platform-independent */ +/* our convention is that pi is little-endian. */ + +/** @todo : direct implementation if too slow */ + +pico_status_t picoos_read_pi_uint16 (picoos_File file, picoos_uint16 * val) +{ + return picoos_read_le_uint16(file,val); +} + +pico_status_t picoos_read_pi_uint32 (picoos_File file, picoos_uint32 * val) +{ + return picoos_read_le_uint32(file, val); +} + +pico_status_t picoos_read_pi_int32 (picoos_File file, picoos_int32 * val) +{ + return picoos_read_le_uint32(file, (picoos_uint32 *)val); +} + +/* read pi from memory */ + +pico_status_t picoos_read_mem_pi_uint16 (picoos_uint8 * data, picoos_uint32 * pos, picoos_uint16 * val) +{ + picoos_uint8 * by = data + *pos; + + /* little-endian */ + *val = (picoos_uint16) by[1] << 8 | (picoos_uint16) by[0]; + (*pos) += 2; + return PICO_OK; +} + +pico_status_t picoos_read_mem_pi_uint32 (picoos_uint8 * data, picoos_uint32 * pos, picoos_uint32 * val) +{ + picoos_uint8 * by = data + *pos; + + /* little-endian */ + *val = (((picoos_uint32) by[3] << 8 | (picoos_uint32) by[2]) << 8 | (picoos_uint32) by[1]) << 8 | (picoos_uint32) by[0]; + (*pos) += 4; + return PICO_OK; +} + +/* **************************************************************************/ +/* Write little-endian / platform-independent integers into file or memory */ +/* **************************************************************************/ +/* write little-endian */ +pico_status_t picoos_write_le_uint16 (picoos_File file, picoos_uint16 val) +{ + picoos_int32 len = 2; + picoos_uint8 by[2]; + + by[0] = (picoos_uint8)((val) & 0x00FF); + by[1] = (picoos_uint8)(((val) & 0xFF00)>>8); + return (picoos_WriteBytes(file,by,&len) && (2 == len)); +} +pico_status_t picoos_write_le_uint32 (picoos_File file, picoos_uint32 val) +{ + picoos_int32 len = 4; + picoos_uint8 by[4]; + + by[0] = (picoos_uint8)(val & 0x000000FF); + by[1] = (picoos_uint8)((val & 0x0000FF00)>>8); + by[2] = (picoos_uint8)((val & 0x00FF0000)>>16); + by[3] = (picoos_uint8)((val & 0xFF000000)>>24); + return (picoos_WriteBytes(file,by,&len) && (4 == len)); +} + +/* write pi to mem */ +pico_status_t picoos_write_mem_pi_uint16 (picoos_uint8 * data, picoos_uint32 * pos, picoos_uint16 val) +{ + picoos_uint8 * by = data + *pos; + /* little-endian */ + by[0] = (picoos_uint8)((val) & 0x00FF); + by[1] = (picoos_uint8)(((val) & 0xFF00)>>8); + (*pos) += 2; + return PICO_OK; +} + +/* *****************************************************************/ +/* String search and compare operations */ +/* *****************************************************************/ + +/* this function is case-sensitive */ +picoos_uint8 picoos_has_extension(const picoos_char *str, const picoos_char *suf) +{ + picoos_int32 istr = picoos_strlen(str)-1; + picoos_int32 isuf = picoos_strlen(suf)-1; + while ((istr >= 0) && (isuf >=0) && (str[istr] == suf[isuf])) { + istr--; + isuf--; + } + return (isuf < 0); +} + + +/* *****************************************************************/ +/* String/Number Conversions (may be moved to picopal) */ +/* *****************************************************************/ + +pico_status_t picoos_string_to_int32(picoos_char str[], + picoos_int32 * res) +{ + /* syntax: [+|-] dig {dig} */ + + int i; + int neg; + int val; + int err; + + err = 0; + i = 0; + while ((str[i] <= ' ') && (str[i] != '\0')) { + i++; + } + neg = 0; + if (str[i] == '-') { + neg = 1; + i++; + } else if (str[i] == '+') { + i++; + } + val = 0; + if ((str[i] < '0') || (str[i]> '9')) { + err = 1; + } + while ((str[i] >= '0') && (str[i] <= '9')) { + val = val * 10 + (str[i] - '0'); + i++; + } + while ((str[i] <= ' ') && (str[i] != '\0')) { + i++; + } + if (neg == 1) { + val = -val; + } + if ((err == 0) && (str[i] == '\0')) { + (*res) = val; + return PICO_OK; + } else { + (*res) = 0; + return PICO_EXC_NUMBER_FORMAT; + } +} + +pico_status_t picoos_string_to_uint32(picoos_char str[], + picoos_uint32 * res) +{ + /* syntax: [+] dig {dig} */ + + int i; + int val; + int err; + + err = 0; + i = 0; + while ((str[i] <= ' ') && (str[i] != '\0')) { + i++; + } + if (str[i] == '+') { + i++; + } + val = 0; + if ((str[i] < '0') || (str[i]> '9')) { + err = 1; + } + while ((str[i] >= '0') && (str[i] <= '9')) { + val = val * 10 + (str[i] - '0'); + i++; + } + while ((str[i] <= ' ') && (str[i] != '\0')) { + i++; + } + if ((err == 0) && (str[i] == '\0')) { + (*res) = val; + return PICO_OK; + } else { + (*res) = 0; + return PICO_EXC_NUMBER_FORMAT; + } +} + +/* 'stringlen' is the part of input string to be considered, + * possibly not containing NULLC (e.g. result of strlen). + * 'maxsize' is the maximal size of 'part' including a byte + * for the terminating NULLC! */ +void picoos_get_sep_part_str(picoos_char string[], + picoos_int32 stringlen, picoos_int32 * ind, picoos_char sepCh, + picoos_char part[], picoos_int32 maxsize, picoos_uint8 * done) +{ + + picoos_int32 j; + picoos_uint8 done1; + + if (((*ind) >= stringlen)) { + (*done) = 0; + part[0] = (picoos_char) NULLC; + } else { + done1 = 1; + j = 0; + while ((((*ind) < stringlen) && (string[(*ind)] != sepCh)) && (string[((*ind))] != (picoos_char)NULLC)) { + if ((j < maxsize-1)) { + part[(j)] = string[(*ind)]; + j++; + } else { + done1 = 0; + } + (*ind)++; + } + part[j] = (picoos_char)NULLC; + if ((*ind) < stringlen) { + if ((string[(*ind)] == sepCh)) { + (*ind)++; /* skip separator character */ + } else if (string[(*ind)] == (picoos_char)NULLC) { + /* reached end of input; set ind to stringlen so that no + more (empty) partial strings will be found */ + (*ind) = stringlen; + } + } + (*done) = done1; + } +} + +/* *****************************************************************/ +/* timer function */ +/* *****************************************************************/ + +extern void picoos_get_timer(picopal_uint32 * sec, picopal_uint32 * usec) +{ + picopal_get_timer(sec, usec); +} + +#ifdef __cplusplus +} +#endif + + +/* end */ diff --git a/pico/lib/picoos.h b/pico/lib/picoos.h new file mode 100644 index 0000000..859e176 --- /dev/null +++ b/pico/lib/picoos.h @@ -0,0 +1,550 @@ +/* + * 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 picoos.h + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +/** + * @addtogroup picoos + + * Operating system generalization module \n + * +*/ + +#ifndef PICOOS_H_ +#define PICOOS_H_ + +#include "picodefs.h" +#include "picopal.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* some "switch" used in picopal and in picocep ... */ +#define PICOOS_DIV_USE_INV PICOPAL_DIV_USE_INV + +/* *************************************************/ +/* types */ +/* *************************************************/ + +typedef picopal_uint8 picoos_uint8; +typedef picopal_uint16 picoos_uint16; +typedef picopal_uint32 picoos_uint32; + +typedef picopal_int8 picoos_int8; +typedef picopal_int16 picoos_int16; +typedef picopal_int32 picoos_int32; + +typedef picopal_double picoos_double; +typedef picopal_single picoos_single; + +typedef picopal_char picoos_char; +typedef picopal_uchar picoos_uchar; + +typedef picopal_uint8 picoos_bool; + +typedef picopal_objsize_t picoos_objsize_t; +typedef picopal_ptrdiff_t picoos_ptrdiff_t; + +/* *************************************************/ +/* functions */ +/* *************************************************/ + + +picoos_int32 picoos_atoi(const picoos_char *); +picoos_int8 picoos_strcmp(const picoos_char *, const picoos_char *); +picoos_int8 picoos_strncmp(const picoos_char *a, const picoos_char *b, picoos_objsize_t siz); +picoos_uint32 picoos_strlen(const picoos_char *); +picoos_char * picoos_strchr(const picoos_char *, picoos_char); +picoos_char *picoos_strstr(const picoos_char *s, const picoos_char *substr); +picoos_int16 picoos_slprintf(picoos_char * b, picoos_uint32 bsize, const picoos_char *f, ...); +picoos_char * picoos_strcpy(picoos_char *, const picoos_char *); +picoos_char * picoos_strcat(picoos_char *, const picoos_char *); + +/* copies 'length' bytes from 'src' to 'dest'. (regions may be overlapping) no error checks! */ +void * picoos_mem_copy(const void * src, void * dst, picoos_objsize_t length); + +/* safe versions */ +picoos_objsize_t picoos_strlcpy(picoos_char *dst, const picoos_char *src, picoos_objsize_t siz); +void * picoos_mem_set(void * dest, picoos_uint8 byte_val, picoos_objsize_t length); + +picoos_double picoos_cos(const picoos_double cos_arg); +picoos_double picoos_sin(const picoos_double sin_arg); +picoos_double picoos_fabs(const picoos_double fabs_arg); + +picoos_double picoos_quick_exp(const picoos_double y); + + +void picoos_get_sep_part_str (picoos_char string[], picoos_int32 stringlen, picoos_int32 * ind, picoos_char sepCh, picoos_char part[], picoos_int32 maxsize, picoos_uint8 * done); +pico_status_t picoos_string_to_uint32 (picoos_char str[], picoos_uint32 * res); +pico_status_t picoos_string_to_int32 (picoos_char str[], picoos_int32 * res); + +/* *****************************************************************/ +/* "Common" */ +/* *****************************************************************/ +/* picoos_common is a collection of basic functionalities that must be globally accesible from every "big" function. + * It includes pointers to the MemoryManasger, ExceptionManager and a list of open files. */ + +typedef struct memory_manager * picoos_MemoryManager; +typedef struct picoos_exception_manager * picoos_ExceptionManager; +typedef struct picoos_file * picoos_File; + + +/** object : Common + * shortcut : common + * + */ +typedef struct picoos_common * picoos_Common; + +/* the picoos_common structure itself is exported so no access functions are needed. Handle with care! (might be changed later) */ +typedef struct picoos_common { + picoos_ExceptionManager em; + picoos_MemoryManager mm; + picoos_File fileList; +} picoos_common_t; + +picoos_Common picoos_newCommon(picoos_MemoryManager mm); + +void picoos_disposeCommon(picoos_MemoryManager mm, picoos_Common * this); + + +/* *****************************************************************/ +/* Memory Management */ +/* *****************************************************************/ + +typedef picoos_char * byte_ptr_t; + +#define PICOOS_ALIGN_SIZE 8 + + + +void * picoos_raw_malloc(byte_ptr_t raw_mem, + picoos_objsize_t raw_mem_size, picoos_objsize_t alloc_size, + byte_ptr_t * rest_mem, picoos_objsize_t * rest_mem_size); + +/** + * Creates a new memory manager object for the specified raw memory + * block. 'enableProtMem' enables or disables memory protection + * functionality; if disabled, picoos_protectMem() has no effect. + */ +picoos_MemoryManager picoos_newMemoryManager( + void *raw_memory, + picoos_objsize_t size, + picoos_bool enableMemProt); + + + +void picoos_disposeMemoryManager(picoos_MemoryManager * mm); + + +void * picoos_allocate(picoos_MemoryManager this, picoos_objsize_t byteSize); +void picoos_deallocate(picoos_MemoryManager this, void * * adr); + +/* the following memory manager routines are for testing and + debugging purposes */ + +/** + * Same as picoos_allocate, but write access to the memory block may be + * prohibited by a subsequent call to picoos_protectMem(). + */ +void *picoos_allocProtMem(picoos_MemoryManager mm, picoos_objsize_t byteSize); + +/** + * Releases a memory block previously allocated by picoos_allocProtMem(). + */ +void picoos_deallocProtMem(picoos_MemoryManager mm, void **addr); + +/** + * Enables or disables write protection of a memory block previously + * allocated by picoos_allocProtMem(). If write protection is enabled, + * any subsequent write access will cause a segmentation fault. + */ +void picoos_protectMem( + picoos_MemoryManager mm, + void *addr, + picoos_objsize_t len, + picoos_bool enable); + +void picoos_getMemUsage( + picoos_MemoryManager this, + picoos_bool resetIncremental, + picoos_int32 *usedBytes, + picoos_int32 *incrUsedBytes, + picoos_int32 *maxUsedBytes); + +void picoos_showMemUsage( + picoos_MemoryManager this, + picoos_bool incremental, + picoos_bool resetIncremental); + +/* *****************************************************************/ +/* Exception Management */ +/* *****************************************************************/ +/** object : ExceptionManager + * shortcut : em + * + */ + + +#define PICOOS_MAX_EXC_MSG_LEN 512 +#define PICOOS_MAX_WARN_MSG_LEN 64 +#define PICOOS_MAX_NUM_WARNINGS 8 + +void picoos_setErrorMsg(picoos_char * dst, picoos_objsize_t siz, + picoos_int16 code, picoos_char * base, const picoos_char *fmt, ...); + + +picoos_ExceptionManager picoos_newExceptionManager(picoos_MemoryManager mm); + +void picoos_disposeExceptionManager(picoos_MemoryManager mm, + picoos_ExceptionManager * this); + + +void picoos_emReset(picoos_ExceptionManager this); + +/* For convenience, this function returns the resulting exception code of 'this' + * (as would be returned by emGetExceptionCode). + * The return value therefore is NOT the status of raising + * the error! */ +pico_status_t picoos_emRaiseException(picoos_ExceptionManager this, + pico_status_t exceptionCode, picoos_char * baseMessage, picoos_char * fmt, ...); + +pico_status_t picoos_emGetExceptionCode(picoos_ExceptionManager this); + +void picoos_emGetExceptionMessage(picoos_ExceptionManager this, picoos_char * msg, picoos_uint16 maxsize); + +void picoos_emRaiseWarning(picoos_ExceptionManager this, + pico_status_t warningCode, picoos_char * baseMessage, picoos_char * fmt, ...); + +picoos_uint8 picoos_emGetNumOfWarnings(picoos_ExceptionManager this); + +pico_status_t picoos_emGetWarningCode(picoos_ExceptionManager this, picoos_uint8 warnNum); + +void picoos_emGetWarningMessage(picoos_ExceptionManager this, picoos_uint8 warnNum, picoos_char * msg, picoos_uint16 maxsize); + + + + +/* *****************************************************************/ +/* File Access */ +/* *****************************************************************/ + +#define picoos_MaxFileNameLen 512 +#define picoos_MaxKeyLen 512 +#define picoos_MaxPathLen 512 +#define picoos_MaxPathListLen 2048 + +typedef picoos_char picoos_Key[picoos_MaxKeyLen]; +typedef picoos_char picoos_FileName[picoos_MaxFileNameLen]; +typedef picoos_char picoos_Path[picoos_MaxPathLen]; +typedef picoos_char picoos_PathList[picoos_MaxPathListLen]; + + +/* ***** Sequential binary file access ******/ + +/* Remark: 'ReadByte', 'ReadBytes' and 'ReadVar' may be mixed; + 'WriteByte', 'WriteBytes' and 'WriteVar' may be mixed. */ + +/* Open existing binary file for read access. */ +picoos_uint8 picoos_OpenBinary(picoos_Common g, picoos_File * f, picoos_char name[]); + + +/* Read next byte from file 'f'. */ +picoos_uint8 picoos_ReadByte(picoos_File f, picoos_uint8 * by); + +/* Read next 'len' bytes from 'f' into 'bytes'; 'len' returns the + number of bytes actually read (may be smaller than requested + length if 'bytes' is too small to hold all bytes or at end of file). + Remark: 'bytes' is compabtible with any variable of any size. */ +picoos_uint8 picoos_ReadBytes(picoos_File f, picoos_uint8 bytes[], + picoos_uint32 * len); + + +/* Create new binary file. + If 'key' is not empty, the file is encrypted with 'key'. */ +picoos_uint8 picoos_CreateBinary(picoos_Common g, picoos_File * f, picoos_char name[]); + +picoos_uint8 picoos_WriteByte(picoos_File f, picoos_char by); + +/* Writes 'len' bytes from 'bytes' onto file 'f'; 'len' returns + the number of bytes actually written. */ +picoos_uint8 picoos_WriteBytes(picoos_File f, const picoos_char bytes[], + picoos_int32 * len); + + +/* Close previously opened binary file. */ +picoos_uint8 picoos_CloseBinary(picoos_Common g, picoos_File * f); + + + + + + +pico_status_t picoos_read_le_int16 (picoos_File file, picoos_int16 * val); +pico_status_t picoos_read_le_uint16 (picoos_File file, picoos_uint16 * val); +pico_status_t picoos_read_le_uint32 (picoos_File file, picoos_uint32 * val); + + +pico_status_t picoos_read_pi_uint16 (picoos_File file, picoos_uint16 * val); +pico_status_t picoos_read_pi_uint32 (picoos_File file, picoos_uint32 * val); + +pico_status_t picoos_write_le_uint16 (picoos_File file, picoos_uint16 val); +pico_status_t picoos_write_le_uint32 (picoos_File file, picoos_uint32 val); + +/* +pico_status_t picoos_write_pi_uint32 (picoos_File file, const picoos_uint32 val); + +pico_status_t picoos_write_pi_uint16 (picoos_File file, const picoos_uint16 val); +*/ + + +/* **************************************************************************************/ +/* *** general file routines *****/ + +/* Returns whether end of file was encountered in previous + read operation. */ +picoos_bool picoos_Eof(picoos_File f); + +/* sets the file pointer to + 'pos' bytes from beginning (first byte = byte 0). This + routine should only be used for binary files. */ +picoos_bool picoos_SetPos(picoos_File f, picoos_int32 pos); + +/* Get position from file 'f'. */ +picoos_bool picoos_GetPos(picoos_File f, picoos_uint32 * pos); + +/* Returns the length of the file in bytes. */ +picoos_bool picoos_FileLength(picoos_File f, picoos_uint32 * len); + +/* Return full name of file 'f'. */ +picoos_bool picoos_Name(picoos_File f, picoos_char name[], picoos_uint32 maxsize); + +/* Returns whether file 'name' exists or not. */ +picoos_bool picoos_FileExists(picoos_Common g, picoos_char name[] /*, picoos_char ckey[] */); + +/* Delete a file. */ +picoos_bool picoos_Delete(picoos_char name[]); + +/* Rename a file. */ +picoos_bool picoos_Rename(picoos_char oldName[], picoos_char newName[]); + + +/* *****************************************************************/ +/* Sampled Data Files */ +/* *****************************************************************/ + +#define SAMPLE_FREQ_16KHZ (picoos_uint32) 16000 + +typedef enum { + FILE_TYPE_WAV, + FILE_TYPE_AU, + FILE_TYPE_RAW, + FILE_TYPE_OTHER +} wave_file_type_t; + +typedef enum { + FORMAT_TAG_LIN = 1, /**< linear 16-bit encoding */ + FORMAT_TAG_ALAW = 6, /**< a-law encoding, 8 bit */ + FORMAT_TAG_ULAW = 7 /**< u-law encoding, 8 bit */ + /* there are many more */ +} wave_format_tag_t; + + +typedef enum { + /* values corresponding RIFF wFormatTag */ + PICOOS_ENC_LIN = FORMAT_TAG_LIN, /**< linear 16-bit encoding; standard */ + PICOOS_ENC_ALAW = FORMAT_TAG_ALAW, /**< a-law encoding, 8 bit */ + PICOOS_ENC_ULAW = FORMAT_TAG_ULAW, /**< u-law encoding, 8 bit */ + /* values outside RIFF wFormatTag values (above 4100) */ + PICOOS_ENC_OTHER = 5000 /**< other; (treated as raw) */ + } picoos_encoding_t; + +typedef struct picoos_sd_file * picoos_SDFile; + +/* SDFile input functions */ + +/* orig. comment from SDInOut.def + Opens sampled data file 'fileName' for input and returns + the encoding 'enc' of the file, sampling rate 'sf', + nr of samples 'nrSamples', and a handle to the opened file + in 'sdFile'. + + If 'fileName' is empty, the input is taken from the direct + acoustic input using the sampling rate specified by + "SetRawDefaults". In this case, 'encoding' returns 'EncLin', + and 'nrSamples' returns 0. + + The file format is taken from the file name extension: + ".wav" --> wav file + ".au" --> au file + other extensions --> headerless files + + For wav and au files, the sampling rate and encoding are taken + from the file header and returned in 'sf' and 'enc'. For + headerless files, 'sf' and 'enc' are taken from the + most recently set default values (procedure SetRawDefaults). + + 'done' returns whether the sampled data file was successfully + opened. */ +extern picoos_bool picoos_sdfOpenIn (picoos_Common g, picoos_SDFile * sdFile, picoos_char fileName[], picoos_uint32 * sf, picoos_encoding_t * enc, picoos_uint32 * nrSamples); + + +extern picoos_bool picoos_sdfGetSamples (picoos_SDFile sdFile, picoos_uint32 start, picoos_uint32 * nrSamples, picoos_int16 samples[]); + + +extern picoos_bool picoos_sdfCloseIn (picoos_Common g, picoos_SDFile * sdFile); + + +/* SDFile output functions*/ + +extern picoos_bool picoos_sdfOpenOut (picoos_Common g, picoos_SDFile * sdFile, picoos_char fileName[], int sf, picoos_encoding_t enc); + + +extern picoos_bool picoos_sdfPutSamples (picoos_SDFile sdFile, picoos_uint32 nrSamples, picoos_int16 samples[]); + +/* +extern picoos_bool picoos_AbortOutput (picoos_SDFile sdFile); + + +extern picoos_bool picoos_ResumeOutput (picoos_SDFile sdFile); + + +extern picoos_bool picoos_FlushOutput (picoos_SDFile sdFile); +*/ + +extern picoos_bool picoos_sdfCloseOut (picoos_Common g, picoos_SDFile * sdFile); + + +/* *****************************************************************/ +/* File Headers */ +/* *****************************************************************/ + +#define PICOOS_MAX_FIELD_STRING_LEN 32 /* including terminating char */ + +#define PICOOS_MAX_NUM_HEADER_FIELDS 10 +#define PICOOS_NUM_BASIC_HEADER_FIELDS 5 + +#define PICOOS_HEADER_NAME 0 +#define PICOOS_HEADER_VERSION 1 +#define PICOOS_HEADER_DATE 2 +#define PICOOS_HEADER_TIME 3 +#define PICOOS_HEADER_CONTENT_TYPE 4 + +#define PICOOS_MAX_HEADER_STRING_LEN (PICOOS_MAX_NUM_HEADER_FIELDS * (2 * PICOOS_MAX_FIELD_STRING_LEN)) + +typedef picoos_char picoos_field_string_t[PICOOS_MAX_FIELD_STRING_LEN]; + +typedef picoos_char picoos_header_string_t[PICOOS_MAX_HEADER_STRING_LEN]; + +typedef enum {PICOOS_FIELD_IGNORE, PICOOS_FIELD_EQUAL, PICOOS_FIELD_COMPAT} picoos_compare_op_t; + +/* private */ +typedef struct picoos_file_header_field { + picoos_field_string_t key; + picoos_field_string_t value; + picoos_compare_op_t op; +} picoos_file_header_field_t; + +/* public */ +typedef struct picoos_file_header * picoos_FileHeader; +typedef struct picoos_file_header { + picoos_uint8 numFields; + picoos_file_header_field_t field[PICOOS_MAX_NUM_HEADER_FIELDS]; +} picoos_file_header_t; + + +pico_status_t picoos_clearHeader(picoos_FileHeader header); + +pico_status_t picoos_setHeaderField(picoos_FileHeader header, picoos_uint8 index, picoos_char * key, picoos_char * value, picoos_compare_op_t op); + +/* caller has to make sure allocated space at key and value are large enough to hold a picoos_field_string */ +pico_status_t picoos_getHeaderField(picoos_FileHeader header, picoos_uint8 index, picoos_field_string_t key, picoos_field_string_t value, picoos_compare_op_t * op); + +/* caller has to make sure allocated space at str is large enough to hold the header in question */ +/* +pico_status_t picoos_hdrToString(picoos_FileHeader header, picoos_header_string_t str); +*/ + +pico_status_t picoos_hdrParseHeader(picoos_FileHeader header, picoos_header_string_t str); + +pico_status_t picoos_getSVOXHeaderString(picoos_char * str, picoos_uint8 * len, picoos_uint32 maxlen); + +pico_status_t picoos_readPicoHeader(picoos_File f, picoos_uint32 * headerlen); + + + +/* *****************************************************************/ +/* String search and compare operations */ +/* *****************************************************************/ + + +picoos_uint8 picoos_has_extension(const picoos_char *str, const picoos_char *suf); + +/* *****************************************************************/ +/* String/Number Manipulations (might be moved to picopal) */ +/* *****************************************************************/ + +pico_status_t picoos_string_to_int32(picoos_char str[], + picoos_int32 * res); + +pico_status_t picoos_string_to_uint32(picoos_char str[], + picoos_uint32 * res); + +/* 'stringlen' is the part of input string to be considered, possibly not containing NULLC (e.g. result of strlen). + * 'maxsize' is the maximal size of 'part' including a byte for the terminating NULLC! */ +void picoos_get_sep_part_str(picoos_char string[], + picoos_int32 stringlen, picoos_int32 * ind, picoos_char sepCh, + picoos_char part[], picoos_int32 maxsize, picoos_uint8 * done); + +/* searches for the first contiguous string of printable characters (> ' ') inside fromStr, possibly skipping + * chars <= ' ') and returns it in toStr. + * fromStr is assumed to be NULLC terminated and toStr is forced to be NULLC terminated within maxsize. + * The search is started at *pos inside fromStr and at return, *pos is the position within fromStr after the + * found string, or the position after the end of fromStr, if no string was found. + * the function returns TRUE if a string was found and fitted toStr, or FALSE otherwise. */ +picoos_uint8 picoos_get_str (picoos_char * fromStr, picoos_uint32 * pos, picoos_char * toStr, picoos_objsize_t maxsize); + + +pico_status_t picoos_read_mem_pi_uint16 (picoos_uint8 * data, picoos_uint32 * pos, picoos_uint16 * val); + +pico_status_t picoos_read_mem_pi_uint32 (picoos_uint8 * data, picoos_uint32 * pos, picoos_uint32 * val); + +pico_status_t picoos_write_mem_pi_uint16 (picoos_uint8 * data, picoos_uint32 * pos, picoos_uint16 val); + + +/* *****************************************************************/ +/* timer function */ +/* *****************************************************************/ + +void picoos_get_timer(picopal_uint32 * sec, picopal_uint32 * usec); + +#ifdef __cplusplus +} +#endif + + +#endif /*PICOOS_H_*/ diff --git a/pico/lib/picopal.c b/pico/lib/picopal.c new file mode 100644 index 0000000..db05e2b --- /dev/null +++ b/pico/lib/picopal.c @@ -0,0 +1,554 @@ +/* + * 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 picopal.c + * + * pico platform abstraction layer + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +/* GCC does not supporte #pragma message */ +#if !defined(__GNUC__) +#define PRAGMA_MESSAGE +#endif + +#if defined(PRAGMA_MESSAGE) && defined(PICO_PLATFORM) +#pragma message("PICO_PLATFORM : is defined externally") +#endif + +#if defined(PRAGMA_MESSAGE) && defined(_WIN32) +#pragma message("_WIN32 : is defined") +#endif + +#if defined(PRAGMA_MESSAGE) && defined(__APPLE__) +#pragma message("__APPLE__ : is defined") +#endif + +#if defined(PRAGMA_MESSAGE) && defined(__MACH__) +#pragma message("__MACH__ : is defined") +#endif + +#if defined(PRAGMA_MESSAGE) && defined(macintosh) +#pragma message("macintosh : is defined") +#endif + +#if defined(PRAGMA_MESSAGE) && defined(linux) +#pragma message("linux : is defined") +#endif +#if defined(PRAGMA_MESSAGE) && defined(__linux__) +#pragma message("__linux__ : is defined") +#endif +#if defined(PRAGMA_MESSAGE) && defined(__linux) +#pragma message("__linux : is defined") +#endif + + +#include +#include +#include +#include + +#include "picodefs.h" +#include "picopal.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +#if PICO_PLATFORM == PICO_Windows +/* use high-resolution timer functions on Windows platform */ +#define USE_CLOCK 0 +#else +/* use clock() function instead of high-resolution timer on + non-Windows platforms */ +#define USE_CLOCK 1 +#endif + +#include +#if PICO_PLATFORM == PICO_Windows +#include +#endif + +#if defined(PRAGMA_MESSAGE) +#pragma message("PICO_PLATFORM : " PICO_PLATFORM_STRING) +#endif + + +picopal_int32 picopal_atoi(const picopal_char *s) { + return (picopal_int32)atoi((const char *)s); +} + +picopal_int32 picopal_strcmp(const picopal_char *a, const picopal_char *b) { + return (picopal_int32)strcmp((const char *)a, (const char *)b); +} + +picopal_int32 picopal_strncmp(const picopal_char *a, const picopal_char *b, picopal_objsize_t siz) { + return (picopal_int32)strncmp((const char *)a, (const char *)b, (size_t) siz); +} + +picopal_objsize_t picopal_strlen(const picopal_char *s) { + return (picopal_objsize_t)strlen((const char *)s); +} + +picopal_char *picopal_strchr(const picopal_char *s, picopal_char c) { + return (picopal_char *)strchr((const char *)s, (int)c); +} + +picopal_char *picopal_strstr(const picopal_char *s, const picopal_char *substr) { + return (picopal_char *)strstr((const char *)s, (const char *)substr); +} + +picopal_char *picopal_strcpy(picopal_char *d, const picopal_char *s) { + return (picopal_char *)strcpy((char *)d, (const char *)s); +} + +picopal_char *picopal_strcat(picopal_char *dest, const picopal_char *src) { + return (picopal_char *)strcat((char *)dest, (const char *)src); +} + + +/* copy src into dst, but make sure that dst is not accessed beyond its size 'siz' and is allways NULLC-terminated. + * 'siz' is the number of bytes of the destination, including one byte for NULLC! + * returns the full length of the input string, not including termination NULLC (strlen(src)). + * the copy is successfull without truncation if picopal_strlcpy(dst,src,siz) < siz */ +picopal_objsize_t picopal_strlcpy(picopal_char *dst, const picopal_char *src, picopal_objsize_t siz) +{ + picopal_char *d = dst; + const picopal_char *s = src; + picopal_objsize_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*(d++) = *(s++)) == NULLC) { + break; + } + } + } + + /* Not enough room in dst, add NULLC and traverse rest of src */ + if (n == 0) { + if (siz != 0) { + *d = NULLC; /* NULLC-terminate dst */ + } + while (*(s++)) {} + ; + } + + return(s - src - 1); /* count does not include NULLC */ +} + + +picopal_int16 picopal_sprintf(picopal_char * dst, const picopal_char *fmt, ...) +{ + picopal_int16 i; + va_list args; + + va_start(args, (char *)fmt); + i = (picopal_int16)vsprintf((char *) dst, (const char *)fmt, args); + va_end(args); + return i; +} + + +picopal_objsize_t picopal_vslprintf(picopal_char * dst, picopal_objsize_t siz, const picopal_char *fmt, va_list args) { + picopal_char buf[21]; + picopal_char *d = dst; + const picopal_char *f = fmt; + picopal_char * b; + picopal_objsize_t len, nnew, n = siz; + picopal_int32 ival; + picopal_char cval; + picopal_objsize_t i = 0; + + if (!f) { + f = (picopal_char *) ""; + } + while (*f) { + if (*f == '%') { + switch (*(++f)) { + case 'i': + f++; + ival = va_arg(args,int); + picopal_sprintf(buf,(picopal_char *)"%i",ival); + b = buf; + break; + case 'c': + f++; + cval = va_arg(args,int); + picopal_sprintf(buf,(picopal_char *)"%c",cval); + b = buf; + break; + case 's': + f++; + b = (picopal_char *) va_arg(args, char*); + break; + default: + if (n > 0) { + (*d++) = '%'; + n--; + } + i++; + b = NULL; + break; + } + if (b) { + len = picopal_strlcpy(d,b,n); /* n1 is the actual length of sval */ + i += len; + nnew = (n > len) ? n-len : 0; /* nnew is the new value of n */ + d += (n - nnew); + n = nnew; + } + } else { + if (n) { + (*d++) = (*f); + n--; + } + i++; + f++; + } + } + + return i; +} + +picopal_objsize_t picopal_slprintf(picopal_char * dst, picopal_objsize_t siz, const picopal_char *fmt, /*args*/ ...) { + picopal_objsize_t i; + va_list args; + + va_start(args, (char *)fmt); + i = picopal_vslprintf(dst, siz, fmt, args); + va_end(args); + return i; + +} + + +/* copies 'length' bytes from 'src' to 'dest'. (regions may be overlapping) no error checks! */ +void * picopal_mem_copy(const void * src, void * dst, picopal_objsize_t length) +{ + return memmove(dst, src, (size_t) length); +} + +/* sets 'length' bytes starting at dest[0] to 'byte_val' */ +void * picopal_mem_set(void * dest, picopal_uint8 byte_val, picopal_objsize_t length) +{ + return memset(dest, (int) byte_val, (size_t) length); +} + +/* *************************************************/ +/* fixed-point math */ +/* *************************************************/ + +/* *************************************************/ +/* transcendent math */ +/* *************************************************/ + + +picopal_double picopal_cos(const picopal_double cos_arg) +{ + return (picopal_double) cos((double)cos_arg); +} +picopal_double picopal_sin(const picopal_double sin_arg) +{ + return (picopal_double) sin((double) sin_arg); +} +picopal_double picopal_fabs(const picopal_double fabs_arg) +{ + return (picopal_double) fabs((double) fabs_arg); +} + + +/* *************************************************/ +/* file access */ +/* *************************************************/ +#define PICOPAL_EOL '\n' + +picopal_char picopal_eol(void) +{ + return PICOPAL_EOL; +} + +/* 'fopen' opens the file with name 'filename'. Depending on + 'mode' : + 'PICOPAL_TEXT_READ' : Opens an existing text file for reading. + The file is positioned at the beginning of the file. + 'PICOPAL_TEXT_WRITE' : Opens and truncates an existing file or creates a new + text file for writing. The file is positioned at the + beginning. + 'PICOPAL_BIN_READ' : Opens an existing binary file for reading. + The file is positioned at the beginning of the file. + 'PICOPAL_BIN_WRITE' : Opens and truncates an existing file or creates a new + binary file for writing. The file is positioned at the + beginning. + If the opening of the file is successful a file pointer is given + back. Otherwise a NIL-File is given back. +*/ +picopal_File picopal_fopen (picopal_char filename[], picopal_access_mode mode) +{ + picopal_File res; + + switch (mode) { + case PICOPAL_TEXT_READ : + res = (picopal_File) fopen((char *)filename, (char *)"r"); + break; + case PICOPAL_TEXT_WRITE : + res = (picopal_File) fopen((char *)filename, (char *)"w"); + break; + case PICOPAL_BINARY_READ : + res = (picopal_File) fopen((char *)filename, (char *)"rb"); + break; + case PICOPAL_BINARY_WRITE : + res = (picopal_File) fopen((char *)filename, (char *)"wb"); + break; + default : + res = (picopal_File) NULL; + } + return res; + +} + + +picopal_File picopal_get_fnil (void) +{ + return (picopal_File) NULL; +} + + +picopal_int8 picopal_is_fnil (picopal_File f) +{ + return (NULL == f); +} + +pico_status_t picopal_fflush (picopal_File f) +{ + return (0 == fflush((FILE *)f)) ? PICO_OK : PICO_EOF; +} + + +pico_status_t picopal_fclose (picopal_File f) +{ + return (0 == fclose((FILE *)f)) ? PICO_OK : PICO_EOF; +} + + + +picopal_uint32 picopal_flength (picopal_File stream) +{ + fpos_t fpos; + picopal_int32 len; + + fgetpos((FILE *)stream,&fpos); + picopal_fseek(stream,0,SEEK_END); + len = ftell((FILE *)stream); + fsetpos((FILE *)stream,&fpos); + clearerr((FILE *)stream); + return len; + +} + +picopal_uint8 picopal_feof (picopal_File stream) +{ + return (0 != feof((FILE *)stream)); + +} + +pico_status_t picopal_fseek (picopal_File f, picopal_uint32 offset, picopal_int8 seekmode) +{ + return (0 == fseek((FILE *)f, offset, seekmode)) ? PICO_OK : PICO_EOF; +} + +pico_status_t picopal_fget_char (picopal_File f, picopal_char * ch) +{ + picopal_int16 res; + + res = fgetc((FILE *)f); + if (res >= 0) { + *ch = (picopal_char) res; + } + else { + *ch = '\0'; + } + return (res >= 0) ? PICO_OK : PICO_EOF; +} + +picopal_objsize_t picopal_fread_bytes (picopal_File f, void * ptr, picopal_objsize_t objsize, picopal_uint32 nobj) +{ + return (picopal_objsize_t) fread(ptr, objsize, nobj, (FILE *)f); +} + +picopal_objsize_t picopal_fwrite_bytes (picopal_File f, void * ptr, picopal_objsize_t objsize, picopal_uint32 nobj){ return (picopal_objsize_t) fwrite(ptr, objsize, nobj, (FILE *)f);} +/* *************************************************/ +/* functions for debugging/testing purposes only */ +/* *************************************************/ + +void *picopal_mpr_alloc(picopal_objsize_t size) +{ +#if PICO_PLATFORM == PICO_Windows + return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); +#else + /* not yet implemented for other platforms; corresponding + function on UNIX systems is pvalloc */ + return NULL; +#endif + size = size; /* avoid warning "var not used in this function"*/ + +} + +void picopal_mpr_free(void **p) +{ +#if PICO_PLATFORM == PICO_Windows + VirtualFree(*p, 0, MEM_RELEASE); +#else + /* not yet implemented for other platforms */ +#endif + *p = NULL; +} + +pico_status_t picopal_mpr_protect(void *addr, picopal_objsize_t len, picopal_int16 prot) +{ + pico_status_t status = PICO_OK; + +#if PICO_PLATFORM == PICO_Windows + DWORD dwNewProtect, dwOldProtect; + dwNewProtect = PICOPAL_PROT_NONE; + if (prot & PICOPAL_PROT_READ) { + if (prot & PICOPAL_PROT_WRITE) { + dwNewProtect = PAGE_READWRITE; + } else { + dwNewProtect = PAGE_READONLY; + } + } else if (prot & PICOPAL_PROT_WRITE) { + /* under Windows write-only is not possible */ + dwNewProtect = PAGE_READWRITE; + } + if (!VirtualProtect(addr, len, dwNewProtect, &dwOldProtect)) { + status = PICO_ERR_OTHER; + } +#else + /* not yet implemented for other platforms */ + addr = addr; /* avoid warning "var not used in this function"*/ + len = len; /* avoid warning "var not used in this function"*/ + prot = prot; /* avoid warning "var not used in this function"*/ + +#endif + return status; +} +/* + * Reference: + * A Fast, Compact Approximation of the Exponential Function by Nicol N. Schraudolph in Neural Computation, 11,853-862 (1999) + * See also: http://www-h.eng.cam.ac.uk/help/tpl/programs/Matlab/mex.html + * + */ +picopal_double picopal_quick_exp(const picopal_double y) { + union { + picopal_double d; + struct { + #if PICO_ENDIANNESS == ENDIANNESS_LITTLE /* little endian */ + picopal_int32 j,i; + #else + picopal_int32 i,j; + #endif + } n; + + } _eco; + _eco.n.i = (picopal_int32)(1512775.3951951856938297995605697f * y) + 1072632447; + return _eco.d; +} + + +/* *************************************************/ +/* timer */ +/* *************************************************/ + +#if IMPLEMENT_TIMER + +#define USEC_PER_SEC 1000000 + +typedef clock_t picopal_clock_t; + + +#if USE_CLOCK +picopal_clock_t startTime; +#else +int timerInit = 0; +LARGE_INTEGER startTime; +LARGE_INTEGER timerFreq; +#endif + + +picopal_clock_t picopal_clock(void) +{ + return (picopal_clock_t)clock(); +} + +#endif /* IMPLEMENT_TIMER */ + +void picopal_get_timer(picopal_uint32 * sec, picopal_uint32 * usec) +{ +#if IMPLEMENT_TIMER +#if USE_CLOCK + picopal_clock_t dt; + dt = picopal_clock() - startTime; + *sec = dt / CLOCKS_PER_SEC; + *usec = USEC_PER_SEC * (dt % CLOCKS_PER_SEC) / CLOCKS_PER_SEC; +#else + LARGE_INTEGER now; + if (!timerInit) { + QueryPerformanceFrequency(&timerFreq); + timerInit = 1; + } + if (QueryPerformanceCounter(&now) && 0) { +/* + LONGLONG dt, tf; + dt = now.QuadPart - GLOB(startTime).QuadPart; + tf = GLOB(timerFreq).QuadPart; + *sec = (unsigned int) (dt / tf); + *usec = (unsigned int) (USEC_PER_SEC * (dt % tf) / tf); +*/ + double dt, tf; + dt = (double)(now.QuadPart - startTime.QuadPart); + tf = (double)(timerFreq.QuadPart); + *sec = (unsigned int) (dt /tf); + *usec = (unsigned int) ((double)USEC_PER_SEC * (dt / tf)) % USEC_PER_SEC; + } else { + /* high freq counter not supported by system */ + DWORD dt; + dt = GetTickCount() - startTime.LowPart; + *sec = dt / 1000; + *usec = 1000 * (dt % 1000); + } +#endif /* USE_CLOCK */ +#else + *sec = 0; + *usec = 0; +#endif /* IMPLEMENT_TIMER */ +} + +#ifdef __cplusplus +} +#endif + +/* End picopal.c */ diff --git a/pico/lib/picopal.h b/pico/lib/picopal.h new file mode 100644 index 0000000..acfc8e0 --- /dev/null +++ b/pico/lib/picopal.h @@ -0,0 +1,288 @@ +/* + * 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 picopal.h + * + * pico plattform abstraction layer + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +/** + * @addtogroup picoos + + * Operating system Platform Specific implementation module \n + * +*/ +#ifndef PICOPAL_H_ +#define PICOPAL_H_ + +#include +#include +#include +#include +#include +#include "picopltf.h" +#include "picodefs.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* *********************************************************/ +/* general defines and typedefs (used to be in picodefs.h) */ +/* *********************************************************/ + +#define TRUE 1 +#define FALSE 0 + +#ifndef NULL +#define NULL 0 +#endif + +#define NULLC '\000' + + +/* "strange" defines to switch variants... */ +#define PICOPAL_DIV_USE_INV 0 + + +/*---------------Externals-----------------------*/ +/* used by picocep*/ +#if defined(PICO_DEBUG) + extern int numlongmult, numshortmult; +#endif + + +typedef signed int pico_status_t; + + +/* unfortunately, ANSI-C uses eof for results and exceptional results .. */ +/* in the context of reading from a CharBuffer, eof means "no more + input available FOR NOW" */ + +#define PICO_EOF (pico_status_t) -1 + + +/* *************************************************/ +/* constants */ +/* *************************************************/ + + + /* operating system identifications */ +#define PICOPAL_OS_NIL 0 /* just an unchangeable first value */ +#define PICOPAL_OS_WINDOWS 1 +/* ... */ +#define PICOPAL_OS_GENERIC 99 /* must always be the last value */ + +/* *************************************************/ +/* types */ +/* *************************************************/ + +typedef unsigned char picopal_uint8; +typedef unsigned short picopal_uint16; +typedef unsigned int picopal_uint32; + +typedef signed char picopal_int8; +typedef signed short picopal_int16; +typedef signed int picopal_int32; + +typedef float picopal_single; +typedef double picopal_double; + +typedef unsigned char picopal_char; + +typedef unsigned char picopal_uchar; + +typedef size_t picopal_objsize_t; +typedef ptrdiff_t picopal_ptrdiff_t; + +/* *************************************************/ +/* functions */ +/* *************************************************/ + +picopal_int32 picopal_atoi(const picopal_char *); + +picopal_int32 picopal_strcmp(const picopal_char *, const picopal_char *); +picopal_int32 picopal_strncmp(const picopal_char *a, const picopal_char *b, picopal_objsize_t siz); +picopal_objsize_t picopal_strlen(const picopal_char *); +picopal_char * picopal_strchr(const picopal_char *, picopal_char); +picopal_char * picopal_strcpy(picopal_char *d, const picopal_char *s); +picopal_char *picopal_strstr(const picopal_char *s, const picopal_char *substr); +picopal_char *picopal_strcat(picopal_char *dest, const picopal_char *src); +picopal_int16 picopal_sprintf(picopal_char * dst, const picopal_char *fmt, ...); + +/* copies 'length' bytes from 'src' to 'dest'. (regions may be overlapping) no error checks! */ +void * picopal_mem_copy(const void * src, void * dst, picopal_objsize_t length); + +/* sets 'length' bytes starting at dest[0] to 'byte_val' */ +void * picopal_mem_set(void * dest, picopal_uint8 byte_val, picopal_objsize_t length); + +/* safe versions */ +picopal_objsize_t picopal_vslprintf(picopal_char * dst, picopal_objsize_t siz, const picopal_char *fmt, va_list args); +picopal_objsize_t picopal_slprintf(picopal_char * dst, picopal_objsize_t siz, const picopal_char *fmt, /*args*/ ...); +picopal_objsize_t picopal_strlcpy(picopal_char *dst, const picopal_char *src, picopal_objsize_t siz); + +/*Fixed point computation*/ +/* +picopal_int32 picopal_fixptdiv(picopal_int32 a, picopal_int32 b, picopal_uint8 bigpow); +picopal_int32 picopal_fixptmult(picopal_int32 x, picopal_int32 y, picopal_uint8 bigpow); +picopal_int32 picopal_fixptdivORinv(picopal_int32 a, picopal_int32 b, picopal_int32 invb, picopal_uint8 bigpow); +picopal_int32 picopal_fixptmultdouble(picopal_int32 x, picopal_int32 y, picopal_uint8 bigpow); +picopal_uint8 picopal_highestBit(picopal_int32 x); +*/ + +/* *************************************************/ +/* math */ +/* *************************************************/ + +picopal_double picopal_cos (const picopal_double cos_arg); +picopal_double picopal_sin (const picopal_double sin_arg); +picopal_double picopal_fabs (const picopal_double fabs_arg); + + + + +/* *************************************************/ +/* file access */ +/* *************************************************/ + +extern picopal_char picopal_eol(void); + +#define picopal_FILE FILE + + +/* seek modes to be used with the 'FSeek' procedure */ +#define PICOPAL_SEEK_SET 0 /* absolut seek position */ +#define PICOPAL_SEEK_CUR 1 /* relative to current */ +#define PICOPAL_SEEK_END 2 /* relative to the end of the file */ + + +typedef enum {PICOPAL_BINARY_READ, PICOPAL_BINARY_WRITE, PICOPAL_TEXT_READ, PICOPAL_TEXT_WRITE} picopal_access_mode; + +typedef picopal_FILE * picopal_File; + +extern picopal_File picopal_fopen (picopal_char fileName[], picopal_access_mode mode); +/* 'FOpen' opens the file with name 'filename'. Depending on + 'mode' : + 'TextRead' : Opens an existing text file for reading. + The file is positioned at the beginning of the file. + 'TextWrite' : Opens and truncates an existing file or creates a new + text file for writing. The file is positioned at the + beginning. + 'BinaryRead' : Opens an existing binary file for reading. + The file is positioned at the beginning of the file. + 'BinaryWrite' : Opens and truncates an existing file or creates a new + binary file for writing. The file is positioned at the + beginning. + If the opening of the file is successful a file pointer is given + back. Otherwise a NIL-File is given back. +*/ + + +extern picopal_File picopal_get_fnil (void); + + +extern picopal_int8 picopal_is_fnil (picopal_File f); + + +extern pico_status_t picopal_fclose (picopal_File f); + + +extern picopal_uint32 picopal_flength (picopal_File f); + + +extern picopal_uint8 picopal_feof (picopal_File f); + + +extern pico_status_t picopal_fseek (picopal_File f, picopal_uint32 offset, picopal_int8 seekmode); + + +extern pico_status_t picopal_fget_char (picopal_File f, picopal_char * ch); + + +extern picopal_objsize_t picopal_fread_bytes (picopal_File f, void * ptr, picopal_objsize_t objsize, picopal_uint32 nobj); + +extern picopal_objsize_t picopal_fwrite_bytes (picopal_File f, void * ptr, picopal_objsize_t objsize, picopal_uint32 nobj); + + +extern pico_status_t picopal_fflush (picopal_File f); + +/* +extern pico_status_t picopal_fput_char (picopal_File f, picopal_char ch); +*/ + + +/* +extern pico_status_t picopal_remove (picopal_char filename[]); + + +extern pico_status_t picopal_rename (picopal_char oldname[], picopal_char newname[]); + +*/ + +/* *************************************************/ +/* functions for debugging/testing purposes only */ +/* *************************************************/ + +/** + * Returns a pointer to a newly allocated chunk of 'size' bytes, aligned + * to the system page size. + * Memory allocated by this routine may be protected by calling function + * picopal_mrp_protect(). + */ +void *picopal_mpr_alloc(picopal_objsize_t size); + +/** + * Releases the chunk of memory pointed to by '*p'. 'p' must be previously + * allocated by a call to picopal_mpr_alloc(). + */ +void picopal_mpr_free(void **p); + +#define PICOPAL_PROT_NONE 0 /* the memory cannot be accessed at all */ +#define PICOPAL_PROT_READ 1 /* the memory can be read */ +#define PICOPAL_PROT_WRITE 2 /* the memory can be written to */ + +/** + * Specifies the desired protection 'prot' for the memory page(s) containing + * part or all of the interval [addr, addr+len-1]. If an access is disallowed + * by the protection given it, the program receives a SIGSEGV. + */ +pico_status_t picopal_mpr_protect(void *addr, picopal_objsize_t len, picopal_int16 prot); + +/* Fast, Compact Approximation of the Exponential Function */ +picopal_double picopal_quick_exp(const picopal_double y); + +/* *************************************************/ +/* types functions for time measurement */ +/* *************************************************/ + +extern void picopal_get_timer(picopal_uint32 * sec, picopal_uint32 * usec); + +#ifdef __cplusplus +} +#endif + + +#endif /*PICOPAL_H_*/ diff --git a/pico/lib/picopam.c b/pico/lib/picopam.c new file mode 100644 index 0000000..02e5cc2 --- /dev/null +++ b/pico/lib/picopam.c @@ -0,0 +1,4803 @@ +/* + * 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 picopam.c + * + * Phonetic to Acoustic Mapping 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 "picopam.h" +#include "picokdt.h" +#include "picokpdf.h" +#include "picoktab.h" +#include "picokdbg.h" +#include "picodsp.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +#define PICOPAM_IN_BUFF_SIZE PICODATA_BUFSIZE_PAM /*input buffer size for PAM */ +#define PICOPAM_OUT_PAM_SIZE PICODATA_BUFSIZE_PAM /*output buffer size for PAM*/ +#define PICOPAM_DT_NRLFZ 5 /* nr of lfz decision trees per phoneme */ +#define PICOPAM_DT_NRMGC 5 /* nr of mgc decision trees per phoneme */ +#define PICOPAM_NRSTPF 5 /* nr of states per phone */ + +#define PICOPAM_COLLECT 0 +#define PICOPAM_SCHEDULE 1 +#define PICOPAM_IMMEDIATE 2 +#define PICOPAM_FORWARD 3 +#define PICOPAM_FORWARD_FORCE_TERM 4 +#define PICOPAM_PROCESS 5 +#define PICOPAM_PLAY 6 +#define PICOPAM_FEED 7 + +#define PICOPAM_CONTINUE 100 +#define PICOPAM_GOTO_SCHEDULE 1 +#define PICOPAM_FLUSH_RECEIVED 6 +#define PICOPAM_GOTO_FEED 7 +#define PICOPAM_PRE_SYLL_ENDED 10 + +#define PICOPAM_BREAK_ADD_SIZE 4 /*syllable feature vector increment dued to BREAK and SILENCE*/ +#define PICOPAM_VECT_SIZE 64+PICOPAM_BREAK_ADD_SIZE /*syllable feature vector size (bytes)*/ +#define PICOPAM_INVEC_SIZE 60 /*phone feature vector size */ +#define PICOPAM_MAX_SYLL_PER_SENT 100 /*maximum number of syllables per sentece*/ +#define PICOPAM_MAX_PH_PER_SENT 400 /*maximum number of phonemes per sentece*/ +#define PICOPAM_MAX_ITEM_PER_SENT 255 /*maximum number of attached items per sentence*/ +#define PICOPAM_MAX_ITEM_SIZE_PER_SENT 4096 /*maximum size of attached items per sentence*/ + +#define PICOPAM_READY 20 /*PAM could start backward processing*/ +#define PICOPAM_MORE 21 /*PAM has still to collect */ +#define PICOPAM_NA 22 /*PAM has not to deal with this item*/ +#define PICOPAM_ERR 23 /*input item is not a valid item*/ + +/*sentence types:cfr pam_map_sentence_type*/ +#define PICOPAM_DECLARATIVE 0 +#define PICOPAM_INTERROGATIVE 1 +#define PICOPAM_EXCLAMATIVE 2 + +#define PICOPAM_T 0 +#define PICOPAM_P 1 +#define PICOPAM_p 2 +#define PICOPAM_Y 3 + +#if 1 +#define PAM_PHR2_WITH_PR1 1 /*deal with PHR2 boundaries as with PHR1*/ +#else +#define PAM_PHR2_WITH_PR3 1 /*deal with PHR2 boundaries as with PHR3*/ +#endif + +#define PICOPAM_DONT_CARE_VALUE 250 /*don't care value for tree printout */ +#define PICOPAM_DONT_CARE_VAL 10 /*don't care value for tree feeding */ +#define PICOPAM_PH_DONT_CARE_VAL 7 /*don't care value for tree feeding (phonetic)*/ + +#define PICOPAM_MAX_STATES_PER_PHONE 5 /*number of states per phone */ +#define PICOPAM_STATE_SIZE_IN_ITEM 6 /*size of a state in frame item */ +#define PICOPAM_FRAME_ITEM_SIZE 4+PICOPAM_MAX_STATES_PER_PHONE*PICOPAM_STATE_SIZE_IN_ITEM + +#define PICOPAM_DIR_FORW 0 /*forward adapter processing*/ +#define PICOPAM_DIR_BACK 1 /*backward adapter processing*/ +#define PICOPAM_DIR_SIL 2 /*final silence attributes*/ + +#define PICOPAM_SYLL_PAUSE 0 /*syllable but containing a pause phone*/ +#define PICOPAM_SYLL_SYLL 1 /*a real syllable with phonemes*/ + +#define PICOPAM_EVENT_P_BOUND 0 /*primary boundary*/ +#define PICOPAM_EVENT_S_BOUND 1 /*secondary boundary*/ +#define PICOPAM_EVENT_W_BOUND 3 /*word boundary*/ +#define PICOPAM_EVENT_SYLL 4 /*syllable*/ + +/* ----- CONSTANTS FOR BREAK COMMAND SUPPORT ----- */ +#define PICOPAM_PWIDX_SBEG 0 +#define PICOPAM_PWIDX_PHR1 1 +#define PICOPAM_PWIDX_PHR2 2 +#define PICOPAM_PWIDX_SEND 3 +#define PICOPAM_PWIDX_DEFA 4 +#define PICOPAM_PWIDX_SIZE 5 + +/*----------------------------------------------------------------*/ +/*structure related to the feature vectors for feeding the trees */ +/*NOTE : the same data structure is used to manage the syllables */ +/* Using the first 8 fields for marking the boundaries */ +/* and using the last 4 bytes as follows */ +/* byte 61 : 1st attached non PAM item id(0=no item attached) */ +/* in the "sSyllItemOffs" data structure */ +/* byte 62 : last attached non PAM item id(0=no item attached)*/ +/* in the "sSyllItemOffs" data structure */ +/* byte 63..64 : offset of the start of the syllable in */ +/* the "sPhIds" data structure */ +typedef struct +{ + picopal_uint8 phoneV[PICOPAM_VECT_SIZE]; +} sFtVect, *pSftVect; + +/*---------------------------------------------------------- + Name : pam_subobj + Function: subobject definition for the pam processing + Shortcut: pam + ---------------------------------------------------------*/ +typedef struct pam_subobj +{ + /*----------------------PU voice management------------------------------*/ + /* picorsrc_Voice voice; */ + /*----------------------PU state management------------------------------*/ + picoos_uint8 procState; /* where to take up work at next processing step */ + picoos_uint8 retState; /* where to go back from feed state at next p.s. */ + picoos_uint8 needMoreInput; /* more data necessary to start processing */ + /*----------------------PU input management------------------------------*/ + picoos_uint8 inBuf[PICOPAM_IN_BUFF_SIZE]; /* internal input buffer */ + picoos_uint16 inBufSize; /* actually allocated size */ + picoos_uint16 inReadPos, inWritePos; /* next pos to read/write from/to inBuf*/ + /*----------------------PU output management-----------------------------*/ + picoos_uint8 outBuf[PICOPAM_OUT_PAM_SIZE]; /* internal output buffer */ + picoos_uint16 outBufSize; /* actually allocated size */ + picoos_uint16 outReadPos, outWritePos; /* next pos to read/write from/to outBuf*/ + /*---------------------- adapter working buffers --------------------*/ + picoos_uint8 *sPhFeats; /*feature vector for a single phone */ + sFtVect *sSyllFeats; /*Syllable feature vector set for the + full sentence */ + picoos_uint8 *sPhIds; /*phone ids for the full sentence */ + picoos_uint8 *sSyllItems; /*items attached to the syllable */ + picoos_int16 *sSyllItemOffs;/*offset of items attached to the syllable*/ + /*---------------------- adapter general variables ---------------------*/ + picoos_int16 nTotalPhonemes; /*number of phonemes in the sentence*/ + picoos_int16 nCurrPhoneme; /*current phoneme in the sentence */ + picoos_int16 nSyllPhoneme; /*current phoneme in the syllable */ + picoos_int16 nCurrSyllable; /*current syllable in the sentence */ + picoos_int16 nTotalSyllables; /*number of syllables in the sentence -> J1*/ + picoos_uint8 nLastAttachedItemId;/*last attached item id*/ + picoos_uint8 nCurrAttachedItem; /*current attached item*/ + picoos_int16 nAttachedItemsSize; /*total size of the attached items*/ + picoos_uint8 sType; /*Sentence type*/ + picoos_uint8 pType; /*Phrase type*/ + picoos_single pMod; /*pitch modifier*/ + picoos_single dMod; /*Duration modifier*/ + picoos_single dRest; /*Duration modifier rest*/ + /*---------------------- adapter specific component variables ----------*/ + picoos_uint8 a3_overall_syllable; /* A3 */ + picoos_uint8 a3_primary_phrase_syllable; + picoos_uint8 b4_b5_syllable; /* B4,B5 */ + picoos_uint8 b6_b7_syllable; /* B6,B7 */ + picoos_uint8 b6_b7_state; + picoos_uint8 b8_b9_stressed_syllable; /* B8,B9 */ + picoos_uint8 b10_b11_accented_syllable; /* B10,B11 */ + picoos_uint8 b12_b13_syllable; /* B12,B13 */ + picoos_uint8 b12_b13_state; + picoos_uint8 b14_b15_syllable; /* B14,B15 */ + picoos_uint8 b14_b15_state; + picoos_uint8 b17_b19_syllable; /* B17,B19 */ + picoos_uint8 b17_b19_state; + picoos_uint8 b18_b20_b21_syllable; /* B18,B20,B21 */ + picoos_uint8 b18_b20_b21_state; + picoos_uint8 c3_overall_syllable; /* C3 */ + picoos_uint8 c3_primary_phrase_syllable; + picoos_uint8 d2_syllable_in_word; /* D2 */ + picoos_uint8 d2_prev_syllable_in_word; + picoos_uint8 d2_current_primary_phrase_word; + picoos_int8 e1_syllable_word_start; /* E1 */ + picoos_int8 e1_syllable_word_end; + picoos_uint8 e1_content; + picoos_int8 e2_syllable_word_start; /* E2 */ + picoos_int8 e2_syllable_word_end; + picoos_uint8 e3_e4_word; /* E3,E4 */ + picoos_uint8 e3_e4_state; + picoos_uint8 e5_e6_content_word; /* E5,E6 */ + picoos_uint8 e5_e6_content; + picoos_uint8 e7_e8_word; /* E7,E8 */ + picoos_uint8 e7_e8_content; + picoos_uint8 e7_e8_state; + picoos_uint8 e9_e11_word; /* E9,E11 */ + picoos_uint8 e9_e11_saw_word; + picoos_uint8 e9_e11_state; + picoos_uint8 e10_e12_e13_word; /* E10,E12,E13 */ + picoos_uint8 e10_e12_e13_state; + picoos_uint8 e10_e12_e13_saw_word; + picoos_uint8 f2_overall_word; /* F2 */ + picoos_uint8 f2_word_syllable; + picoos_uint8 f2_next_word_syllable; + picoos_uint8 f2_current_primary_phrase_word; + picoos_int8 g1_current_secondary_phrase_syllable; /*G1 */ + picoos_int8 g1_current_syllable; + picoos_int8 g2_current_secondary_phrase_word; /*G2 */ + picoos_int8 g2_current_word; + picoos_uint8 h1_current_secondary_phrase_syll; /*H1 */ + picoos_uint8 h2_current_secondary_phrase_word; /*H2 */ + picoos_uint8 h3_h4_current_secondary_phrase_word; /*H3,H4 */ + picoos_uint8 h5_current_phrase_type; /*H5 */ + + picoos_uint8 h5_syllable; /* H5 */ + picoos_uint8 h5_state; + + picoos_uint8 i1_secondary_phrase_syllable; /*I1 */ + picoos_uint8 i1_next_secondary_phrase_syllable; + picoos_uint8 i2_secondary_phrase_word; /*I2 */ + picoos_uint8 i2_next_secondary_phrase_word; + picoos_uint8 j1_utterance_syllable; /*J1 */ + picoos_uint8 j2_utterance_word; /*J2 */ + picoos_uint8 j3_utterance_sec_phrases; /*J3 */ + /*---------------------- constant data -------------------*/ + picoos_uint16 sil_weights[PICOPAM_PWIDX_SIZE][PICOPAM_MAX_STATES_PER_PHONE]; + /*---------------------- LINGWARE related data -------------------*/ + picokdt_DtPAM dtdur; /* dtdur knowledge base */ + picokdt_DtPAM dtlfz[PICOPAM_DT_NRLFZ]; /* dtlfz knowledge bases */ + picokdt_DtPAM dtmgc[PICOPAM_DT_NRMGC]; /* dtmgc knowledge bases */ + /*---------------------- Pdfs related data -------------------*/ + picokpdf_PdfDUR pdfdur; /* pdfdur knowledge base */ + picokpdf_PdfMUL pdflfz; /* pdflfz knowledge base */ + /*---------------------- Tree traversal related data -------------------*/ + picoos_uint16 durIndex; + picoos_uint8 numFramesState[PICOPAM_DT_NRLFZ]; + picoos_uint16 lf0Index[PICOPAM_DT_NRLFZ]; + picoos_uint16 mgcIndex[PICOPAM_DT_NRMGC]; + /*---------------------- temps for updating the feature vector ---------*/ + picoos_uint16 phonDur; + picoos_single phonF0[PICOPAM_DT_NRLFZ]; + /*---------------------- Phones related data -------------------*/ + picoktab_Phones tabphones; +} pam_subobj_t; + + +/* ----- CONSTANTS FOR FEATURE VECTOR BUILDING (NOT PREFIXED WITH "PICOPAM_" FOR BREVITY) ----- */ +#define P1 0 /*field 1 of the input vector*/ +#define P2 1 +#define P3 2 +#define P4 3 +#define P5 4 +#define P6 5 +#define P7 6 +#define bnd 6 /*boundary type item associated to the syllable = P7 */ +#define P8 7 +#define A3 8 +#define B1 9 +#define B2 10 +#define B3 11 +#define B4 12 +#define B5 13 +#define B6 14 +#define B7 15 +#define B8 16 +#define B9 17 +#define B10 18 +#define B11 19 +#define B12 20 +#define B13 21 +#define B14 22 +#define B15 23 +#define B16 24 +#define B17 25 +#define B18 26 +#define B19 27 +#define B20 28 +#define B21 29 +#define C3 30 +#define D2 31 +#define E1 32 +#define E2 33 +#define E3 34 +#define E4 35 +#define E5 36 +#define E6 37 +#define E7 38 +#define E8 39 +#define E9 40 +#define E10 41 +#define E11 42 +#define E12 43 +#define E13 44 +#define F2 45 +#define G1 46 +#define G2 47 +#define H1 48 +#define H2 49 +#define H3 50 +#define H4 51 +#define H5 52 +#define I1 53 +#define I2 54 +#define J1 55 +#define J2 56 +#define J3 57 +#define DUR 58 /*duration component*/ +#define F0 59 /*F0 component*/ +#define ITM 60 /*Item Offset into sSyllItems item list*/ +#define itm 61 /*second byte of the Item Offset */ +#define FID 62 /*Phoneme offset in the sPhIds phoneme list*/ +#define fid 63 /*second byte of the Phoneme offset */ +#define Min 64 /*offset to min syllable duration (uint 16,pauses)*/ +#define Max 66 /*offset to max syllable duration (uint 16,pauses)*/ +/* ------------------------------------------------------------------- + PAM feature vector indices position changes, + ------------------------------------------------------------------- */ +#define T_B1 8 +#define T_B2 9 +#define T_B3 10 +#define T_B4 11 +#define T_B5 12 +#define T_B6 13 +#define T_B7 14 +#define T_B8 15 +#define T_B9 16 +#define T_B10 17 +#define T_B11 18 +#define T_B12 19 +#define T_B13 20 +#define T_B14 21 +#define T_B15 22 +#define T_B16 23 +#define T_B17 24 +#define T_B18 25 +#define T_B19 26 +#define T_B20 27 +#define T_B21 28 +#define T_E1 29 +#define T_E2 30 +#define T_E3 31 +#define T_E4 32 +#define T_E5 33 +#define T_E6 34 +#define T_E7 35 +#define T_E8 36 +#define T_E9 37 +#define T_E10 38 +#define T_E11 39 +#define T_E12 40 +#define T_E13 41 +#define T_A3 42 +#define T_C3 43 +#define T_D2 44 +#define T_F2 45 +#define T_G1 46 +#define T_I1 47 +#define T_G2 48 +#define T_I2 49 +#define T_H1 50 +#define T_H2 51 +#define T_H3 52 +#define T_H4 53 +#define T_H5 54 + +/*------------------------------------------------------------------ + Service routines : + ------------------------------------------------------------------*/ +static pico_status_t pam_initialize(register picodata_ProcessingUnit this); +static pico_status_t pam_terminate(register picodata_ProcessingUnit this); +static pico_status_t pam_allocate(picoos_MemoryManager mm, pam_subobj_t *pam); +static void pam_deallocate(picoos_MemoryManager mm, pam_subobj_t *pam); +static pico_status_t pam_subobj_deallocate(register picodata_ProcessingUnit this, + picoos_MemoryManager mm); +/*------------------------------------------------------------------ + Processing routines : + ------------------------------------------------------------------*/ +static picodata_step_result_t pam_step(register picodata_ProcessingUnit this, + picoos_int16 mode, picoos_uint16 * numBytesOutput); +static pico_status_t pam_deal_with(const picoos_uint8 *item); +/*Utility*/ +static picoos_uint8 pam_get_vowel_name(register picodata_ProcessingUnit this, + picoos_uint8 *item, picoos_uint8 *pos); +static picoos_uint8 pam_get_pause_id(register picodata_ProcessingUnit this); + +static picoos_uint8 pam_map_sentence_type(picoos_uint8 iteminfo1, + picoos_uint8 iteminfo2); +static picoos_uint8 pam_map_phrase_type(picoos_uint8 iteminfo1, + picoos_uint8 iteminfo2); + +/*Adapter*/ +static pico_status_t pam_reset_processors(register picodata_ProcessingUnit this); +static pico_status_t pam_reset_processors_back( + register picodata_ProcessingUnit this); +static pico_status_t pam_create_syllable(register picodata_ProcessingUnit this, + picoos_uint8 syllType, picoos_uint8 *sContent, picoos_uint8 sentType, + picoos_uint8 phType, picoos_uint8 uBoundType, picoos_uint16 uMin, + picoos_uint16 uMax); +static pico_status_t pam_process_event_feature( + register picodata_ProcessingUnit this, picoos_uint8 nFeat, + picoos_uint8 event_type, picoos_uint8 direction); +static pico_status_t pam_process_event(register picodata_ProcessingUnit this, + picoos_uint8 event_type, picoos_uint8 direction); +static pico_status_t pam_adapter_forward_step( + register picodata_ProcessingUnit this, picoos_uint8 *itemBase); +static pico_status_t pam_adapter_backward_step( + register picodata_ProcessingUnit this); +static pico_status_t pam_do_pause(register picodata_ProcessingUnit this); +static pico_status_t pam_adapter_do_pauses(register picodata_ProcessingUnit this); +/*-------------- tree traversal ---------------------------------------*/ +static pico_status_t pam_expand_vector(register picodata_ProcessingUnit this); +static picoos_uint8 pam_do_tree(register picodata_ProcessingUnit this, + const picokdt_DtPAM dtpam, const picoos_uint8 *invec, + const picoos_uint8 inveclen, picokdt_classify_result_t *dtres); +static pico_status_t pam_get_f0(register picodata_ProcessingUnit this, + picoos_uint16 *lf0Index, picoos_uint8 nState, picoos_single *phonF0); +static pico_status_t pam_get_duration(register picodata_ProcessingUnit this, + picoos_uint16 durIndex, picoos_uint16 *phonDur, + picoos_uint8 *numFramesState); +static pico_status_t pam_update_vector(register picodata_ProcessingUnit this); +/*-------------- FINAL ITEM FEEDING -----------------------------------------*/ +static pico_status_t pam_put_item(register picodata_ProcessingUnit this, + picoos_uint8 *outBuff, picoos_uint16 outWritePos, + picoos_uint8 *bytesWr); + +static pico_status_t pam_put_term(picoos_uint8 *outBuff, + picoos_uint16 outWritePos, picoos_uint8 *bytesWr); + +static pico_status_t is_pam_command(const picoos_uint8 *qItem); + +static void get_default_boundary_limit(picoos_uint8 uBoundType, + picoos_uint16 *uMinDur, picoos_uint16 *uMaxDur); + +/* ------------------------------------------------------------- + * Pico System functions + * ------------------------------------------------------------- + */ + +/** + * allocation for PAM memory on pam PU + * @param mm : handle to engine memory manager + * @param pam : handle to a pam struct + * @return PICO_OK : allocation successful + * @return PICO_ERR_OTHER : allocation errors + * @callgraph + * @callergraph + */ +static pico_status_t pam_allocate(picoos_MemoryManager mm, pam_subobj_t *pam) +{ + picoos_uint8 *data; + picoos_int16 *dataI; + + pam->sSyllFeats = NULL; + pam->sPhIds = NULL; + pam->sPhFeats = NULL; + pam->sSyllItems = NULL; + pam->sSyllItemOffs = NULL; + + /*----------------------------------------------------------------- + * PAM Local buffers ALLOCATION + ------------------------------------------------------------------*/ + /*PAM Local buffers*/ + data = (picopal_uint8 *) picoos_allocate(mm, sizeof(sFtVect) + * PICOPAM_MAX_SYLL_PER_SENT); + if (data == NULL) + return PICO_ERR_OTHER; + pam->sSyllFeats = (sFtVect*) data; + + data = (picopal_uint8 *) picoos_allocate(mm, sizeof(picopal_uint8) + * PICOPAM_MAX_PH_PER_SENT); + if (data == NULL) { + pam_deallocate(mm, pam); + return PICO_ERR_OTHER; + } + pam->sPhIds = (picopal_uint8*) data; + + data = (picopal_uint8 *) picoos_allocate(mm, sizeof(picopal_uint8) + * PICOPAM_VECT_SIZE); + if (data == NULL) { + pam_deallocate(mm, pam); + return PICO_ERR_OTHER; + } + pam->sPhFeats = (picopal_uint8*) data; + + data = (picopal_uint8 *) picoos_allocate(mm, sizeof(picopal_uint8) + * PICOPAM_MAX_ITEM_SIZE_PER_SENT); + if (data == NULL) { + pam_deallocate(mm, pam); + return PICO_ERR_OTHER; + } + pam->sSyllItems = (picopal_uint8*) data; + + dataI = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) + * PICOPAM_MAX_ITEM_PER_SENT); + if (data == NULL) { + pam_deallocate(mm, pam); + return PICO_ERR_OTHER; + } + pam->sSyllItemOffs = (picoos_int16*) dataI; + + return PICO_OK; +}/*pam_allocate*/ + +/** + * frees allocation for DSP memory on PAM PU + * @param mm : memory manager + * @param pam : pam PU internal sub-object + * @return void + * @remarks modified and inserted in sub obj removal PP 15.09.08 + * @callgraph + * @callergraph + */ +static void pam_deallocate(picoos_MemoryManager mm, pam_subobj_t *pam) +{ + /*----------------------------------------------------------------- + * Memory de-allocations + * ------------------------------------------------------------------*/ + if (pam->sSyllFeats != NULL) + picoos_deallocate(mm, (void *) &pam->sSyllFeats); + if (pam->sPhIds != NULL) + picoos_deallocate(mm, (void *) &pam->sPhIds); + if (pam->sPhFeats != NULL) + picoos_deallocate(mm, (void *) &pam->sPhFeats); + if (pam->sSyllItems != NULL) + picoos_deallocate(mm, (void *) &pam->sSyllItems); + if (pam->sSyllItemOffs != NULL) + picoos_deallocate(mm, (void *) &pam->sSyllItemOffs); + +}/*pam_deallocate*/ + +/** + * initialization of a pam PU + * @param this : handle to a PU struct + * @return PICO_OK : init OK + * @return PICO_ERR_OTHER : error on getting pkbs addresses + * @callgraph + * @callergraph + */ +static pico_status_t pam_initialize(register picodata_ProcessingUnit this) +{ + pico_status_t nI, nJ; + pam_subobj_t *pam; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + pam->inBufSize = PICOPAM_IN_BUFF_SIZE; + pam->outBufSize = PICOPAM_OUT_PAM_SIZE; + pam->inReadPos = 0; + pam->inWritePos = 0; + pam->outReadPos = 0; + pam->outWritePos = 0; + pam->needMoreInput = 0; + pam->procState = 0; + + /*----------------------------------------------------------------- + * MANAGE INTERNAL INITIALIZATION + ------------------------------------------------------------------*/ + /*init the syllable structure*/ + for (nI = 0; nI < PICOPAM_MAX_SYLL_PER_SENT; nI++) + for (nJ = 0; nJ < PICOPAM_VECT_SIZE; nJ++) + pam->sSyllFeats[nI].phoneV[nJ] = 0; + + for (nI = 0; nI < PICOPAM_MAX_PH_PER_SENT; nI++) + pam->sPhIds[nI] = 0; + + for (nI = 0; nI < PICOPAM_VECT_SIZE; nI++) + pam->sPhFeats[nI] = 0; + + for (nI = 0; nI < PICOPAM_MAX_ITEM_SIZE_PER_SENT; nI++) + pam->sSyllItems[nI] = 0; + + for (nI = 0; nI < PICOPAM_MAX_ITEM_PER_SENT; nI++) + pam->sSyllItemOffs[nI] = 0; + + /*Other variables*/ + pam_reset_processors(this); + pam->nLastAttachedItemId = pam->nCurrAttachedItem = 0; + pam->nAttachedItemsSize = 0; + + /*pitch and duration modifiers*/ + pam->pMod = 1.0f; + pam->dMod = 1.0f; + pam->dRest = 0.0f; + + + /* constant tables */ + { + picoos_uint8 i, j; + picoos_uint16 tmp_weights[PICOPAM_PWIDX_SIZE][PICOPAM_MAX_STATES_PER_PHONE] = { + {10, 10, 10, 10, 1 }, /*SBEG*/ + { 1, 4, 8, 4, 1 }, /*PHR1*/ + { 1, 4, 8, 4, 1 }, /*PHR2*/ + { 1, 10, 10, 10, 10 },/*SEND*/ + { 1, 1, 1, 1, 1 } /*DEFAULT*/ + }; + for (i = 0; i < PICOPAM_PWIDX_SIZE; i++) { + for (j = 0; j < PICOPAM_PWIDX_SIZE; j++) { + pam->sil_weights[j][j] = tmp_weights[i][j]; + } + } + } +/*----------------------------------------------------------------- + * MANAGE LINGWARE INITIALIZATION IF NEEDED + ------------------------------------------------------------------*/ + /* kb dtdur */ + pam->dtdur = picokdt_getDtPAM(this->voice->kbArray[PICOKNOW_KBID_DT_DUR]); + if (pam->dtdur == NULL) { + picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL, + NULL); + return PICO_ERR_OTHER; + }PICODBG_DEBUG(("got dtdur")); + + /* kb dtlfz* */ + pam->dtlfz[0] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_LFZ1]); + pam->dtlfz[1] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_LFZ2]); + pam->dtlfz[2] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_LFZ3]); + pam->dtlfz[3] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_LFZ4]); + pam->dtlfz[4] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_LFZ5]); + for (nI = 0; nI < PICOPAM_DT_NRLFZ; nI++) { + if (pam->dtlfz[nI] == NULL) { + picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + return PICO_ERR_OTHER; + }PICODBG_DEBUG(("got dtlfz%d", nI+1)); + } + + /* kb dtmgc* */ + pam->dtmgc[0] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_MGC1]); + pam->dtmgc[1] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_MGC2]); + pam->dtmgc[2] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_MGC3]); + pam->dtmgc[3] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_MGC4]); + pam->dtmgc[4] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_MGC5]); + for (nI = 0; nI < PICOPAM_DT_NRMGC; nI++) { + if (pam->dtmgc[nI] == NULL) { + picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + return PICO_ERR_OTHER; + }PICODBG_DEBUG(("got dtmgc%d", nI+1)); + } + + /* kb pdfdur* */ + pam->pdfdur = picokpdf_getPdfDUR( + this->voice->kbArray[PICOKNOW_KBID_PDF_DUR]); + if (pam->pdfdur == NULL) { + picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL, + NULL); + return PICO_ERR_OTHER; + }PICODBG_DEBUG(("got pdfdur")); + + /* kb pdflfz* */ + pam->pdflfz = picokpdf_getPdfMUL( + this->voice->kbArray[PICOKNOW_KBID_PDF_LFZ]); + if (pam->pdflfz == NULL) { + picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL, + NULL); + return PICO_ERR_OTHER; + }PICODBG_DEBUG(("got pdflfz")); + + /* kb tabphones */ + pam->tabphones = picoktab_getPhones( + this->voice->kbArray[PICOKNOW_KBID_TAB_PHONES]); + if (pam->tabphones == NULL) { + picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL, + NULL); + return PICO_ERR_OTHER; + }PICODBG_DEBUG(("got tabphones")); + + return PICO_OK; +}/*pam_initialize*/ + +/** + * termination of a pam PU + * @param this : handle to a pam PU struct + * @return PICO_OK + * @callgraph + * @callergraph + */ +static pico_status_t pam_terminate(register picodata_ProcessingUnit this) +{ + + pam_subobj_t *pam; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + + return PICO_OK; +}/*pam_terminate*/ + +/** + * deallocaton of a pam PU + * @param this : handle to a pam PU struct + * @param mm : engine memory manager + * @return PICO_OK + * @callgraph + * @callergraph + */ +static pico_status_t pam_subobj_deallocate(register picodata_ProcessingUnit this, + picoos_MemoryManager mm) +{ + + pam_subobj_t* pam; + + if (NULL != this) { + pam = (pam_subobj_t *) this->subObj; + mm = mm; /* avoid warning "var not used in this function"*/ + /*----------------------------------------------------------------- + * Memory de-allocations + * ------------------------------------------------------------------*/ + if (pam->sSyllFeats != NULL) { + picoos_deallocate(this->common->mm, (void *) &pam->sSyllFeats); + } + if (pam->sPhIds != NULL) { + picoos_deallocate(this->common->mm, (void *) &pam->sPhIds); + } + if (pam->sPhFeats != NULL) { + picoos_deallocate(this->common->mm, (void *) &pam->sPhFeats); + } + if (pam->sSyllItems != NULL) { + picoos_deallocate(this->common->mm, (void *) &pam->sSyllItems); + } + if (pam->sSyllItemOffs != NULL) { + picoos_deallocate(this->common->mm, (void *) &pam->sSyllItemOffs); + } + picoos_deallocate(this->common->mm, (void *) &this->subObj); + } + + return PICO_OK; +}/*pam_subobj_deallocate*/ + +/** + * creates a new pam processing unit + * @param mm : engine memory manager + * @param common : engine common object pointer + * @param cbIn : pointer to input buffer + * @param cbOut : pointer to output buffer + * @param voice : pointer to voice structure + * @return this : pam PU handle if success + * @return NULL : if error + * @callgraph + * @callergraph + */ +picodata_ProcessingUnit picopam_newPamUnit(picoos_MemoryManager mm, + picoos_Common common, picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, picorsrc_Voice voice) +{ + + register pam_subobj_t * pam; + + picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, + cbOut, voice); + if (this == NULL) { + return NULL; + } + this->initialize = pam_initialize; + + PICODBG_DEBUG(("picotok_newPamUnit -- set this->step to pam_step")); + + this->step = pam_step; + this->terminate = pam_terminate; + this->subDeallocate = pam_subobj_deallocate; + this->subObj = picoos_allocate(mm, sizeof(pam_subobj_t)); + if (this->subObj == NULL) { + PICODBG_ERROR(("Error in Pam Object allocation")); + picoos_deallocate(mm, (void*) &this); + return NULL; + }; + + /*----------------------------------------------------------------- + * Allocate internal memory for PAM (only at PU creation time) + * ------------------------------------------------------------------*/ + pam = (pam_subobj_t *) this->subObj; + if (PICO_OK != pam_allocate(mm, pam)) { + PICODBG_ERROR(("Error in Pam buffers Allocation")); + picoos_deallocate(mm, (void *) &this->subObj); + picoos_deallocate(mm, (void *) &this); + return NULL; + } + + /*----------------------------------------------------------------- + * Initialize memory for PAM (this may be re-used elsewhere, e.g.Reset) + * ------------------------------------------------------------------*/ + if (PICO_OK != pam_initialize(this)) { + PICODBG_ERROR(("problem initializing the pam sub-object")); + } + return this; +}/*picopam_newPamUnit*/ + +/*------------------------------------------------------------------------------- + PROCESSING AND INTERNAL FUNCTIONS + --------------------------------------------------------------------------------*/ + +/** + * initializes default duration limits for boundary items + * @param uBoundType : type of input boundary type + * @param *uMinDur, *uMaxDur : addresses of values to initialize + * @return void + * @remarks so far initializes to 0 both values; this will leave the values given by tree prediction + * @callgraph + * @callergraph + */ +static void get_default_boundary_limit(picoos_uint8 uBoundType, + picoos_uint16 *uMinDur, picoos_uint16 *uMaxDur) +{ + switch (uBoundType) { + case PICODATA_ITEMINFO1_BOUND_SBEG: + *uMinDur = 0; + *uMaxDur = 20; + break; + case PICODATA_ITEMINFO1_BOUND_SEND: + *uMinDur = 550; + *uMaxDur = 650; + break; + case PICODATA_ITEMINFO1_BOUND_TERM: + *uMinDur = 0; + *uMaxDur = 0; + break; + case PICODATA_ITEMINFO1_BOUND_PHR0: + *uMinDur = 0; + *uMaxDur = 0; + break; + case PICODATA_ITEMINFO1_BOUND_PHR1: + *uMinDur = 275; + *uMaxDur = 325; + break; + case PICODATA_ITEMINFO1_BOUND_PHR2: + *uMinDur = 4; + *uMaxDur = 60; + break; + case PICODATA_ITEMINFO1_BOUND_PHR3: + *uMinDur = 0; + *uMaxDur = 0; + break; + default: + break; + } + +}/*get_default_boundary_limit*/ + +/** + * checks if "neededSize" is available on "nCurrPhoneme" + * @param pam : pam subobj + * @param neededSize : the requested size + * @return PICO_OK : size is available + * @return !=PICO_OK : size not available + * @callgraph + * @callergraph + */ +static pico_status_t check_phones_size(pam_subobj_t *pam, + picoos_int16 neededSize) +{ + if ((pam->nCurrPhoneme + neededSize) > PICOPAM_MAX_PH_PER_SENT - 1) { + return PICO_ERR_OTHER; + } + return PICO_OK; +}/*check_phones_size*/ + +/** + * checks if neededSize is available on "nCurrSyllable" + * @param pam : pam subobj + * @param neededSize : the requested size + * @return PICO_OK : size is available + * @return !=PICO_OK : size not available + * @callgraph + * @callergraph + */ +static pico_status_t check_syllables_size(pam_subobj_t *pam, + picoos_int16 neededSize) +{ + if ((pam->nCurrSyllable + neededSize) > PICOPAM_MAX_SYLL_PER_SENT - 1) { + return PICO_ERR_OTHER; + } + return PICO_OK; +}/*check_syllables_size*/ + +/** + * verifies that local storage has enough space to receive 1 item + * @param this : pointer to current PU struct + * @param item : pointer to current item head + * @return TRUE : resource limits would be reached during processing of input item + * @return FALSE : item could be processed normally + * @remarks item pointed to by *item should be already valid + * @callgraph + * @callergraph + */ +static pico_status_t pamCheckResourceLimits( + register picodata_ProcessingUnit this, const picoos_uint8 *item) +{ + register pam_subobj_t * pam; + picodata_itemhead_t head; + pico_status_t sResult; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + sResult = TRUE; /*default : resource limits reached*/ + head.type = item[0]; + head.info1 = item[1]; + head.info2 = item[2]; + head.len = item[3]; + + switch (head.type) { + /*commands that generate syllables/phonemes*/ + case PICODATA_ITEM_SYLLPHON: + if (pam->nCurrSyllable >= PICOPAM_MAX_SYLL_PER_SENT - 2) { + return sResult; /*no room for more syllables*/ + } + if ((pam->nCurrPhoneme + head.len) >= PICOPAM_MAX_PH_PER_SENT - 2) { + return sResult; /*no room for more phoneme*/ + } + break; + case PICODATA_ITEM_BOUND: + if ((head.info1 == PICODATA_ITEMINFO1_BOUND_SBEG) || (head.info1 + == PICODATA_ITEMINFO1_BOUND_SEND) || (head.info1 + == PICODATA_ITEMINFO1_BOUND_TERM) || (head.info1 + == PICODATA_ITEMINFO1_BOUND_PHR1) +#ifdef PAM_PHR2_WITH_PR1 + || (head.info1 == PICODATA_ITEMINFO1_BOUND_PHR2) +#endif + ) { + + if (pam->nCurrSyllable >= PICOPAM_MAX_SYLL_PER_SENT - 2) { + return sResult; /*no room for more syllables*/ + } + if ((pam->nCurrPhoneme + 1) >= PICOPAM_MAX_PH_PER_SENT - 2) { + return sResult; /*no room for more phoneme*/ + } + } + break; + + default: + /*all other commands has to be queued*/ + if ((pam->nAttachedItemsSize + head.len) + >= PICOPAM_MAX_ITEM_SIZE_PER_SENT - 1) { + return sResult; /*no room for more items*/ + } + break; + } + return FALSE; /*no resource limits apply to current item*/ +} /*pamCheckResourceLimits*/ + +/** + * selects items to be sent to next PU immedately + * @param this : pointer to current PU struct + * @param item : pointer to current item head + * @return TRUE : item should be passed on next PU NOW + * @return FALSE : item should not be passed on next PU now but should be processed + * @remarks item pointed to by *item should be already valid + * @callgraph + * @callergraph + */ +static pico_status_t pam_check_immediate(register picodata_ProcessingUnit this, + const picoos_uint8 *item) +{ + register pam_subobj_t * pam; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + + if (pam->nCurrSyllable <= -1) { + if (item[0] == PICODATA_ITEM_SYLLPHON) + return FALSE; + if ((item[0] == PICODATA_ITEM_BOUND) && (item[1] + == PICODATA_ITEMINFO1_BOUND_SBEG)) + return FALSE; + if (is_pam_command((picoos_uint8 *) item) == TRUE) + return FALSE; + return TRUE; /*no need to process data : send it*/ + } + return FALSE; /*syllable struct not void : do standard processing*/ + +} /*pam_check_immediate*/ + +/** + * checks if the input item has to be queued in local storage for later resynch + * @param this : pointer to current PU struct + * @param item : pointer to current item head + * @return TRUE : item should be queued + * @return FALSE : item should not be queued + * @remarks item pointed to by *item should be already valid + * @callgraph + * @callergraph + */ +static pico_status_t pam_hastobe_queued(register picodata_ProcessingUnit this, + const picoos_uint8 *item) +{ + register pam_subobj_t * pam; + picodata_itemhead_t head; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + head.type = item[0]; + head.info1 = item[1]; + + switch (head.type) { + /*commands that generate syllables/phonemes*/ + case PICODATA_ITEM_SYLLPHON: + return FALSE; /*no queue needed*/ + break; + case PICODATA_ITEM_BOUND: + if ((head.info1 == PICODATA_ITEMINFO1_BOUND_PHR3) +#ifdef PAM_PHR2_WITH_PR3 + ||(head.info1==PICODATA_ITEMINFO1_BOUND_PHR2) +#endif + || (head.info1 == PICODATA_ITEMINFO1_BOUND_PHR0)) { + return FALSE; /*no queue needed*/ + } + break; + + default: + /*all other items has to be queued*/ + break; + } + return TRUE; /*item has to be queued*/ +} /*pam_hastobe_queued*/ + +/** + * queue item in local storage for later resynch + * @param this : pointer to current PU struct + * @param item : pointer to current item head + * @return TRUE : item queued + * @return FALSE : item not queued because of errors + * @remarks item pointed to by *item should be already valid + * @callgraph + * @callergraph + */ +static pico_status_t pam_queue(register picodata_ProcessingUnit this, + const picoos_uint8 *item) +{ + register pam_subobj_t * pam; + picodata_itemhead_t head; + picoos_uint8 nI; + pico_status_t sResult; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + sResult = TRUE; /*default : item queued*/ + head.type = item[0]; + head.info1 = item[1]; + head.info2 = item[2]; + head.len = item[3]; + + /*test condition on enough room to store current item in the "sSyllItems" area*/ + if ((pam->nAttachedItemsSize + head.len + sizeof(picodata_itemhead_t)) + >= PICOPAM_MAX_ITEM_SIZE_PER_SENT - 1) { + return FALSE; /*resource limit reached*/ + } + /*store current offset*/ + pam->sSyllItemOffs[pam->nLastAttachedItemId] = pam->nAttachedItemsSize; + /*store the item to the "sSyllItems" area*/ + for (nI = 0; nI < (head.len + sizeof(picodata_itemhead_t)); nI++) { + pam->sSyllItems[pam->nAttachedItemsSize + nI] = item[nI]; + } + /*increment the attached items area*/ + pam->nAttachedItemsSize += nI; + + /*increment id*/ + pam->nLastAttachedItemId++; + /*set start(if not initialized) and end ids of queued items in sSyllFeats*/ + if (pam->nCurrSyllable > -1) { + /*normal case : the item is attached to current syllable*/ + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] == 0) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] + = pam->nLastAttachedItemId; + } + pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] + = pam->nLastAttachedItemId; + } else { + /*special case : an item is requested to be queued even if no + syllables has been assigned to the sentence structure : + -->> use syll 0*/ + if (pam->sSyllFeats[0].phoneV[ITM] == 0) { + pam->sSyllFeats[0].phoneV[ITM] = pam->nLastAttachedItemId; + } + pam->sSyllFeats[0].phoneV[itm] = pam->nLastAttachedItemId; + } + return TRUE; /*item queued successfully*/ +} /*pam_queue*/ + +/** + * selects items to be dealth with by the PU processing + * @param item : pointer to current item head + * @return TRUE : item should be processed + * @return FALSE : item should not be processed (maybe it ontains commands or items for other PUs) + * @remarks item pointed to by *item should be already valid + * @callgraph + * @callergraph + */ +static pico_status_t pam_deal_with(const picoos_uint8 *item) +{ + picodata_itemhead_t head; + pico_status_t sResult; + sResult = FALSE; + head.type = item[0]; + head.info1 = item[1]; + head.info2 = item[2]; + head.len = item[3]; + switch (head.type) { + case PICODATA_ITEM_SYLLPHON: + case PICODATA_ITEM_BOUND: + sResult = TRUE; + break; + default: + break; + } + return sResult; +} /*pam_deal_with*/ + +/** + * returns true if more items has to be produced for current syllable + * @param this : Pam object pointer + * @return TRUE : item is to be produced + * @return FALSE : item is not to be produced + * @remarks item pointed to by *item should be already valid + * @callgraph + * @callergraph + */ +static picoos_uint8 pamHasToProcess(register picodata_ProcessingUnit this) +{ + register pam_subobj_t * pam; + picoos_uint8 nCond1, nCond2, nCond3; + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + /*conditions originating a "NOT to be processed" result */ + nCond1 = pam->nCurrSyllable <= -1; + nCond2 = pam->nCurrSyllable >= pam->nTotalSyllables; + nCond3 = pam->nSyllPhoneme + >= pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3]; + + if ((nCond1) || (nCond2) || (nCond3)) + return FALSE; + + return TRUE; +} /*pamHasToProcess*/ + +/** + * modifies the process flags in order to point to next valid syllable phone or item to be produced + * @param this : Pam object pointer + * @return TRUE : item has to be produced + * @return FALSE : item has not to be produced + * @callgraph + * @callergraph + */ +static pico_status_t pamUpdateProcess(register picodata_ProcessingUnit this) +{ + register pam_subobj_t * pam; + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + + if (pam->nCurrSyllable == -1) { + /*this to be able to manage sudden PU cleanup after FLUSH CMD*/ + return PICO_OK; + } + /*check number of phonemes for current syllable*/ + if (pam->nSyllPhoneme < pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] - 1) { + pam->nSyllPhoneme++; + return PICO_OK; + } + if (pam->nSyllPhoneme == pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] - 1) { + /*this helps in identifyng the end of syllable condition in PamHasToProcess*/ + pam->nSyllPhoneme++; + } + /*previous syllable phonemes are complete: test if any items are tied to this syllable*/ + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] > 0) { + /*there are items tied to this syllable*/ + if (pam->nCurrAttachedItem == 0) { + /*if it is the first item to be regenerated initialize it*/ + pam->nCurrAttachedItem + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM]; + return PICO_OK; + } else { + /*not the first item : check if more*/ + if (pam->nCurrAttachedItem + < pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]) { + /*more tied items to be regenerated*/ + pam->nCurrAttachedItem++; + return PICO_OK; + } + } + } + /*previous syllable phonemes and items are complete: switch to next syllable*/ + if (pam->nCurrSyllable < pam->nTotalSyllables - 1) { + pam->nCurrSyllable++; + pam->nSyllPhoneme = 0; + pam->nCurrAttachedItem = 0; + return PICO_OK; + } + /*no more phonemes or items to be produced*/ + pam->nCurrSyllable++; + pam->nSyllPhoneme = 0; + return PICO_ERR_OTHER; + +} /*pamUpdateProcess*/ + +/** + * returns true if more items has to be popped for current syllable + * @param this : Pam object pointer + * @return TRUE : item has to be popped + * @return FALSE : item has not to be popped + * @callgraph + * @callergraph + */ +static picoos_uint8 pamHasToPop(register picodata_ProcessingUnit this) +{ + register pam_subobj_t * pam; + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + + /*Preliminary condition : at least 1 syllable*/ + if (pam->nCurrSyllable <= -1) + return FALSE; + + /*Preliminary condition : not maximum number of syllables*/ + if (pam->nCurrSyllable >= pam->nTotalSyllables) + return FALSE; + + /*Preliminary condition : start and end offset in current item > 0 */ + if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] <= 0) + || (pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] <= 0)) + return FALSE; + + /*Final condition : current popped item less or eq to maximum*/ + if (pam->nCurrAttachedItem + > pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]) + return FALSE; + + return TRUE; +} /*pamHasToPop*/ + +/** + * returns the address of an item to be popped from the current syllable queue + * @param this : Pam object pointer + * @return pop_address : item address + * @return NULL : item not poppable + * @callgraph + * @callergraph + */ +static picoos_uint8 *pamPopItem(register picodata_ProcessingUnit this) +{ + register pam_subobj_t * pam; + picoos_uint8 nItem; + if (NULL == this || NULL == this->subObj) { + return NULL; + } + pam = (pam_subobj_t *) this->subObj; + + /*Preliminary condition : at least 1 syllable*/ + if (pam->nCurrSyllable <= -1) + return NULL; + + /*Preliminary condition : not maximum number of syllables*/ + if (pam->nCurrSyllable >= pam->nTotalSyllables) + return NULL; + + /*Preliminary condition : start and end offset in current item > 0 */ + if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] <= 0) + || (pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] <= 0)) + return NULL; + + /*Final condition : current popped item less than maximum*/ + if (pam->nCurrAttachedItem + > pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]) + return NULL; + + nItem = pam->nCurrAttachedItem; + /*please note : nItem-1 should match with actions performed in function "pam_queue(..)" */ + return &(pam->sSyllItems[pam->sSyllItemOffs[nItem - 1]]); + +} /*pamPopItem*/ + +/** + * returns the address of an item popped from the syllable 0 queue + * @param this : Pam object pointer + * @return pop_address : item address + * @return NULL : item not poppable + * @remarks the item is popped only if it has been inserted in the queue before the first + * @remarks item assigned to the syllable 0 i.e. + * @remarks AttachedItem<=pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]-1 + * @callgraph + * @callergraph + */ +static picoos_uint8 *pamPopAttachedSy0(register picodata_ProcessingUnit this) +{ + register pam_subobj_t * pam; + picoos_uint8 nItem; + if (NULL == this || NULL == this->subObj) { + return NULL; + } + pam = (pam_subobj_t *) this->subObj; + + /*should be syllable 0*/ + if (pam->nCurrSyllable != 0) + return NULL; + + /*start and end offset in current item > 0 */ + if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] <= 0) + || (pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] <= 0)) + return NULL; + + /*if current popped item is > 0 test end condition*/ + if (pam->nCurrAttachedItem > 0) { + /*Other condition : current popped item less than maximum*/ + if (pam->nCurrAttachedItem + > pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] - 1) + return NULL; + } + nItem = pam->nCurrAttachedItem; + return &(pam->sSyllItems[pam->sSyllItemOffs[nItem]]); + +} /*pamPopAttachedSy0*/ + +/** + * pdf access for duration + * @param this : Pam object pointer + * @param durIndex : index of duration in the pdf + * @param phonDur : pointer to base of array where to store the duration values + * @param numFramesState : pointer to base of array where to store the number of frames per state + * @return PICO_OK : pdf retrieved + * @return PICO_ERR_OTHER : pdf not retrieved + * @remarks Modifies phonDur (the requested duration value) + * @remarks Modifies numFramesState (the requested number of frames per state (vector)) + * @callgraph + * @callergraph + */ +static pico_status_t pam_get_duration(register picodata_ProcessingUnit this, + picoos_uint16 durIndex, picoos_uint16 *phonDur, + picoos_uint8 *numFramesState) +{ + pam_subobj_t *pam; + picokpdf_PdfDUR pdf; + picoos_uint8 *durItem; + picoos_uint16 nFrameSize, nI; + picoos_single fValue; + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pdf = pam->pdfdur; + /*make the index 0 based*/ + if (durIndex > 0) + durIndex--; + + /* check */ + if (durIndex > pdf->numframes - 1) { + PICODBG_ERROR(("PAM durPdf access error, index overflow -> index: %d , numframes: %d", durIndex, pdf->numframes)); + return PICO_ERR_OTHER; + } + /* base pointer */ + durItem = &(pdf->content[durIndex * pdf->vecsize]); + if (durItem == NULL) { + PICODBG_ERROR(("PAM durPdf access error , frame pointer = NULL")); + return PICO_ERR_OTHER; + } + nFrameSize = pdf->sampperframe / 16; + *phonDur = ((pdf->phonquant[((*durItem) & 0xF0) >> 4]) * nFrameSize); + numFramesState[0] = pdf->statequant[((*durItem) & 0x0F)]; + durItem++; + numFramesState[1] = pdf->statequant[((*durItem) & 0xF0) >> 4]; + numFramesState[2] = pdf->statequant[((*durItem) & 0x0F)]; + durItem++; + numFramesState[3] = pdf->statequant[((*durItem) & 0xF0) >> 4]; + numFramesState[4] = pdf->statequant[((*durItem) & 0x0F)]; + + /*modification of the duration information based on the duration modifier*/ + *phonDur = (picoos_uint16) (((picoos_single) * phonDur) * pam->dMod); + for (nI = 0; nI < 5; nI++) { + fValue = pam->dRest + (picoos_single) numFramesState[nI] * pam->dMod; + numFramesState[nI] = (picoos_uint8) (fValue); + pam->dRest = fValue - (picoos_single) numFramesState[nI]; + } + return PICO_OK; +}/*pam_get_duration*/ + +/** + * pdf access for pitch + * @param this : Pam object pointer + * @param lf0Index : pointer to variable to receive index of pitch in the pdf + * @param nI : number of the phone's state + * @param phonF0 : pointer to variable to receive the pitch value + * @return PICO_OK : pdf retrieved + * @return PICO_ERR_OTHER : pdf not retrieved + * @remarks Modifies phonDur (the requested duration value) + * @remarks Modifies phonF0 (the requested pitch value (scalar)) + * @callgraph + * @callergraph + */ +static pico_status_t pam_get_f0(register picodata_ProcessingUnit this, + picoos_uint16 *lf0Index, picoos_uint8 nI, picoos_single *phonF0) +{ + pam_subobj_t *pam; + picoos_uint8 *lfItem, numstreams; + picoos_uint16 lf0IndexOffset, sTemp; + picoos_single lfum, lfivar, lfz; + + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + lf0IndexOffset = lf0Index[nI]; + + /*make the index 0 based*/ + if (lf0IndexOffset > 0) + lf0IndexOffset--; + + lf0IndexOffset += pam->pdflfz->stateoffset[nI]; + if (lf0IndexOffset > pam->pdflfz->numframes - 1) { + PICODBG_ERROR(("PAM flfzPdf access error, index overflow -> index: %d , numframes: %d", lf0Index, pam->pdflfz->numframes)); + return PICO_ERR_OTHER; + } + /* base pointer */ + lf0IndexOffset *= pam->pdflfz->vecsize; + + lfItem = &(pam->pdflfz->content[lf0IndexOffset]); + sTemp = (picoos_uint16) (((lfItem[1] << 8)) | lfItem[0]); + + lfum = (picoos_single) (sTemp << (pam->pdflfz->meanpowUm[0])); + numstreams = 3; + lfivar = (picoos_single) (((picoos_uint16) lfItem[numstreams * 2]) + << pam->pdflfz->ivarpow[0]); + lfz = (picoos_single) lfum / (picoos_single) lfivar; + lfz = (picoos_single) exp((double) lfz); + phonF0[nI] = (picoos_single) lfz; + + /*pitch modoification*/ + phonF0[nI] *= pam->pMod; + return PICO_OK; +}/*pam_get_f0*/ + +/** + * elementary rounding function + * @param fIn : (real) input value + * @return the rounded value + * @callgraph + * @callergraph + */ +static picoos_single f_round(picoos_single fIn) +{ + picoos_int32 iVal; + picoos_single fVal; + + iVal = (picoos_int32) fIn; + fVal = (picoos_single) iVal; + + if (fIn > (picoos_single) 0.0f) { + if ((fIn - fVal) < (picoos_single) 0.5f) + return fVal; + else + return fVal + (picoos_single) 1.0f; + } else { + if ((fVal - fIn) < (picoos_single) 0.5f) + return fVal; + else + return fVal - (picoos_single) 1.0f; + } +}/*f_round*/ + +/** + * updates the input vector for PAM + * @param this : Pam object pointer + * @return PICO_OK : update successful + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @remarks Modifies pam->sPhFeats[] + * @callgraph + * @callergraph + */ +static pico_status_t pam_update_vector(register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + picoos_uint8 numstates, nI; + picoos_single fDur, f0avg, f0quant, minf0, maxf0, durquant1, durquant2, + mindur, maxdur1, maxdur2; + + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + /*default init*/ + pam->sPhFeats[DUR] = 0; + pam->sPhFeats[F0] = 0; + /* + Hard coded parameters for quantization + */ + numstates = PICOPAM_NRSTPF; + f0quant = 30.0f; + minf0 = 90.0f; + maxf0 = 360.0f; + + durquant1 = 20.0f; + durquant2 = 100.0f; + mindur = 40.0f; + maxdur1 = 160.0f; + maxdur2 = 600.0f; + f0avg = 0.0f; + for (nI = 0; nI < numstates; nI++) + f0avg += pam->phonF0[nI]; + f0avg /= (picoos_single) numstates; + + f0avg = f_round(f0avg / f0quant) * f0quant; + if (f0avg < minf0) + f0avg = minf0; + if (f0avg > maxf0) + f0avg = maxf0; + + /*make initial silence of sentence shorter (see also pam_put_item)*/ + if ((pam->nCurrSyllable == 0) && (pam->nSyllPhoneme == 0)) { + pam->phonDur = 2 * 4; + } + + fDur = (picoos_single) pam->phonDur; + fDur = f_round(fDur / durquant1) * durquant1; + if (fDur < mindur) + fDur = mindur; + if (fDur > maxdur1) { + fDur = f_round(fDur / durquant2) * durquant2; + if (fDur > maxdur2) + fDur = maxdur2; + } + pam->sPhFeats[DUR] = (picoos_uint8) (fDur / (picoos_single) 10.0f); + pam->sPhFeats[F0] = (picoos_uint8) (f0avg / (picoos_single) 10.0f); + + return PICO_OK; +}/*pam_update_vector*/ + +/** + * compress a single feature in the range 0..9 + * @param inVal : the value to be compressed + * @return compVal : the compressed value + * @callgraph + * @callergraph + */ +static picoos_uint8 pamCompressComponent(picoos_uint8 inVal) +{ + if (inVal <= 5) + return inVal; + if ((5 < inVal) && (inVal <= 10)) + return 6; + if ((10 < inVal) && (inVal <= 20)) + return 7; + if ((20 < inVal) && (inVal <= 30)) + return 8; + return 9; +}/*pamCompressComponent*/ + +/** + * prepares the input vector for tree feeding + * @param this : Pam object pointer + * @return PICO_OK : vector expanded + * @return PICO_ERR_OTHER : errors on expansion or retrieving the PU pointer + * @remarks Modifies pam->sPhFeats[] + * @callgraph + * @callergraph + */ +static pico_status_t pam_expand_vector(register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + picoos_uint8 *inVect, *phonVect, *outVect, nI; + picoos_int16 nOffs, nOffs1, nLen; + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + inVect = &(pam->sSyllFeats[pam->nCurrSyllable].phoneV[0]); + phonVect = &(pam->sPhIds[0]); + outVect = &(pam->sPhFeats[0]); + /*just copy back*/ + for (nI = 0; nI < PICOPAM_INVEC_SIZE; nI++) + outVect[nI] = inVect[nI]; + /*now fill missing fields*/ + picoos_mem_copy((void*) &(inVect[FID]), &nOffs, sizeof(nOffs)); + /*offset to first phone of current syllable*/ + nOffs = nOffs + pam->nSyllPhoneme; /*offset to current phone of current syllable*/ + nLen = inVect[B3]; /*len of current syllable*/ + if (pam->nSyllPhoneme >= nLen) { + /*error on addressing current phone*/ + return PICO_ERR_OTHER; + } + /*previous of the previous phone*/ + nOffs1 = nOffs - 2; + if (nOffs1 >= 0) + outVect[P1] = phonVect[nOffs1]; + else + outVect[P1] = PICOPAM_PH_DONT_CARE_VAL; + /*previous phone*/ + nOffs1 = nOffs - 1; + if (nOffs1 >= 0) + outVect[P2] = phonVect[nOffs1]; + else + outVect[P2] = PICOPAM_PH_DONT_CARE_VAL; + /*^current phone*/ + outVect[P3] = phonVect[nOffs]; + + /*next phone*/ + nOffs1 = nOffs + 1; + if (nOffs1 < pam->nTotalPhonemes) + outVect[P4] = phonVect[nOffs1]; + else + outVect[P4] = PICOPAM_PH_DONT_CARE_VAL; + /*next of the next phone*/ + nOffs1 = nOffs + 2; + if (nOffs1 < pam->nTotalPhonemes) + outVect[P5] = phonVect[nOffs1]; + else + outVect[P5] = PICOPAM_PH_DONT_CARE_VAL; + /*pos of curr phone with respect to left syllable boundary*/ + outVect[P6] = pam->nSyllPhoneme + 1; + /*pos of curr phone with respect to right syllable boundary*/ + outVect[P7] = nLen - pam->nSyllPhoneme; + /*is current phone in consonant syllable boundary? (1:yes)*/ + if (pam->nSyllPhoneme < inVect[P8]) + outVect[P8] = 1; + else + outVect[P8] = 0; + return PICO_OK; +}/*pam_expand_vector*/ + +/** + * compresses the input vector for PAM + * @param this : Pam object pointer + * @return PICO_OK : compression successful + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @remarks Modifies pam->sPhFeats[] + * @callgraph + * @callergraph + */ +static pico_status_t pamCompressVector(register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + picoos_uint8 *outVect, nI; + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + outVect = &(pam->sPhFeats[0]); + for (nI = 0; nI < PICOPAM_INVEC_SIZE; nI++) { + switch (nI) { + case P1: + case P2: + case P3: + case P4: + case P5: + case B1: + case B2: + case B16: + case E1: + case H5: + /*don't do any compression*/ + break; + default: + /*do compression*/ + if (outVect[nI] != PICOPAM_DONT_CARE_VALUE) + outVect[nI] = pamCompressComponent(outVect[nI]); + else + outVect[nI] = PICOPAM_DONT_CARE_VAL; + break; + } + } + return PICO_OK; +}/*pamCompressVector*/ + +/** + * reorganizes the input vector for PAM + * @param this : Pam object pointer + * @return PICO_OK : reorganization successful + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @remarks Modifies pam->sPhFeats[] + * @callgraph + * @callergraph + */ +static pico_status_t pamReorgVector(register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + picoos_uint8 *outVect, inVect[60], nI; + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + outVect = &(pam->sPhFeats[0]); + for (nI = 0; nI < PICOPAM_INVEC_SIZE; nI++) inVect[nI] = outVect[nI]; + /*reorganize*/ + for (nI = T_B1; nI <= T_H5; nI++) { + switch (nI) { + case T_B1: + outVect[T_B1] = inVect[B1]; + break; + case T_B2: + outVect[T_B2] = inVect[B2]; + break; + case T_B3: + outVect[T_B3] = inVect[B3]; + break; + case T_B4: + outVect[T_B4] = inVect[B4]; + break; + case T_B5: + outVect[T_B5] = inVect[B5]; + break; + case T_B6: + outVect[T_B6] = inVect[B6]; + break; + case T_B7: + outVect[T_B7] = inVect[B7]; + break; + case T_B8: + outVect[T_B8] = inVect[B8]; + break; + case T_B9: + outVect[T_B9] = inVect[B9]; + break; + case T_B10: + outVect[T_B10] = inVect[B10]; + break; + case T_B11: + outVect[T_B11] = inVect[B11]; + break; + case T_B12: + outVect[T_B12] = inVect[B12]; + break; + case T_B13: + outVect[T_B13] = inVect[B13]; + break; + case T_B14: + outVect[T_B14] = inVect[B14]; + break; + case T_B15: + outVect[T_B15] = inVect[B15]; + break; + case T_B16: + outVect[T_B16] = inVect[B16]; + break; + case T_B17: + outVect[T_B17] = inVect[B17]; + break; + case T_B18: + outVect[T_B18] = inVect[B18]; + break; + case T_B19: + outVect[T_B19] = inVect[B19]; + break; + case T_B20: + outVect[T_B20] = inVect[B20]; + break; + case T_B21: + outVect[T_B21] = inVect[B21]; + break; + + case T_E1: + outVect[T_E1] = inVect[E1]; + break; + case T_E2: + outVect[T_E2] = inVect[E2]; + break; + case T_E3: + outVect[T_E3] = inVect[E3]; + break; + case T_E4: + outVect[T_E4] = inVect[E4]; + break; + case T_E5: + outVect[T_E5] = inVect[E5]; + break; + case T_E6: + outVect[T_E6] = inVect[E6]; + break; + case T_E7: + outVect[T_E7] = inVect[E7]; + break; + case T_E8: + outVect[T_E8] = inVect[E8]; + break; + case T_E9: + outVect[T_E9] = inVect[E9]; + break; + case T_E10: + outVect[T_E10] = inVect[E10]; + break; + case T_E11: + outVect[T_E11] = inVect[E11]; + break; + case T_E12: + outVect[T_E12] = inVect[E12]; + break; + case T_E13: + outVect[T_E13] = inVect[E13]; + break; + + case T_A3: + outVect[T_A3] = inVect[A3]; + break; + case T_C3: + outVect[T_C3] = inVect[C3]; + break; + case T_D2: + outVect[T_D2] = inVect[D2]; + break; + case T_F2: + outVect[T_F2] = inVect[F2]; + break; + + case T_G1: + outVect[T_G1] = inVect[G1]; + break; + case T_I1: + outVect[T_I1] = inVect[I1]; + break; + + case T_G2: + outVect[T_G2] = inVect[G2]; + break; + case T_I2: + outVect[T_I2] = inVect[I2]; + break; + + case T_H1: + outVect[T_H1] = inVect[H1]; + break; + case T_H2: + outVect[T_H2] = inVect[H2]; + break; + case T_H3: + outVect[T_H3] = inVect[H3]; + break; + case T_H4: + outVect[T_H4] = inVect[H4]; + break; + case T_H5: + outVect[T_H5] = inVect[H5]; + break; + } + } + return PICO_OK; +}/*pamReorgVector*/ + +/** + * puts a PAM item into PU output buffer + * @param this : Pam object pointer + * @param outBuff : output buffer base pointer + * @param outWritePos : offset in output buffer + * @param *bytesWr : actual bytes written + * @return PICO_OK : put successful + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @callgraph + * @callergraph + */ +static pico_status_t pam_put_item(register picodata_ProcessingUnit this, + picoos_uint8 *outBuff, picoos_uint16 outWritePos, picoos_uint8 *bytesWr) +{ + pam_subobj_t *pam; + picoos_uint8 *sDest, nI, nType, nIdx, fde; + picoos_uint32 pos, pos32; + picoos_int16 ft, dt; + picoos_uint16 uMinDur, uMaxDur; + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + sDest = &(outBuff[outWritePos]); + sDest[0] = PICODATA_ITEM_PHONE; /*Item type*/ + sDest[1] = pam->sPhFeats[P3]; /*phonetic id*/ + sDest[2] = PICOPAM_NRSTPF; /*number of states per phone*/ + sDest[3] = sizeof(picoos_uint16) * PICOPAM_NRSTPF * 3; /*size of the item*/ + pos = 4; + /*make initial silence of sentence shorter (see also UpdateVector)*/ + if ((pam->nCurrSyllable == 0) && (pam->nSyllPhoneme == 0)) { + for (nI = 0; nI < PICOPAM_NRSTPF - 1; nI++) + pam->numFramesState[nI] = 0; + pam->numFramesState[nI] = 2; + } else { + /*manage silence syllables with prescribed durations*/ + pos32 = Min; + picoos_read_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV, + &pos32, &uMinDur); + pos32 = Max; + picoos_read_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV, + &pos32, &uMaxDur); + + if (uMaxDur > 0) { + /* Select weights*/ + nType = pam->sSyllFeats[pam->nCurrSyllable].phoneV[bnd]; + switch (nType) { + case PICODATA_ITEMINFO1_BOUND_SBEG: + nIdx = PICOPAM_PWIDX_SBEG; + break; + case PICODATA_ITEMINFO1_BOUND_PHR1: + nIdx = PICOPAM_PWIDX_PHR1; + break; + case PICODATA_ITEMINFO1_BOUND_PHR2: + nIdx = PICOPAM_PWIDX_PHR2; + break; + case PICODATA_ITEMINFO1_BOUND_SEND: + case PICODATA_ITEMINFO1_BOUND_TERM: + nIdx = PICOPAM_PWIDX_SEND; + break; + default: + nIdx = PICOPAM_PWIDX_DEFA; + break; + } + fde = 2; + ft = 0; + dt = 0; + picodata_transformDurations( + fde, /* 2's exponent of frame duration in ms, e.g. 2 for 4ms, 3 for 8ms */ + PICOPAM_NRSTPF, /* number of states per phone */ + &(pam->numFramesState[0]), /* estimated durations */ + pam->sil_weights[nIdx], /* integer weights */ + uMinDur, /* minimum target duration in ms */ + uMaxDur, /* maximum target duration in ms */ + ft, /* factor to be multiplied to get the target */ + &dt /* in/out, rest in ms */ + ); + } + } + /*put data*/ + for (nI = 0; nI < PICOPAM_NRSTPF; nI++) { + picoos_write_mem_pi_uint16(sDest, &pos, + (picoos_uint16) pam->numFramesState[nI]); + picoos_write_mem_pi_uint16(sDest, &pos, + (picoos_uint16) pam->lf0Index[nI]); + picoos_write_mem_pi_uint16(sDest, &pos, + (picoos_uint16) pam->mgcIndex[nI]); + } + *bytesWr = sizeof(picodata_itemhead_t) + sizeof(picoos_uint16) + * PICOPAM_NRSTPF * 3; + return PICO_OK; +}/*pam_put_item*/ + +/** + * puts a non PAM (queued) item into PU output buffer + * @param qItem : pointer to item to put + * @param outBuff : output buffer base pointer + * @param outWritePos : offset in output buffer + * @param *bytesWr : actual bytes written + * @return PICO_OK : put successful + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @callgraph + * @callergraph + */ +static pico_status_t pam_put_qItem(picoos_uint8 *qItem, picoos_uint8 *outBuff, + picoos_uint16 outWritePos, picoos_uint8 *bytesWr) +{ + picoos_uint8 *sDest, nI; + sDest = &(outBuff[outWritePos]); + *bytesWr = sizeof(picodata_itemhead_t); + for (nI = 0; nI < (sizeof(picodata_itemhead_t) + qItem[3]); nI++) { + sDest[nI] = qItem[nI]; + } + *bytesWr = nI; + return PICO_OK; +}/*pam_put_qItem*/ + +/** + * tells if an item is a PAM command (except play) + * @param qItem : input item to test + * @return TRUE : qItem is a PAM command (except play) + * @return FALSE : qItem not a PAM command + * @callgraph + * @callergraph + */ +static pico_status_t is_pam_command(const picoos_uint8 * qItem) +{ + switch (qItem[0]) { + + case PICODATA_ITEM_CMD: + switch (qItem[1]) { + case PICODATA_ITEMINFO1_CMD_FLUSH: + /* flush is for all PU's and as such it is also for PAM*/ + case PICODATA_ITEMINFO1_CMD_PITCH: + case PICODATA_ITEMINFO1_CMD_SPEED: + return TRUE; + break; + default: + break; + } + } + return FALSE; +}/*is_pam_command*/ + +/** + * tells if an item is a PAM PLAY command + * @param qItem : input item to test + * @return TRUE : qItem is a PAM PLAY command + * @return FALSE : qItem not a PAM PLAY command + * @callgraph + * @callergraph + */ +static pico_status_t is_pam_play_command(picoos_uint8 *qItem) +{ + switch (qItem[0]) { + + case PICODATA_ITEM_CMD: + switch (qItem[1]) { + case PICODATA_ITEMINFO1_CMD_PLAY: + if (qItem[2] == PICODATA_ITEMINFO2_CMD_TO_PAM) + return TRUE; + break; + default: + break; + } + } + return FALSE; +}/*is_pam_play_command*/ + +/** + * command processor for PAM pu + * @param this : Pam item subobject + * @param qItem : input item pointer + * @return PICOPAM_FLUSH_RECEIVED : when a FLUSH is received + * @return PICOPAM_CONTINUE : normal command processing + * @return PICODATA_PU_ERROR : errors in accessing data + * @callgraph + * @callergraph + */ +static pico_status_t pamDoCommand(register picodata_ProcessingUnit this, + picoos_uint8 *qItem) +{ + pam_subobj_t *pam; + picoos_single fValue; + picoos_uint16 nValue; + picoos_uint32 nPos; + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + if (qItem[0] == PICODATA_ITEM_CMD) { + switch (qItem[1]) { + case PICODATA_ITEMINFO1_CMD_FLUSH: + /* flush is for all PU's and as such it is also for PAM : implement the flush!!*/ + pam_reset_processors(this); + pam->nLastAttachedItemId = pam->nCurrAttachedItem = 0; + pam->nAttachedItemsSize = 0; + return PICOPAM_FLUSH_RECEIVED; + break; + + case PICODATA_ITEMINFO1_CMD_PITCH: + case PICODATA_ITEMINFO1_CMD_SPEED: + nPos = 4; + picoos_read_mem_pi_uint16(qItem, &nPos, &nValue); + if (qItem[2] == 'a') { + /*absloute modifier*/ + fValue = (picoos_single) nValue / (picoos_single) 100.0f; + if (qItem[1] == PICODATA_ITEMINFO1_CMD_PITCH) + pam->pMod = fValue; + if (qItem[1] == PICODATA_ITEMINFO1_CMD_SPEED) + pam->dMod = (1.0f / fValue); + } + if (qItem[2] == 'r') { + /*relative modifier*/ + fValue = (picoos_single) nValue / (picoos_single) 1000.0f; + if (qItem[1] == PICODATA_ITEMINFO1_CMD_PITCH) + pam->pMod *= (1.0f / fValue); + if (qItem[1] == PICODATA_ITEMINFO1_CMD_SPEED) + pam->dMod *= (1.0f / fValue); + } + return PICOPAM_CONTINUE; + break; + + default: + break; + }/*end switch switch (qItem[1])*/ + }/*end if (qItem[0]==PICODATA_ITEM_CMD)*/ + return PICOPAM_CONTINUE; +}/*pamDoCommand*/ + +/** + * defines if an item has to be sent to following PUs + * @param qItem : input item pointer + * @return TRUE : item has to be transmitted to following PUs + * @return FALSE : item has to be consumed internallz on PAM + * @callgraph + * @callergraph + */ +static pico_status_t isItemToPut(picoos_uint8 *qItem) +{ + switch (qItem[0]) { + case PICODATA_ITEM_CMD: + /* is a command*/ + if (PICODATA_ITEMINFO1_CMD_SPEED == qItem[1]) { + /* SPEED consumed here*/ + return FALSE; + } + break; + case PICODATA_ITEM_BOUND: + switch (qItem[1]) { + case PICODATA_ITEMINFO1_BOUND_SBEG: + case PICODATA_ITEMINFO1_BOUND_PHR0: + case PICODATA_ITEMINFO1_BOUND_PHR1: + case PICODATA_ITEMINFO1_BOUND_PHR2: + case PICODATA_ITEMINFO1_BOUND_PHR3: + /*boudary items consumed here except SEND,TERM*/ + return FALSE; + break; + default: + break; + } + break; + default: + break; + } + /*all other items not explicitly mentioned here + are transmitted to next PUs*/ + return TRUE; +}/*isItemToPut*/ + +/** + * pushes a boundary TERM item into some buffer + * @param outBuff : output buffer base pointer + * @param outWritePos : offset in output buffer + * @param *bytesWr : actual bytes written + * @return PICO_OK + * @remarks used while forcing TERM input items in forward processing + * @callgraph + * @callergraph + */ +static pico_status_t pam_put_term(picoos_uint8 *outBuff, + picoos_uint16 outWritePos, picoos_uint8 *bytesWr) +{ + picoos_uint8 *sDest; + sDest = &(outBuff[outWritePos]); + sDest[0] = PICODATA_ITEM_BOUND; /*Item type*/ + sDest[1] = PICODATA_ITEMINFO1_BOUND_TERM; + sDest[2] = PICODATA_ITEMINFO2_BOUNDTYPE_T; + sDest[3] = 0; /*item size*/ + *bytesWr = 4; + return PICO_OK; +}/*pam_put_term*/ + +/** + * translates one full phone into a PHONE Item including DT Dur, F0 and CEP trees feature generation and traversal + * @param this : Pam item subobject pointer + * @return PICO_OK : processing successful + * @return PICODATA_PU_ERROR : error accessing PAM object + * @return !=PICO_OK : processing errors + * @callgraph + * @callergraph + */ +static pico_status_t pamPhoneProcess(register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + pico_status_t sResult; + picokdt_classify_result_t dTreeResult; + picoos_uint8 nI, bWr; + + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + /*expands current phone in current syllable in the corresponding vector pam->sPhFeats[]*/ + sResult = pam_expand_vector(this); + sResult = pamCompressVector(this); + sResult = pamReorgVector(this); + + /*tree traversal for duration*/ + if (!pam_do_tree(this, pam->dtdur, &(pam->sPhFeats[0]), PICOPAM_INVEC_SIZE, + &dTreeResult)) { + PICODBG_WARN(("problem using pam tree dtdur, using fallback value")); + dTreeResult.class = 0; + } + pam->durIndex = dTreeResult.class; + sResult = pam_get_duration(this, pam->durIndex, &(pam->phonDur), + &(pam->numFramesState[0])); + + /*tree traversal for pitch*/ + for (nI = 0; nI < PICOPAM_MAX_STATES_PER_PHONE; nI++) { + if (!pam_do_tree(this, pam->dtlfz[nI], &(pam->sPhFeats[0]), + PICOPAM_INVEC_SIZE, &dTreeResult)) { + PICODBG_WARN(("problem using pam tree lf0Tree, using fallback value")); + dTreeResult.class = 0; + } + pam->lf0Index[nI] = dTreeResult.class; + } + + /*pdf access for pitch*/ + for (nI = 0; nI < PICOPAM_MAX_STATES_PER_PHONE; nI++) { + sResult = pam_get_f0(this, &(pam->lf0Index[0]), nI, &(pam->phonF0[0])); + } + + /*update vector with duration and pitch for cep tree traversal*/ + sResult = pam_update_vector(this); + /*cep tree traversal*/ + for (nI = 0; nI < PICOPAM_MAX_STATES_PER_PHONE; nI++) { + + if (!pam_do_tree(this, pam->dtmgc[nI], &(pam->sPhFeats[0]), + PICOPAM_INVEC_SIZE, &dTreeResult)) { + PICODBG_WARN(("problem using pam tree lf0Tree, using fallback value")); + dTreeResult.class = 0; + } + pam->mgcIndex[nI] = dTreeResult.class; + } + /*put item to output buffer*/ + sResult = pam_put_item(this, pam->outBuf, pam->outWritePos, &bWr); + if (sResult == PICO_OK) + pam->outWritePos += bWr; + else + return sResult; + return PICO_OK; +}/*pamPhoneProcess*/ + +/** + * manages first syllable attached items when seen before SBEG + * @param this : Pam item subobject pointer + * @return PICO_OK (0) : default return code --> means no more items to be processed before 1st syllable + * @return PICOPAM_GOTO_FEED : go to feed state after this + * @return PICOPAM_GOTO_SCHEDULE : flush received + * @return PICODATA_PU_ERROR : errors + * @callgraph + * @callergraph + */ +static pico_status_t pamDoPreSyll(register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + pico_status_t sResult; + picoos_uint8 bWr, nRc; + picoos_uint8 *qItem; + nRc = PICOPAM_PRE_SYLL_ENDED; + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + /*regenerate initial items before the phonemes*/ + if (((qItem = pamPopAttachedSy0(this)) != NULL) && !((qItem[0] + == PICODATA_ITEM_BOUND) && (qItem[1] + == PICODATA_ITEMINFO1_BOUND_SBEG))) { + if (isItemToPut(qItem)) { + pam_put_qItem(qItem, pam->outBuf, pam->outWritePos, &bWr);/*popped item has to be sent to next PU*/ + pam->outWritePos += bWr; + nRc = PICOPAM_GOTO_FEED; + } + + if (is_pam_command(qItem) == TRUE) { + nRc = pamDoCommand(this, qItem); /*popped item is a PAM command : do it NOW!!*/ + if ((nRc == PICOPAM_FLUSH_RECEIVED) || (nRc == PICODATA_PU_ERROR)) { + /*FLUSH command RECEIVED or errors: stop ALL PROCESSING*/ + return nRc; + } + } + pam->nCurrAttachedItem++; + if (nRc == 0) + return PICOPAM_CONTINUE; + else + return nRc; + } + /*SBEG item management*/ + if ((qItem != NULL) && (qItem[0] == PICODATA_ITEM_BOUND) && (qItem[1] + == PICODATA_ITEMINFO1_BOUND_SBEG)) { + sResult = pam_put_qItem(qItem, pam->outBuf, pam->outWritePos, &bWr); + pam->outWritePos += bWr; + pam->nCurrAttachedItem++; + nRc = PICOPAM_GOTO_FEED; + } + return nRc; +}/*pamDoPreSyll*/ + +/** + * performs a step of the pam processing + * @param this : Pam item subobject pointer + * @param mode : mode for the PU + * @param *numBytesOutput : pointer to output number fo bytes produced + * @return PICODATA_PU_IDLE : nothing to do + * @return PICODATA_PU_BUSY : still tasks undergoing + * @return PICODATA_PU_ERROR : errors on processing + * @callgraph + * @callergraph + */ +static picodata_step_result_t pam_step(register picodata_ProcessingUnit this, + picoos_int16 mode, picoos_uint16 * numBytesOutput) +{ + + register pam_subobj_t * pam; + + pico_status_t sResult; + picoos_uint16 blen, numinb, numoutb; + pico_status_t rv; + picoos_uint8 bWr; + picoos_uint8 bForcedItem[4]; + picoos_uint8 *qItem; + + numinb = 0; + numoutb = 0; + rv = PICO_OK; + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + mode = mode; /* avoid warning "var not used in this function"*/ + /*Init number of output bytes*/ + *numBytesOutput = 0; + + while (1) { /* exit via return */ + + PICODBG_DEBUG(("pam_step -- doing state %i",pam->procState)); + + switch (pam->procState) { + + case PICOPAM_COLLECT: + /* *************** item collector ***********************************/ + /*collecting items from the PU input buffer*/ + sResult = picodata_cbGetItem(this->cbIn, + &(pam->inBuf[pam->inWritePos]), pam->inBufSize + - pam->inWritePos, &blen); + if (sResult != PICO_OK) { + if (sResult == PICO_EOF) { + /*no items available : remain in state 0 and return idle*/ + return PICODATA_PU_IDLE; + } else { + /*errors : remain in state 0 and return error*/ + PICODBG_DEBUG(("pam_step(PICOPAM_COLLECT) -- Errors on item buffer input, status: %d",sResult)); + return PICODATA_PU_ERROR; + } + } + + PICODBG_DEBUG(("pam_step -- got item, status: %d",sResult)); + sResult = picodata_is_valid_item( + &(pam->inBuf[pam->inWritePos]), blen); + if (sResult != TRUE) { + /*input item is not valid : consume the input item and stay in COLLECT*/ + pam->inWritePos += blen; + pam->inReadPos += blen; + if (pam->inReadPos >= pam->inWritePos) { + pam->inReadPos = 0; + pam->inWritePos = 0; + }PICODBG_DEBUG(("pam_step -- item is not valid, type: %d",pam->inBuf[pam->inWritePos])); + return PICODATA_PU_BUSY; + } + + /*update input write pointer + move to "schedule" state*/ + pam->inWritePos += blen; + pam->procState = PICOPAM_SCHEDULE; + return PICODATA_PU_BUSY; + + case PICOPAM_SCHEDULE: + /* check out if more items are available */ + if (pam->inReadPos >= pam->inWritePos) { + /*no more items : back to collect state*/ + pam->procState = PICOPAM_COLLECT; + return PICODATA_PU_BUSY; + } + /* we have one full valid item, with len>0 starting at + pam->inBuf[pam->inReadPos]; here we decide how to elaborate it */ + + /* PLAY management */ + if (is_pam_play_command(&(pam->inBuf[pam->inReadPos])) == TRUE) { + /*consume the input item : it has been managed*/ + pam->inReadPos += pam->inBuf[pam->inReadPos + 3] + + sizeof(picodata_itemhead_t); + if (pam->inReadPos >= pam->inWritePos) { + pam->inReadPos = 0; + pam->inWritePos = 0; + } + /*stay in schedule*/ + return PICODATA_PU_BUSY; + } + + if (pam_check_immediate(this, &(pam->inBuf[pam->inReadPos]))) { + /* item has to be sent to next PU NOW : switch to "immediate" state */ + pam->procState = PICOPAM_IMMEDIATE; + return PICODATA_PU_BUSY; + } + if (pamCheckResourceLimits(this, &(pam->inBuf[pam->inReadPos]))) { + /* item would not fit into local buffers -->> free some space -->> + switch to "force term" state */ + pam->procState = PICOPAM_FORWARD_FORCE_TERM; + return PICODATA_PU_BUSY; + } + + if (pam_deal_with(&(pam->inBuf[pam->inReadPos]))) { + /* item has to be managed by the "forward" state : switch to forward state*/ + pam->procState = PICOPAM_FORWARD; + return PICODATA_PU_BUSY; + } + + if (pam_hastobe_queued(this, &(pam->inBuf[pam->inReadPos]))) { + /* item is not for PAM so it has to be queued internally */ + pam_queue(this, &(pam->inBuf[pam->inReadPos])); + /*consume the input item : it has been queued*/ + pam->inReadPos += pam->inBuf[pam->inReadPos + 3] + + sizeof(picodata_itemhead_t); + if (pam->inReadPos >= pam->inWritePos) { + pam->inReadPos = 0; + pam->inWritePos = 0; + } + return PICODATA_PU_BUSY; + } + /*if we get here something wrong happened. Being the the item valid, + switch to "immediate" state -> send it to next PU -> */ + PICODBG_DEBUG(("pam_step (PICOPAM_SCHEDULE) -- unexpected item is sent to next PU !!")); + pam->procState = PICOPAM_IMMEDIATE; + return PICODATA_PU_BUSY; + break; /*PICOPAM_SCHEDULE*/ + + case PICOPAM_FORWARD: + /*we have one full valid item, with len>0 starting at pam->inBuf[pam->inReadPos]. + furthermore this item should be in the set {BOUND,SYLL}. + No other items should arrive here*/ + sResult = pam_adapter_forward_step(this, + &(pam->inBuf[pam->inReadPos])); + /*decide if this item has to be queued for later re-synchronization + normally this is only done for SEND/TERM items*/ + if (pam_hastobe_queued(this, &(pam->inBuf[pam->inReadPos]))) { + /*item has to be queued iternally in local storage*/ + pam_queue(this, &(pam->inBuf[pam->inReadPos])); + } + /*now assign next state according to Forward results*/ + switch (sResult) { + case PICOPAM_READY: + pam->needMoreInput = FALSE; + /*consume the input item : it has already been stored*/ + pam->inReadPos += pam->inBuf[pam->inReadPos + 3] + + sizeof(picodata_itemhead_t); + if (pam->inReadPos >= pam->inWritePos) { + pam->inReadPos = 0; + pam->inWritePos = 0; + } + /*activate backward processing*/ + sResult = pam_adapter_backward_step(this); + if (sResult == PICO_OK) { + pam->procState = PICOPAM_PROCESS; + return PICODATA_PU_BUSY; + } else { + PICODBG_DEBUG(("pam_step (PICOPAM_FORWARD) -- wrong return from BackwardStep: %d -- Buffered sentence will be discarded",sResult)); + pam_reset_processors(this); + pam->nLastAttachedItemId = pam->nCurrAttachedItem + = 0; + pam->nAttachedItemsSize = 0; + + pam->procState = PICOPAM_SCHEDULE; + return PICODATA_PU_BUSY; + } + break; + + case PICOPAM_MORE: + pam->needMoreInput = TRUE; + /*consume the input item : it has already been stored*/ + pam->inReadPos += pam->inBuf[pam->inReadPos + 3] + + sizeof(picodata_itemhead_t); + if (pam->inReadPos >= pam->inWritePos) { + /*input is finished and PAM need more data : + clenaup input buffer + switch state back to "schedule state" + */ + pam->inReadPos = 0; + pam->inWritePos = 0; + pam->procState = PICOPAM_SCHEDULE; + return PICODATA_PU_ATOMIC; + } else { + /*input is not finished and need more data : + remain in state "PICOPAM_FORWARD" */ + return PICODATA_PU_ATOMIC; + } + break; + + case PICOPAM_NA: + default: + /*this item has not been stored in internal buffers: + assign this item to the management of + "immediate" state*/ + pam->procState = PICOPAM_IMMEDIATE; + return PICODATA_PU_BUSY; + break; + } /*end switch sResult*/ + break; /*PICOPAM_FORWARD*/ + + case PICOPAM_FORWARD_FORCE_TERM: + /*we have one full valid item, with len>0 + starting at pam->inBuf[pam->inReadPos] but we decided + to force a TERM item before, without losing the item in + inBuf[inReadPos] : --> generate a TERM item and do the + forward processing */ + pam_put_term(bForcedItem, 0, &bWr); + sResult = pam_adapter_forward_step(this, &(bForcedItem[0])); + switch (sResult) { + case PICOPAM_READY: + pam_queue(this, &(bForcedItem[0])); + /*activate backward processing*/ + sResult = pam_adapter_backward_step(this); + if (sResult == PICO_OK) { + pam->procState = PICOPAM_PROCESS; + return PICODATA_PU_BUSY; + } else { + PICODBG_DEBUG(("pam_step (PICOPAM_FORWARD_FORCE_TERM) -- wrong return from BackwardStep: %d -- Buffered sentence will be discarded",sResult)); + pam_reset_processors(this); + pam->nLastAttachedItemId = pam->nCurrAttachedItem + = 0; + pam->nAttachedItemsSize = 0; + + pam->procState = PICOPAM_SCHEDULE; + return PICODATA_PU_BUSY; + } + break; + + default: + PICODBG_DEBUG(("pam_step (PICOPAM_FORWARD_FORCE_TERM) -- Forced a TERM but processing do not appear to end -- Buffered sentence will be discarded",sResult)); + pam_reset_processors(this); + pam->nLastAttachedItemId = pam->nCurrAttachedItem = 0; + pam->nAttachedItemsSize = 0; + + pam->procState = PICOPAM_SCHEDULE; + return PICODATA_PU_BUSY; + break; + + } /*end switch sResult*/ + break; /*PICOPAM_FORWARD_FORCE_TERM*/ + + case PICOPAM_PROCESS: + + if ((PICOPAM_FRAME_ITEM_SIZE + 4) > (pam->outBufSize + - pam->outWritePos)) { + /*WARNING (buffer overflow): leave status unchanged until output buffer free */ + return PICODATA_PU_BUSY; + } + + if (pam->nCurrSyllable == 0) { + sResult = pamDoPreSyll(this); + if (sResult == PICOPAM_GOTO_FEED) { + /* + items pushed to output buffer : + switch to "feed" but then back + to "process" + */ + pam->retState = PICOPAM_PROCESS; + pam->procState = PICOPAM_FEED; + return PICODATA_PU_BUSY; + } + if (sResult == PICOPAM_CONTINUE) { + /* + items processed (maybe commands) : + return (maybe we need to process other + items in pre_syll) and then back to "process" + */ + pam->retState = PICOPAM_PROCESS; + pam->procState = PICOPAM_PROCESS; + return PICODATA_PU_BUSY; + } + + if ((sResult == PICOPAM_FLUSH_RECEIVED) || (sResult + == PICODATA_PU_ERROR)) { + /* + items processed were a flush or + problems found: switch to "schedule" + and abort all processing + */ + pam->retState = PICOPAM_SCHEDULE; + pam->procState = PICOPAM_SCHEDULE; + return PICODATA_PU_BUSY; + } + if (sResult == PICOPAM_PRE_SYLL_ENDED) { + /* + we get here when pam->nCurrSyllable==0 and + no more items to be processed before the syllable + */ + sResult = sResult; + } + } + + if (pamHasToProcess(this)) { + if (pamPhoneProcess(this) == PICO_OK) { + sResult = pamUpdateProcess(this); + pam->procState = PICOPAM_FEED; /*switch to feed*/ + return PICODATA_PU_BUSY; + } else { + PICODBG_DEBUG(("pam_step(PICOPAM_PROCESS) --- NULL return from pamPhoneProcess")); + return PICODATA_PU_ERROR; + } + } + + if (pamHasToPop(this) != FALSE) { + if ((qItem = pamPopItem(this)) == NULL) { + PICODBG_DEBUG(("pam_step(PICOPAM_PROCESS) --- NULL return from pamPopItem")); + return PICODATA_PU_ERROR; + } + + if (isItemToPut(qItem)) { + /*popped item has to be sent to next PU*/ + sResult = pam_put_qItem(qItem, pam->outBuf, + pam->outWritePos, &bWr); + if (sResult != PICO_OK) { + PICODBG_DEBUG(("pam_step(PICOPAM_PROCESS) --- Error on writing item to output buffer")); + return PICODATA_PU_ERROR; + } + pam->outWritePos += bWr; /*item write ok*/ + pam->procState = PICOPAM_FEED; /*switch to feed*/ + } + + /*moved command processing here (after pam_put_qItem) because of FLUSH command could erase + * the syllable structure and make it impossible to transmit the flush to other PUs*/ + if (is_pam_command(qItem) == TRUE) { + sResult = pamDoCommand(this, qItem); /*popped item is a PAM command : do it NOW!!*/ + if ((sResult == PICOPAM_FLUSH_RECEIVED) || (sResult + == PICODATA_PU_ERROR)) { + pam->retState = PICOPAM_SCHEDULE; + pam->procState = PICOPAM_SCHEDULE; /*switch to schedule */ + return PICODATA_PU_BUSY; + } + } + /*update PAM status: if more items attached to the current syllable + stay in current syllable, otherwise move to next syllable and switch + to processing phones */ + sResult = pamUpdateProcess(this); /*both "doCommand" or "put" : update PAM status*/ + return PICODATA_PU_BUSY; + } else { + pam->procState = PICOPAM_SCHEDULE; /*switch to schedule */ + return PICODATA_PU_BUSY; + } + + break; /*PICOPAM_PROCESS*/ + + case PICOPAM_IMMEDIATE: + /* *** item is output NOW!!! */ + /*context: full valid item, with len> starting at pam->inBuf[pam->inReadPos]*/ + numinb = PICODATA_ITEM_HEADSIZE + + pam->inBuf[pam->inReadPos + 3]; + sResult = picodata_copy_item(&(pam->inBuf[pam->inReadPos]), + numinb, &(pam->outBuf[pam->outWritePos]), + pam->outBufSize - pam->outWritePos, &numoutb); + + if (sResult == PICO_OK) { + pam->inReadPos += numinb; + if (pam->inReadPos >= pam->inWritePos) { + pam->inReadPos = 0; + pam->inWritePos = 0; + pam->needMoreInput = FALSE; + } + pam->outWritePos += numoutb; + pam->procState = PICOPAM_FEED; /*switch to FEED state*/ + pam->retState = PICOPAM_SCHEDULE; /*back to SCHEDULE after FEED*/ + } else { + /* + PICO_EXC_BUF_IGNORE + PICO_EXC_BUF_UNDERFLOW + PICO_EXC_BUF_OVERFLOW + */ + PICODBG_DEBUG(("pam_step(PICOPAM_IMMEDIATE) --- wrong return from picodata_copy_item:%d",sResult)); + return PICODATA_PU_ERROR; + } + return PICODATA_PU_BUSY; + break; /*PICOPAM_IMMEDIATE*/ + + case PICOPAM_FEED: + /* *************** item output/feeding ***********************************/ + /*feeding items to PU output buffer*/ + sResult = picodata_cbPutItem(this->cbOut, + &(pam->outBuf[pam->outReadPos]), pam->outWritePos + - pam->outReadPos, &numoutb); + PICODBG_DEBUG(("pam_step -- put item, status: %d",sResult)); + if (PICO_OK == sResult) { + + PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], + (picoos_uint8 *)"pam: ", + pam->outBuf + pam->outReadPos, pam->outBufSize); + + pam->outReadPos += numoutb; + *numBytesOutput = numoutb; + if (pam->outReadPos >= pam->outWritePos) { + /*reset the output pointers*/ + pam->outReadPos = 0; + pam->outWritePos = 0; + /*switch to appropriate state*/ + switch (pam->retState) { + case PICOPAM_IMMEDIATE: + pam->procState = PICOPAM_IMMEDIATE; + pam->retState = PICOPAM_SCHEDULE; + return PICODATA_PU_BUSY; + break; + case PICOPAM_PLAY: + pam->procState = PICOPAM_PLAY; + pam->retState = PICOPAM_SCHEDULE; + return PICODATA_PU_BUSY; + break; + default: + break; + } + /*Define next state + a)process (if current sentence has more data to process) + b)schedule (no more data to process in current sentence) + NOTE : case b)also happens when dealing with non BOUND/SYLL items*/ + if ((pamHasToProcess(this)) || (pamHasToPop(this))) { + pam->procState = PICOPAM_PROCESS; + } else { + pam->nCurrSyllable = -1; + pam_reset_processors(this); + pam->nLastAttachedItemId = pam->nCurrAttachedItem + = 0; + pam->nAttachedItemsSize = 0; + + pam->nSyllPhoneme = 0; + pam->procState = PICOPAM_SCHEDULE; + } + } + return PICODATA_PU_BUSY; + + } else if (PICO_EXC_BUF_OVERFLOW == sResult) { + + PICODBG_DEBUG(("pam_step ** feeding, overflow, PICODATA_PU_OUT_FULL")); + return PICODATA_PU_OUT_FULL; + + } else if ((PICO_EXC_BUF_UNDERFLOW == sResult) + || (PICO_ERR_OTHER == sResult)) { + + PICODBG_DEBUG(("pam_step ** feeding problem, discarding item")); + pam->outReadPos = 0; + pam->outWritePos = 0; + pam->procState = PICOPAM_COLLECT; + return PICODATA_PU_ERROR; + + } + break; /*PICOPAM_FEED*/ + + default: + /*NOT feeding items*/ + sResult = PICO_EXC_BUF_IGNORE; + break; + }/*end switch*/ + return PICODATA_PU_BUSY; /*check if there is more data to process after feeding*/ + + }/*end while*/ + return PICODATA_PU_IDLE; +}/*pam_step*/ + +/** + * performs one step of a PamTree + * @param this : Pam item subobject pointer + * @param dtpam : the Pam decision tree + * @param *invec : the input vector pointer + * @param inveclen : length of the input vector + * @param *dtres : the classification result + * @return dtres->set : the result of tree traversal + * @callgraph + * @callergraph + */ +static picoos_uint8 pam_do_tree(register picodata_ProcessingUnit this, + const picokdt_DtPAM dtpam, const picoos_uint8 *invec, + const picoos_uint8 inveclen, picokdt_classify_result_t *dtres) +{ + picoos_uint8 okay; + + okay = TRUE; + /* construct input vector, which is set in dtpam */ + if (!picokdt_dtPAMconstructInVec(dtpam, invec, inveclen)) { + /* error constructing invec */ + PICODBG_WARN(("problem with invec")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, NULL, NULL); + okay = FALSE; + } + /* classify */ + if (okay && (!picokdt_dtPAMclassify(dtpam))) { + /* error doing classification */ + PICODBG_WARN(("problem classifying")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, NULL, + NULL); + okay = FALSE; + } + /* decompose */ + if (okay && (!picokdt_dtPAMdecomposeOutClass(dtpam, dtres))) { + /* error decomposing */ + PICODBG_WARN(("problem decomposing")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_OUTVECTOR, NULL, NULL); + okay = FALSE; + } + + PICODBG_TRACE(("dtpam output class: %d", dtres->class)); + + return dtres->set; +}/*pam_do_tree*/ + +/** + * returns the carrier vowel id inside a syllable + * @param this : Pam item subobject pointer + * @param item : the full syllable item + * @param *pos : pointer to the variable to receive the position of the carrier vowel + * @return the phonetic id for the carrier vowel inside the syllable + * @callgraph + * @callergraph + */ +static picoos_uint8 pam_get_vowel_name(register picodata_ProcessingUnit this, + picoos_uint8 *item, picoos_uint8 *pos) +{ + pam_subobj_t *pam; + picoos_uint8 *phon, nI, nCond1; + if (NULL == this || NULL == this->subObj) { + return 0; + } + pam = (pam_subobj_t *) this->subObj; + + if (item == NULL) + return 0; + if (item[3] == 0) + return 0; + phon = &item[4]; + for (nI = 0; nI < item[3]; nI++) { + nCond1 = picoktab_isSyllCarrier(pam->tabphones, phon[nI]); + if (nCond1) { + *pos = nI; + return phon[nI]; + } + } + return 0; +}/*pam_get_vowel_name */ + +/** + * returns the pause phone id in the current ph.alphabet + * @param this : Pam sub object pointer + * @return the (numeric) phonetic id of the pause phone in current phonetic alphabet + * @return 0 : errors on getting the pam subobject pointer + * @callgraph + * @callergraph + */ +static picoos_uint8 pam_get_pause_id(register picodata_ProcessingUnit this) +{ + picoos_uint8 nVal1; + /*picoos_uint8 nVal2; */ + pam_subobj_t *pam; + if (NULL == this || NULL == this->subObj) { + return 0; + } + pam = (pam_subobj_t *) this->subObj; + nVal1 = picoktab_getPauseID(pam->tabphones); + return nVal1; +}/*pam_get_pause_id */ + +/** + * returns the pam sentence type (declarative, interrogative...) + * @param iteminfo1 : the boundary item info 1 + * @param iteminfo2 : the boundary item info 2 + * @return the sentence type suitably encoded for trees + * @callgraph + * @callergraph + */ +static picoos_uint8 pam_map_sentence_type(picoos_uint8 iteminfo1, + picoos_uint8 iteminfo2) +{ + switch (iteminfo2) { + case PICODATA_ITEMINFO2_BOUNDTYPE_P: + return PICOPAM_DECLARATIVE; + case PICODATA_ITEMINFO2_BOUNDTYPE_T: + return PICOPAM_DECLARATIVE; + case PICODATA_ITEMINFO2_BOUNDTYPE_Q: + return PICOPAM_INTERROGATIVE; + case PICODATA_ITEMINFO2_BOUNDTYPE_E: + return PICOPAM_DECLARATIVE; + default: + return PICOPAM_DECLARATIVE; + } + iteminfo1 = iteminfo1; /* avoid warning "var not used in this function"*/ + return PICOPAM_DECLARATIVE; +}/*pam_map_sentence_type */ + +/** + * returns the pam phrase type + * @param iteminfo1 : the boundary item info 1 + * @param iteminfo2 : the boundary item info 2 + * @return the phrase type suitably encoded for trees + * @callgraph + * @callergraph + */ +static picoos_uint8 pam_map_phrase_type(picoos_uint8 iteminfo1, + picoos_uint8 iteminfo2) +{ + + switch (iteminfo2) { + case PICODATA_ITEMINFO2_BOUNDTYPE_P: + switch (iteminfo1) { + case PICODATA_ITEMINFO1_BOUND_PHR1: +# ifdef PAM_PHR2_WITH_PR1 + case PICODATA_ITEMINFO1_BOUND_PHR2: +# endif + return PICOPAM_P; /*current_prhase type = "P" (encoded to 1) */ + break; + case PICODATA_ITEMINFO1_BOUND_PHR3: +# ifdef PAM_PHR2_WITH_PR3 + case PICODATA_ITEMINFO1_BOUND_PHR2 : +# endif + return PICOPAM_p; /*current_prhase type = "p" (encoded to 2) */ + break; + case PICODATA_ITEMINFO1_BOUND_SBEG: + return PICOPAM_P; /*current_prhase type = "P" (encoded to 1) */ + break; + default: + PICODBG_DEBUG(("Map pam_map_phrase_type : unexpected iteminfo1")); + return PICOPAM_P; /*current_prhase type = "P" (encoded to 1) */ + break; + } + case PICODATA_ITEMINFO2_BOUNDTYPE_T: + return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */ + break; + case PICODATA_ITEMINFO2_BOUNDTYPE_E: + return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */ + break; + case PICODATA_ITEMINFO2_BOUNDTYPE_Q: + return PICOPAM_Y; /*current_prhase type = "T" (encoded to 0) */ + break; + default: + PICODBG_DEBUG(("Map pam_map_phrase_type : unexpected iteminfo2")); + return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */ + break; + }PICODBG_DEBUG(("Map pam_map_phrase_type : unexpected iteminfo2")); + return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */ + +}/*pam_map_phrase_type */ + +/** + * does the cleanup of the sub object processors flags at sentence start + * @param this : pointer to PAM PU sub object pointer + * @return PICO_OK : reset OK + * @return PICO_ERR_OTHER : errors on getting pam sub obj pointer + * @callgraph + * @callergraph + */ +static pico_status_t pam_reset_processors(register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + + pam->nCurrSyllable = -1; + pam->nTotalPhonemes = pam->nSyllPhoneme = pam->nCurrPhoneme + = pam->nTotalSyllables = pam->sType = pam->pType = 0; + pam->dRest = 0.0f; + /*set all to 0*/ + pam->a3_overall_syllable = pam->a3_primary_phrase_syllable = pam->b4_b5_syllable = + pam->b6_b7_syllable = pam->b6_b7_state = pam->b8_b9_stressed_syllable = + pam->b10_b11_accented_syllable = pam->b12_b13_syllable = pam->b12_b13_state = + pam->b14_b15_syllable = pam->b14_b15_state = pam->b17_b19_syllable = + pam->b17_b19_state = pam->b18_b20_b21_syllable = pam->b18_b20_b21_state = + pam->c3_overall_syllable= pam->c3_primary_phrase_syllable = pam->d2_syllable_in_word = + pam->d2_prev_syllable_in_word = pam->d2_current_primary_phrase_word = pam->e1_syllable_word_start = + pam->e1_syllable_word_end= pam->e1_content = pam->e2_syllable_word_start = + pam->e2_syllable_word_end= pam->e3_e4_word = pam->e3_e4_state = + pam->e5_e6_content_word = pam->e5_e6_content = pam->e7_e8_word = + pam->e7_e8_content = pam->e7_e8_state = pam->e9_e11_word = + pam->e9_e11_saw_word = pam->e9_e11_state = pam->e10_e12_e13_word = + pam->e10_e12_e13_state = pam->e10_e12_e13_saw_word = pam->f2_overall_word = + pam->f2_word_syllable = pam->f2_next_word_syllable = pam->f2_current_primary_phrase_word = + pam->g1_current_secondary_phrase_syllable = pam->g1_current_syllable = + pam->g2_current_secondary_phrase_word = pam->g2_current_word = + pam->h1_current_secondary_phrase_syll = pam->h2_current_secondary_phrase_word = + pam->h3_h4_current_secondary_phrase_word = pam->h5_current_phrase_type = + pam->h5_syllable = pam->h5_state = pam->i1_secondary_phrase_syllable = + pam->i1_next_secondary_phrase_syllable = pam->i2_secondary_phrase_word = + pam->i2_next_secondary_phrase_word = pam->j1_utterance_syllable = + pam->j2_utterance_word = pam->j3_utterance_sec_phrases = 0; + /*Override 0 with 1*/ + pam->b4_b5_syllable = pam->b17_b19_syllable = pam->b18_b20_b21_syllable = + pam->e9_e11_word = pam->e10_e12_e13_word = pam->e7_e8_word = + pam->h2_current_secondary_phrase_word = 1; + /*Override 0 with -1*/ + pam->e1_syllable_word_start = pam->e1_syllable_word_end = pam->e2_syllable_word_start = + pam->e2_syllable_word_end = -1; + + return PICO_OK; +}/*pam_reset_processors*/ + +/** + * does the cleanup of the sub object processors flags before the backward step + * @param this : pointer to PAM PU sub object pointer + * @return PICO_OK : reset OK + * @return PICO_ERR_OTHER : errors on getting pam sub obj pointer + * @callgraph + * @callergraph + */ +static pico_status_t pam_reset_processors_back( + register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + + /*set all to 0*/ + pam->a3_overall_syllable + = pam->a3_primary_phrase_syllable + = pam->b4_b5_syllable + = pam->b6_b7_syllable + = pam->b6_b7_state + = pam->b8_b9_stressed_syllable + = pam->b10_b11_accented_syllable + = pam->b12_b13_syllable + = pam->b12_b13_state + = pam->b14_b15_syllable + = pam->b14_b15_state + = pam->b17_b19_syllable + = pam->b17_b19_state + = pam->b18_b20_b21_syllable + = pam->b18_b20_b21_state + = pam->c3_overall_syllable + = pam->c3_primary_phrase_syllable + = pam->d2_syllable_in_word + = pam->d2_prev_syllable_in_word + = pam->d2_current_primary_phrase_word + = pam->e1_syllable_word_start + = pam->e1_syllable_word_end + = pam->e1_content + = pam->e2_syllable_word_start + = pam->e2_syllable_word_end + = pam->e3_e4_word + = pam->e3_e4_state + = pam->e5_e6_content_word + = pam->e5_e6_content + = pam->e7_e8_word + = pam->e7_e8_content + = pam->e7_e8_state + = pam->e9_e11_word + = pam->e9_e11_saw_word + = pam->e9_e11_state + = pam->e10_e12_e13_word + = pam->e10_e12_e13_state + = pam->e10_e12_e13_saw_word + = pam->f2_overall_word + = pam->f2_word_syllable + = pam->f2_next_word_syllable + = pam->f2_current_primary_phrase_word + = pam->g1_current_secondary_phrase_syllable + = pam->g1_current_syllable + = pam->g2_current_secondary_phrase_word + = pam->g2_current_word + = pam->h1_current_secondary_phrase_syll + = pam->h2_current_secondary_phrase_word + = pam->h3_h4_current_secondary_phrase_word + = pam->h5_current_phrase_type + = pam->h5_state + = pam->i1_secondary_phrase_syllable + = pam->i1_next_secondary_phrase_syllable + = pam->i2_secondary_phrase_word + = pam->i2_next_secondary_phrase_word + = 0; + /*Override 0 with 1*/ + pam->b4_b5_syllable = pam->b17_b19_syllable = pam->b18_b20_b21_syllable + = pam->e9_e11_word = pam->e10_e12_e13_word = pam->e7_e8_word + = pam->h2_current_secondary_phrase_word = 1; + /*Override 0 with -1*/ + pam->e1_syllable_word_start = pam->e1_syllable_word_end + = pam->e2_syllable_word_start = pam->e2_syllable_word_end = -1; + + return PICO_OK; +}/*pam_reset_processors_back*/ + +/** + * processes an input event for a specific feature + * @param this : pointer to PAM PU sub object pointer + * @param nFeat : feature column to process + * @param event_type : event id among syll/boundprim/boundsec/boundword + * @param direction : forward(0)/backward(1) + * @return PICO_OK : process OK + * @return PICO_ERR_OTHER : errors on getting pam sub obj pointer + * @callgraph + * @callergraph + */ +static pico_status_t pam_process_event_feature( + register picodata_ProcessingUnit this, picoos_uint8 nFeat, + picoos_uint8 event_type, picoos_uint8 direction) +{ + picoos_uint8 sDest, nI; + picoos_uint16 syllCurr; + pam_subobj_t *pam; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + syllCurr = pam->nCurrSyllable; + switch (nFeat) { + case A3: + /*processor for A3*/ + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] + == 1) || (pam->a3_primary_phrase_syllable >= 1)) { + if (pam->a3_overall_syllable < 1) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] + = 0; + else + pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] + = pam->sSyllFeats[pam->nCurrSyllable + - 1].phoneV[B3]; + } else { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] = 0; + } + pam->a3_primary_phrase_syllable++; + pam->a3_overall_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->a3_primary_phrase_syllable = 0; + } + break; + case PICOPAM_DIR_BACK: + /*do nothing*/ + break; + } + break; + case B1: + case B2: + case B3: + /*done in createSyllable*/ + break; + case B4:/*processor for B4,B5*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = B4; + break; + case PICOPAM_DIR_BACK: + sDest = B5; + break; + default: + sDest = B4; + break; + } + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] == 0) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b4_b5_syllable; + pam->b4_b5_syllable++; + } else { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] = 0; + } + } + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) { + pam->b4_b5_syllable = 1; + } + break; + case B5:/*processor for B5 : done in B4*/ + break; + case B6:/*processor for B6,B7*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = B6; + break; + case PICOPAM_DIR_BACK: + sDest = B7; + break; + default: + sDest = B6; + break; + } + switch (pam->b6_b7_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = PICOPAM_DONT_CARE_VALUE; + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->b6_b7_syllable = 1; + pam->b6_b7_state = 1; + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b6_b7_syllable; + pam->b6_b7_syllable++; + } + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->b6_b7_syllable = 1; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->b6_b7_state = 0; + } + break; + default: + break; + } + break; + case B7:/*Done in B6*/ + break; + case B8:/*processor for B8,B9*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = B8; + break; + case PICOPAM_DIR_BACK: + sDest = B9; + break; + default: + sDest = B8; + break; + } + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b8_b9_stressed_syllable; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 1) + pam->b8_b9_stressed_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->b8_b9_stressed_syllable = 0; + } + + break; + case B9:/*done in B8*/ + break; + case B10:/*processor for B10, B11*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = B10; + break; + case PICOPAM_DIR_BACK: + sDest = B11; + break; + default: + sDest = B10; + break; + } + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b10_b11_accented_syllable; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 1) + pam->b10_b11_accented_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->b10_b11_accented_syllable = 0; + } + break; + case B11:/*done in B10*/ + break; + case B12:/*processor for B12,B13*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = B12; + break; + case PICOPAM_DIR_BACK: + sDest = B13; + break; + default: + sDest = B12; + break; + } + switch (pam->b12_b13_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 0) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = PICOPAM_DONT_CARE_VALUE; + else { + pam->b12_b13_syllable = 0; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = PICOPAM_DONT_CARE_VALUE; + pam->b12_b13_state = 1; + } + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b12_b13_syllable; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 1) + pam->b12_b13_syllable = 0; + else + pam->b12_b13_syllable++; + pam->b12_b13_state = 2; + } + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->b12_b13_state = 0; + break; + case 2: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b12_b13_syllable; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 1) + pam->b12_b13_syllable = 0; + else + pam->b12_b13_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->b12_b13_state = 0; + + break; + default: + break; + } + break; + case B13:/*done in B12*/ + break; + + case B14:/*processor for B14, B15*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = B14; + break; + case PICOPAM_DIR_BACK: + sDest = B15; + break; + default: + sDest = B14; + break; + } + switch (pam->b14_b15_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 0) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = PICOPAM_DONT_CARE_VALUE; + else { + pam->b14_b15_syllable = 0; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = PICOPAM_DONT_CARE_VALUE; + pam->b14_b15_state = 1; + } + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b14_b15_syllable; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 1) + pam->b14_b15_syllable = 0; + else + pam->b14_b15_syllable++; + pam->b14_b15_state = 2; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->b14_b15_state = 0; + } + break; + case 2: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b14_b15_syllable; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 1) + pam->b14_b15_syllable = 0; + else + pam->b14_b15_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->b14_b15_state = 0; + } + break; + default: + break; + } + break; + case B15:/*Processor for B15 : done in B14*/ + break; + case B16:/*done in createSyllable*/ + break; + case B17:/*processor for B17, B19 unified */ + switch (direction) { + case PICOPAM_DIR_FORW: + switch (pam->b17_b19_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17] + = PICOPAM_DONT_CARE_VALUE; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19] + = pam->b17_b19_syllable; + pam->b17_b19_syllable++; + } + if (((event_type == PICOPAM_EVENT_P_BOUND) + || (event_type == PICOPAM_EVENT_S_BOUND)) + && (pam->b17_b19_syllable > 1)) { + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->b17_b19_syllable = 1; + pam->b17_b19_state = 1; + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17] + = pam->b17_b19_syllable; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19] + = PICOPAM_DONT_CARE_VALUE; + pam->b17_b19_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->b17_b19_syllable = 1; + } + break; + default: + break; + } + break; + case PICOPAM_DIR_BACK: + /*do nothing*/ + break; + } + break; + case B18:/*processor for B18, B20, B21 unfied*/ + switch (direction) { + case PICOPAM_DIR_FORW:/*do nothing*/ + break; + case PICOPAM_DIR_BACK: + switch (pam->b18_b20_b21_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B18] + = PICOPAM_DONT_CARE_VALUE; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] + == PICOPAM_DECLARATIVE) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] + = pam->b18_b20_b21_syllable; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] + = PICOPAM_DONT_CARE_VALUE; + } else { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] + = PICOPAM_DONT_CARE_VALUE; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] + = pam->b18_b20_b21_syllable; + } + pam->b18_b20_b21_syllable++; + } + if (((event_type == PICOPAM_EVENT_P_BOUND) + || (event_type == PICOPAM_EVENT_S_BOUND)) + && (pam->b18_b20_b21_syllable > 1)) { + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->b18_b20_b21_syllable = 1; + pam->b18_b20_b21_state = 1; + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B18] + = pam->b18_b20_b21_syllable; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] + = PICOPAM_DONT_CARE_VALUE; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] + = PICOPAM_DONT_CARE_VALUE; + pam->b18_b20_b21_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->b18_b20_b21_syllable = 1; + } + break; + default: + break; + } + break; + } + break; + case B19:/*processor for B19 : done in B17*/ + break; + case B20:/*processor for B20 : done in B18*/ + break; + case B21:/*processor for B21 : done in B18*/ + break; + case C3:/*processor for C3*/ + switch (direction) { + case PICOPAM_DIR_FORW: + /*do nothing*/ + break; + case PICOPAM_DIR_BACK: + if (event_type == PICOPAM_EVENT_SYLL) { + if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] + == 1) || (pam->c3_primary_phrase_syllable >= 1)) { + if (pam->c3_overall_syllable < 1) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] + = 0; + else + pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] + = pam->sSyllFeats[pam->nCurrSyllable + + 1].phoneV[B3]; + } else { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] = 0; + } + pam->c3_primary_phrase_syllable++; + pam->c3_overall_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->c3_primary_phrase_syllable = 0; + } + break; + } + break; + case D2:/*processor for D2*/ + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] + == 1) || (pam->d2_current_primary_phrase_word + >= 1)) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[D2] + = pam->d2_prev_syllable_in_word; + else + pam->sSyllFeats[pam->nCurrSyllable].phoneV[D2] = 0; + + pam->d2_syllable_in_word++; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) { + pam->d2_current_primary_phrase_word = 1; + pam->d2_prev_syllable_in_word + = pam->d2_syllable_in_word; + pam->d2_syllable_in_word = 0; + /*pam->d2_current_primary_phrase_word++;*/ + } + if ((event_type == PICOPAM_EVENT_P_BOUND)) { + pam->d2_current_primary_phrase_word = 0; + } + break; + case PICOPAM_DIR_BACK: + /*do nothing*/ + break; + } + break; + case E1:/*processor for E1*/ + switch (direction) { + case PICOPAM_DIR_FORW: /*remember : content syllable indicator already on P5*/ + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->e1_syllable_word_start == -1) + pam->e1_syllable_word_start + = (picoos_int8) pam->nCurrSyllable; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1) + pam->e1_content = 1; + pam->e1_syllable_word_end + = (picoos_int8) pam->nCurrSyllable; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) { + if ((pam->e1_syllable_word_start != -1) + && (pam->e1_syllable_word_end != -1)) { + for (nI = pam->e1_syllable_word_start; nI + <= pam->e1_syllable_word_end; nI++) + pam->sSyllFeats[nI].phoneV[E1] + = pam->e1_content; + } + pam->e1_content = 0; + pam->e1_syllable_word_start = -1; + pam->e1_syllable_word_end = -1; + } + break; + case PICOPAM_DIR_BACK: + /*do nothing*/ + break; + } + break; + case E2:/*processor for E2*/ + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->e2_syllable_word_start == -1) + pam->e2_syllable_word_start + = (picoos_int8) pam->nCurrSyllable; + pam->e2_syllable_word_end + = (picoos_int8) pam->nCurrSyllable; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) { + if ((pam->e2_syllable_word_start != -1) + && (pam->e2_syllable_word_end != -1)) { + for (nI = pam->e2_syllable_word_start; nI + <= pam->e2_syllable_word_end; nI++) + pam->sSyllFeats[nI].phoneV[E2] + = pam->e2_syllable_word_end + - pam->e2_syllable_word_start + + 1; + } + pam->e1_content = 0; + pam->e2_syllable_word_start = -1; + pam->e2_syllable_word_end = -1; + } + break; + case PICOPAM_DIR_BACK: + break; + } + break; + case E3:/*processor for E3,E4*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = E3; + break; + case PICOPAM_DIR_BACK: + sDest = E4; + break; + default: + sDest = E3; + break; + } + switch (pam->e3_e4_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = PICOPAM_DONT_CARE_VALUE; + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->e3_e4_word = 1; + pam->e3_e4_state = 1; + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->e3_e4_word; + if (event_type == PICOPAM_EVENT_S_BOUND) + pam->e3_e4_word = 1; + if (event_type == PICOPAM_EVENT_W_BOUND) + pam->e3_e4_word++; + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->e3_e4_state = 0; + break; + default: + break; + } + break; + case E4:/*processor for E4 : done in E3*/ + break; + case E5:/*processor for E5,E6*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = E5; + break; + case PICOPAM_DIR_BACK: + sDest = E6; + break; + default: + sDest = E5; + break; + } + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->e5_e6_content_word; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1) + pam->e5_e6_content = 1; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) { + if (pam->e5_e6_content == 1) + pam->e5_e6_content_word++; + pam->e5_e6_content = 0; + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->e5_e6_content_word = 0; + } + break; + case E6:/*processor for E6 : done in E5*/ + break; + case E7:/*processor for E7,E8*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = E7; + break; + case PICOPAM_DIR_BACK: + sDest = E8; + break; + default: + sDest = E7; + break; + } + switch (pam->e7_e8_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = PICOPAM_DONT_CARE_VALUE; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1) + pam->e7_e8_content = 1; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->e7_e8_content = 0; + } + + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND)) { + if (pam->e7_e8_content == 1) { + pam->e7_e8_word = 0; + pam->e7_e8_content = 0; + pam->e7_e8_state = 1; + } + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->e7_e8_word; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1) + pam->e7_e8_content = 1; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND)) { + if (pam->e7_e8_content == 1) { + pam->e7_e8_word = 0; + pam->e7_e8_content = 0; + } else { + pam->e7_e8_word++; + } + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->e7_e8_state = 0; + pam->e7_e8_content = 0; /*<<<<<< added */ + } + + default: + break; + } + break; + case E8:/*processor for E8 : done in E7*/ + break; + case E9: + /*processor for E9, E11*/ + switch (direction) { + case PICOPAM_DIR_FORW: + switch (pam->e9_e11_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9] + = PICOPAM_DONT_CARE_VALUE; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11] + = pam->e9_e11_word; + pam->e9_e11_saw_word = 1; /*new variable, needs to be initialized to 0*/ + } + if (event_type == PICOPAM_EVENT_W_BOUND) + pam->e9_e11_word++; + if (((event_type == PICOPAM_EVENT_P_BOUND) + || (event_type == PICOPAM_EVENT_S_BOUND)) + && (pam->e9_e11_saw_word == 1)) { /* modified*/ + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->e9_e11_word = 1; + else + pam->e9_e11_word++; /*modified*/ + pam->e9_e11_state = 1; + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9] + = pam->e9_e11_word; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11] + = PICOPAM_DONT_CARE_VALUE; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) + || (event_type == PICOPAM_EVENT_S_BOUND)) + pam->e9_e11_word++; + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->e9_e11_word = 1; + break; + default: + break; + } + break; + case PICOPAM_DIR_BACK: + /*do nothing*/ + break; + } + break; + case E10:/*processor for E10, E12, E13 unified*/ + switch (direction) { + case PICOPAM_DIR_FORW:/*do nothing*/ + break; + case PICOPAM_DIR_BACK: + switch (pam->e10_e12_e13_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E10] + = PICOPAM_DONT_CARE_VALUE; + pam->e10_e12_e13_saw_word = 1; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] + == PICOPAM_DECLARATIVE) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] + = pam->e10_e12_e13_word; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] + = PICOPAM_DONT_CARE_VALUE; + } else { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] + = PICOPAM_DONT_CARE_VALUE; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] + = pam->e10_e12_e13_word; + } + } + if (event_type == PICOPAM_EVENT_W_BOUND) + pam->e10_e12_e13_word++; + + /*if (((event_type==PICOPAM_EVENT_P_BOUND)||(event_type==PICOPAM_EVENT_S_BOUND))&&(pam->e10_e12_e13_word>1)) {*/ + if (((event_type == PICOPAM_EVENT_P_BOUND) + || (event_type == PICOPAM_EVENT_S_BOUND)) + && (pam->e10_e12_e13_saw_word > 0)) { + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->e10_e12_e13_word = 1; + else + pam->e10_e12_e13_word++; + pam->e10_e12_e13_state = 1; + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E10] + = pam->e10_e12_e13_word; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] + = PICOPAM_DONT_CARE_VALUE; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] + = PICOPAM_DONT_CARE_VALUE; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) + || (event_type == PICOPAM_EVENT_S_BOUND)) + pam->e10_e12_e13_word++; + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->e10_e12_e13_word = 1; + break; + default: + break; + } + break; + } + break; + + case E11:/*processor for E11 : done in E9*/ + break; + case E12:/*processor for E12 : done in E10*/ + break; + case E13:/*processor for E13 : done in E10*/ + break; + + case F2: + switch (direction) { + case PICOPAM_DIR_FORW:/*do nothing*/ + break; + case PICOPAM_DIR_BACK: + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->f2_current_primary_phrase_word >= 1)/*at least second word in current primary phrase*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2] + = pam->f2_next_word_syllable; + else + /*first word in current primary phrase*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2] = 0; + pam->f2_word_syllable++; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) {/*word - end : switch*/ + pam->f2_next_word_syllable = pam->f2_word_syllable; + pam->f2_word_syllable = 0; + } + if (event_type == PICOPAM_EVENT_P_BOUND)/*mark first word in current primary phrase*/ + pam->f2_current_primary_phrase_word = 0; + else /*mark next word in current primary phrase(enables output in PICOPAM_EVENT_SYLL)*/ + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND)) + pam->f2_current_primary_phrase_word++; + break; + } + break; + case G1: + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->g1_current_secondary_phrase_syllable > 0) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[G1] + = pam->g1_current_secondary_phrase_syllable; + else + pam->sSyllFeats[pam->nCurrSyllable].phoneV[G1] = 0; + pam->g1_current_syllable++; + } + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->g1_current_secondary_phrase_syllable + = pam->g1_current_syllable; + pam->g1_current_syllable = 0; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->g1_current_secondary_phrase_syllable = 0; + pam->g1_current_syllable = 0; + } + case PICOPAM_DIR_BACK: /*do nothing*/ + break; + } + break; + case G2: + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->g2_current_secondary_phrase_word > 0) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[G2] + = pam->g2_current_secondary_phrase_word; + else + pam->sSyllFeats[pam->nCurrSyllable].phoneV[G2] = 0; + } + if (event_type == PICOPAM_EVENT_W_BOUND) + pam->g2_current_word++; + + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->g2_current_secondary_phrase_word + = pam->g2_current_word + 1; + pam->g2_current_word = 0; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->g2_current_secondary_phrase_word = 0; + pam->g2_current_word = 0; + } + break; + case PICOPAM_DIR_BACK: /*do nothing*/ + break; + } + break; + case H1: + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->h1_current_secondary_phrase_syll++; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1] + = pam->h1_current_secondary_phrase_syll; + } + if ((event_type == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) + pam->h1_current_secondary_phrase_syll = 0; + break; + case PICOPAM_DIR_BACK: + if (event_type == PICOPAM_EVENT_SYLL) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1] + = pam->h1_current_secondary_phrase_syll; + if (event_type == PICOPAM_EVENT_S_BOUND) + pam->h1_current_secondary_phrase_syll + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1]; + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->h1_current_secondary_phrase_syll + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H1]; + break; + } + break; + case H2: + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] + = pam->h2_current_secondary_phrase_word; + } + if (event_type == PICOPAM_EVENT_W_BOUND) { + pam->h2_current_secondary_phrase_word++; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] + = pam->h2_current_secondary_phrase_word; + } + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] + = pam->h2_current_secondary_phrase_word + 1; + pam->h2_current_secondary_phrase_word = 0; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + if (pam->nCurrSyllable > 1) + pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2] + = pam->h2_current_secondary_phrase_word + 1; + pam->h2_current_secondary_phrase_word = 0; + } + break; + case PICOPAM_DIR_BACK: + if (event_type == PICOPAM_EVENT_SYLL) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] + = pam->h2_current_secondary_phrase_word; + if (event_type == PICOPAM_EVENT_S_BOUND) + pam->h2_current_secondary_phrase_word + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2]; + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->h2_current_secondary_phrase_word + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2]; + break; + } + break; + case H3:/*processor for H3,H4 unified */ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = H3; + break; + case PICOPAM_DIR_BACK: + sDest = H4; + break; + default: + sDest = H3; + break; + } + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->h3_h4_current_secondary_phrase_word; + } + if ((event_type == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) + pam->h3_h4_current_secondary_phrase_word++; + break; + case H4: /*processor for H4 : already in H3*/ + break; + + case H5:/*processor for H5*/ + switch (direction) { + case PICOPAM_DIR_FORW: + break; + case PICOPAM_DIR_BACK: + switch (pam->h5_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5]; + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->h5_state = 1; + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] + == PICOPAM_P) + && (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] + == 0)) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] + = PICOPAM_p; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->h5_state = 0; + } + break; + default: + break; + } + break; + + default: + break; + } + break; + + case I1:/*processor for I1*/ + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->i1_secondary_phrase_syllable++; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1] + = pam->i1_secondary_phrase_syllable; + } + if ((event_type == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) + pam->i1_secondary_phrase_syllable = 0; + break; + case PICOPAM_DIR_BACK: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1] + = pam->i1_next_secondary_phrase_syllable; + } + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->i1_next_secondary_phrase_syllable + = pam->i1_secondary_phrase_syllable; + pam->i1_secondary_phrase_syllable + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1]; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->i1_next_secondary_phrase_syllable = 0; + pam->i1_secondary_phrase_syllable + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[I1]; + } + break; + } + break; + case I2: /*processor for I2*/ + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2] + = pam->i2_secondary_phrase_word; + } + if (event_type == PICOPAM_EVENT_W_BOUND) + pam->i2_secondary_phrase_word++; + + if ((event_type == PICOPAM_EVENT_P_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND)) + pam->i2_secondary_phrase_word = 1; + + break; + case PICOPAM_DIR_BACK: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2] + = pam->i2_next_secondary_phrase_word; + } + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->i2_next_secondary_phrase_word + = pam->i2_secondary_phrase_word; + pam->i2_secondary_phrase_word + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2]; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->i2_next_secondary_phrase_word = 0; + pam->i2_secondary_phrase_word + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[I2]; + } + break; + } + break; + case J1: /*processor for J1 */ + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] != 1) + pam->j1_utterance_syllable++; + } + break; + case PICOPAM_DIR_BACK: + pam->sSyllFeats[pam->nCurrSyllable].phoneV[J1] + = pam->j1_utterance_syllable; + break; + } + break; + case J2: /*processor for J2*/ + switch (direction) { + case PICOPAM_DIR_FORW: + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) + pam->j2_utterance_word++; + break; + case PICOPAM_DIR_BACK: + pam->sSyllFeats[pam->nCurrSyllable].phoneV[J2] + = pam->j2_utterance_word - 1; + break; + } + break; + case J3: /*processor for J3*/ + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->j3_utterance_sec_phrases++; + break; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->j3_utterance_sec_phrases++; + break; + } + break; + case PICOPAM_DIR_BACK: + pam->sSyllFeats[pam->nCurrSyllable].phoneV[J3] + = pam->j3_utterance_sec_phrases - 1; + break; + } + break; + } + return PICO_OK; +}/*pam_process_event_feature*/ + +/** + * processes an input event spanning it to all column features + * @param this : pointer to PAM PU sub object pointer + * @param event_type : event id among syll/boundprim/boundsec/boundword + * @param direction : forward(0)/backward(1) + * @return PICO_OK : process OK + * @return PICO_ERR_OTHER : errors on getting pam sub obj pointer + * @callgraph + * @callergraph + */ +static pico_status_t pam_process_event(register picodata_ProcessingUnit this, + picoos_uint8 event_type, picoos_uint8 direction) +{ + picoos_uint8 nFeat; + pico_status_t nResult; + + pam_subobj_t *pam; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + + if (direction == PICOPAM_DIR_FORW) { + if (event_type == PICOPAM_EVENT_P_BOUND) + /*primary boundary*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P2] = 1; + if (event_type == PICOPAM_EVENT_S_BOUND) + /*secondary boundary*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P3] = 1; + if (event_type == PICOPAM_EVENT_W_BOUND) + /*word boundary*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P4] = 1; + } + for (nFeat = A3; nFeat <= J3; nFeat++) { + nResult = pam_process_event_feature(this, nFeat, event_type, direction); + if (nResult != PICO_OK) + return nResult; + } + return PICO_OK; +}/*pam_process_event*/ + +/** + * inserts a syllable inside the subobj sentence data struct. + * @param this : pointer to PAM PU sub object pointer + * @param syllType : the syllable type (pause/syllable) + * @param sContent : the item content + * @param sentType : the sentence type + * @param phType : the phrase type + * @param uBoundType : the boundary type (only for silence syllables) + * @param uMinDur, uMaxDur : the mimimum and maximum duration (only for silence syllables) + * @return PICO_OK : syllable creation successful + * @return PICO_ERR_OTHER : errors in one internal function (check_phones_size..) + * @callgraph + * @callergraph + */ +static pico_status_t pam_create_syllable(register picodata_ProcessingUnit this, + picoos_uint8 syllType, picoos_uint8 *sContent, picoos_uint8 sentType, + picoos_uint8 phType, picoos_uint8 uBoundType, picoos_uint16 uMinDur, + picoos_uint16 uMaxDur) +{ + pam_subobj_t *pam; + picoos_uint8 nI; + picoos_uint8 pos; + /* picoos_uint8 *npUi16; */ + picoos_uint32 pos32; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + pos = 0; + /*check buffer full condition on number of syllables*/ + if (check_syllables_size(pam, 1) != PICO_OK) { + return PICO_ERR_OTHER; + } + + if (syllType == PICOPAM_SYLL_PAUSE) { + /*check buffer full condition on number of phonemes*/ + if (check_phones_size(pam, 1) != PICO_OK) { + return PICO_ERR_OTHER; + } + } + if (syllType == PICOPAM_SYLL_SYLL) { + /*check item availability*/ + if (sContent == NULL) { + return PICO_ERR_OTHER; + } + /*check buffer full condition on number of phonemes*/ + if (check_phones_size(pam, sContent[3]) != PICO_OK) { + return PICO_ERR_OTHER; + } + } + + /*open new syllable*/ + pam->nCurrSyllable = pam->nCurrSyllable + 1; + /*cleanup*/ + for (nI = 0; nI < PICOPAM_VECT_SIZE; nI++) { + if (pam->nCurrSyllable > 0) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] = 0; + } else { + if ((nI >= ITM) && (nI <= itm)) { + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] > 0) { + /*do not cleanup "attached item offset" fields (ITM, itm): + an already existing attached item could be lost*/ + } else { + /*cleanup "attached item offset"*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] = 0; + } + } else { + /*cleanup all fields except "attached item offset" (ITM, itm)*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] = 0; + } + } + } + /*set minimum and maximum duration values*/ + if ((uMinDur == 0) && (uMaxDur == 0) && (syllType == PICOPAM_SYLL_PAUSE)) { + /*both 0 : use default duration limits for boundaries*/ + get_default_boundary_limit(uBoundType, &uMinDur, &uMaxDur); + } + if (uMinDur > 0) { + pos32 = Min; + picoos_write_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV, + &pos32, uMinDur); + } + if (uMaxDur > 0) { + pos32 = Max; + picoos_write_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV, + &pos32, uMaxDur); + } + /*END OF BREAK COMMAND SUPPORT*/ + + if (syllType == PICOPAM_SYLL_PAUSE) { + /*initialize a pause syllable*/ + if (sentType == PICOPAM_DECLARATIVE) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] + = PICOPAM_DECLARATIVE; + if (sentType == PICOPAM_INTERROGATIVE) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] + = PICOPAM_INTERROGATIVE; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[bnd] = uBoundType; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] = 1; /*this means the syllable contains a pause-silence*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P8] = 1; + + /*b1,b2,b9,b11,b13,b15,e1,e6,e8,e10 already set to 0*/ + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B4] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B5] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B6] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B7] + = 1; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B16] + = PICOPAM_PH_DONT_CARE_VAL; /*name of the vowel in the syllable = NONE */ + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E2] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E3] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E4] = 1; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] = phType; + + /*Store current phonetic codes in input phonetic string*/ + pam->sPhIds[pam->nCurrPhoneme] = pam_get_pause_id(this); + picoos_mem_copy((void*) &pam->nCurrPhoneme, + &(pam->sSyllFeats[pam->nCurrSyllable].phoneV[FID]), + sizeof(pam->nCurrPhoneme)); + pam->nCurrPhoneme++; + pam->nTotalPhonemes++; + /*add 1 to total number of syllables*/ + pam->nTotalSyllables++; + + return PICO_OK; + } + if (syllType == PICOPAM_SYLL_SYLL) { + /*initialize a real syllable*/ + if (sContent[2] > PICODATA_ACC0) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] = 1; /*set content syllable indicator*/ + if (sentType == PICOPAM_DECLARATIVE) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] + = PICOPAM_DECLARATIVE; + if (sentType == PICOPAM_INTERROGATIVE) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] + = PICOPAM_INTERROGATIVE; + + if ((sContent[2] >= PICODATA_ACC1) && (sContent[2] <= PICODATA_ACC4)) + /*stressed*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] = 1; + + if ((sContent[2] >= PICODATA_ACC1) && (sContent[2] <= PICODATA_ACC2)) + /*accented*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] = 1; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] = sContent[3];/*len*/ + + if (pam->nCurrSyllable > 30) + pam->nCurrSyllable = pam->nCurrSyllable; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B16] = pam_get_vowel_name(this, + sContent, &pos); /*name of the vowel in the syllable*/ + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P8] = pos; /*temp for storing the position of the vowel*/ + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] = phType; + + /*Store current phonetic codes in input phonetic string*/ + picoos_mem_copy((void*) &pam->nCurrPhoneme, + &(pam->sSyllFeats[pam->nCurrSyllable].phoneV[FID]), + sizeof(pam->nCurrPhoneme)); + for (nI = 0; nI < sContent[3]; nI++) + pam->sPhIds[pam->nCurrPhoneme + nI] = sContent[4 + nI]; + pam->nCurrPhoneme += nI; + pam->nTotalPhonemes += nI; + /*add 1 to total number of syllables*/ + pam->nTotalSyllables++; + return PICO_OK; + } + /*if no SyllType has been identified -->> error*/ + return PICO_ERR_OTHER; +}/*pam_create_syllable*/ + +/** + * performs the forward step of the PAM adapter + * @param this : pointer to PAM PU sub object pointer + * @param itemBase : pointer to current item + * @return PICOPAM_READY : forward step ok, the sentence is complete + * @return PICOPAM_MORE : forward step ok, but more data needed to complete the sentence + * @return PICO_ERR_OTHER : errors in one internal function (CreateSyllable..) + * @callgraph + * @callergraph + */ +static pico_status_t pam_adapter_forward_step( + register picodata_ProcessingUnit this, picoos_uint8 *itemBase) +{ + register pam_subobj_t * pam; + pico_status_t sResult; + picoos_uint16 uMinDur, uMaxDur; + picoos_uint32 nPos; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + uMinDur = uMaxDur = 0; /*default 0 : not initialized*/ + switch (itemBase[0]) { + case PICODATA_ITEM_BOUND: + /*received a boundary item*/ + switch (itemBase[1]) { + case PICODATA_ITEMINFO1_BOUND_SBEG: + case PICODATA_ITEMINFO1_BOUND_PHR1: +#ifdef PAM_PHR2_WITH_PR1 + case PICODATA_ITEMINFO1_BOUND_PHR2: +#endif + case PICODATA_ITEMINFO1_BOUND_SEND: + case PICODATA_ITEMINFO1_BOUND_TERM: + if (itemBase[3] == 2 * sizeof(picoos_uint16)) { + /*only when the item len duration is equal to 2 int16 --> get the values*/ + nPos = 4; + picoos_read_mem_pi_uint16(itemBase, &nPos, &uMinDur); + picoos_read_mem_pi_uint16(itemBase, &nPos, &uMaxDur); + } + break; + default: + break; + } + switch (itemBase[1]) { + case PICODATA_ITEMINFO1_BOUND_SBEG: + /* received a sentence init boundary */ + pam_reset_processors(this); /*reset all processor variables*/ + pam->sType + = pam_map_sentence_type(itemBase[1], itemBase[2]); + pam->pType = pam_map_phrase_type(itemBase[1], itemBase[2]); + /*create silence syll and process P_BOUND event*/ + sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, + pam->sType, pam->pType, itemBase[1], uMinDur, + uMaxDur); + if (sResult != PICO_OK) + return sResult; + sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, + PICOPAM_DIR_FORW); + if (sResult != PICO_OK) + return sResult; + return PICOPAM_MORE; + break; + + case PICODATA_ITEMINFO1_BOUND_PHR1: +#ifdef PAM_PHR2_WITH_PR1 + case PICODATA_ITEMINFO1_BOUND_PHR2: +#endif + /*received a primary boundary*/ + pam->sType + = pam_map_sentence_type(itemBase[1], itemBase[2]); + pam->pType = pam_map_phrase_type(itemBase[1], itemBase[2]); + /*create silence syll and process P_BOUND event*/ + sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, + pam->sType, pam->pType, itemBase[1], uMinDur, + uMaxDur); + if (sResult != PICO_OK) + return sResult; + sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, + PICOPAM_DIR_FORW); + if (sResult != PICO_OK) + return sResult; + return PICOPAM_MORE; + break; + +#ifdef PAM_PHR2_WITH_PR3 + case PICODATA_ITEMINFO1_BOUND_PHR2 : +#endif + case PICODATA_ITEMINFO1_BOUND_PHR3: + /*received a secondary boundary*/ + /*process S_BOUND event*/ + sResult = pam_process_event(this, PICOPAM_EVENT_S_BOUND, + PICOPAM_DIR_FORW); + /*determine new sentence and Phrase types for following syllables*/ + pam->sType + = pam_map_sentence_type(itemBase[1], itemBase[2]); + pam->pType = pam_map_phrase_type(itemBase[1], itemBase[2]); + if (sResult != PICO_OK) + return sResult; + return PICOPAM_MORE; + break; + + case PICODATA_ITEMINFO1_BOUND_PHR0: + /*received a word end boundary*/ + /*process W_BOUND event*/ + sResult = pam_process_event(this, PICOPAM_EVENT_W_BOUND, + PICOPAM_DIR_FORW); + if (sResult != PICO_OK) + return sResult; + return PICOPAM_MORE; + break; + + case PICODATA_ITEMINFO1_BOUND_SEND: + /*received a SEND boundary*/ + /*insert a new silence syllable and process P_BOUND event*/ + /*create silence syll and process P_BOUND event*/ + sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, + pam->sType, pam->pType, itemBase[1], uMinDur, + uMaxDur); + if (sResult != PICO_OK) + return sResult; + sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, + PICOPAM_DIR_FORW); + if (sResult != PICO_OK) + return sResult; + return PICOPAM_READY; + break; + + case PICODATA_ITEMINFO1_BOUND_TERM: + /* received a flush boundary*/ + if (pam->nCurrSyllable == -1) { + return PICOPAM_NA; + } + /*insert a new silence syllable and process P_BOUND event*/ + /*create silence syll and process P_BOUND event*/ + sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, + pam->sType, pam->pType, itemBase[1], uMinDur, + uMaxDur); + if (sResult != PICO_OK) + return sResult; + sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, + PICOPAM_DIR_FORW); + if (sResult != PICO_OK) + return sResult; + return PICOPAM_READY; + break; + + default: + /*boundary type not known*/ + return PICOPAM_NA; + break; + }/*end switch (itemBase[1])*/ + break; /*end case PICODATA_ITEM_BOUND*/ + + case PICODATA_ITEM_SYLLPHON: + /*received a syllable item*/ + /* ------------------------------------------------------------------ + following code has to be used if we do expect + SYLL items arrive even without SBEG items starting the sentence. + this may happen after a term has been issued to make room in local storage. + */ + if (pam->nCurrSyllable == -1) { + pam_reset_processors(this); + /*insert an SBEG with sType and pType taken from previous sentence*/ + sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, + pam->sType, pam->pType, PICODATA_ITEMINFO1_BOUND_SBEG, + 0, 0); + if (sResult != PICO_OK) + return sResult; + sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, + PICOPAM_DIR_FORW); + if (sResult != PICO_OK) + return sResult; + } + /* ------------------------------------------------------------------*/ + sResult = pam_create_syllable(this, PICOPAM_SYLL_SYLL, itemBase, + pam->sType, pam->pType, 0, 0, 0); + if (sResult != PICO_OK) + return sResult; + sResult = pam_process_event(this, PICOPAM_EVENT_SYLL, + PICOPAM_DIR_FORW); + if (sResult != PICO_OK) + return sResult; + return PICOPAM_MORE; + break; + + default: + return PICOPAM_NA; + break; + } + return PICO_ERR_OTHER; +}/*pam_adapter_forward_step*/ + +/** + * performs the backward step of the PAM adapter + * @param this : pointer to PAM PU sub object pointer + * @return PICO_OK : backward step complete + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @remarks derived in some parts from the pam forward code + * @callgraph + * @callergraph + */ +static pico_status_t pam_adapter_backward_step( + register picodata_ProcessingUnit this) +{ + register pam_subobj_t * pam; + picoos_uint8 nProcessed; + picoos_uint16 nSyll; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + + /*Resets the processors for the backward step*/ + pam_reset_processors_back(this); + /*Do the backward step*/ + nSyll = pam->nCurrSyllable; + while (pam->nCurrSyllable >= 0) { + nProcessed = 0; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P2] == 1) { + /*primary boundary*/ + pam_process_event(this, PICOPAM_EVENT_P_BOUND, PICOPAM_DIR_BACK); + pam->nCurrSyllable--; + nProcessed = 1; + } + if ((nProcessed == 0) + && (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P3] == 1)) { + /*secondary boundary*/ + pam_process_event(this, PICOPAM_EVENT_S_BOUND, PICOPAM_DIR_BACK); + pam_process_event(this, PICOPAM_EVENT_SYLL, PICOPAM_DIR_BACK); + pam->nCurrSyllable--; + nProcessed = 1; + } + if ((nProcessed == 0) + && (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P4] == 1)) { + /*word boundary*/ + pam_process_event(this, PICOPAM_EVENT_W_BOUND, PICOPAM_DIR_BACK); + pam_process_event(this, PICOPAM_EVENT_SYLL, PICOPAM_DIR_BACK); + pam->nCurrSyllable--; + nProcessed = 1; + } + if (nProcessed == 0) { + /*non boundaried syllable*/ + pam_process_event(this, PICOPAM_EVENT_SYLL, PICOPAM_DIR_BACK); + pam->nCurrSyllable--; + nProcessed = 0; + } + }/*end while (pam->nCurrSyllable>=0)*/ + /*reset syllpointer to original value*/ + pam->nCurrSyllable = nSyll; + /*Perform pause processing*/ + pam_adapter_do_pauses(this); + pam->nCurrSyllable = 0; + pam->nSyllPhoneme = 0; + + return PICO_OK; +}/*pam_adapter_backward_step*/ + +/** + * processes a pause (silence) syllable after backward processing + * @param this : pointer to PAM PU sub object pointer : processes a pause (silence) syllable after backward processing + * @return PICO_OK : backward step complete + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @remarks pam->nCurrSyllable should point to a pause item + * @remarks this function should be called after backward processing + * @remarks this function corresponds to initializing silence phonemes with + * @remarks values derived from previous or following syllables + * @callgraph + * @callergraph + */ +static pico_status_t pam_do_pause(register picodata_ProcessingUnit this) +{ + picoos_uint16 syllCurr; + pam_subobj_t *pam; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + syllCurr = pam->nCurrSyllable; + + /*processor for all features that can be inherited from previous syll (or word/phrase)*/ + if (pam->nCurrSyllable > 0) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B3]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B8] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B8]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B10] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B10]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B12] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B12]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B14] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B14]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B17]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B19]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B20]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B21]; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[D2] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E2]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[G1] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H1]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[G2] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2]; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E5] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E5]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E7] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E7]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E9]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E11]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E12]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E13]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E13]; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H1]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H3] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H3]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H4] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H4]; + + } else { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] + =pam->sSyllFeats[pam->nCurrSyllable].phoneV[B8] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B10] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B12] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B14] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E5] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H3] + = 0; + + /*init values different from 0*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H4] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[J3]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] = PICOPAM_p; + + } + + /*processor for all features that can be inherited from next syll (or word/phrase)*/ + if (pam->nCurrSyllable < pam->nTotalSyllables - 1) { + /*non last syllable*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] + = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[B3]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2] + = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[E2]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1] + = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[H1]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2] + = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[H2]; + } else { + /*last syllable*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2] + = 0; + } + + /*Other fixed values derived from de-facto standard*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B18] = 0; + + return PICO_OK; +}/*pam_do_pause*/ + +/** + * performs the initialization of pause "syllables" + * @param this : pointer to PAM PU sub object pointer : processes a pause (silence) syllable after backward processing + * @return PICO_OK : pause processing successful + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @callgraph + * @callergraph + */ +static pico_status_t pam_adapter_do_pauses(register picodata_ProcessingUnit this) +{ + register pam_subobj_t * pam; + picoos_uint16 nSyll; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + + /*Do the pause processing*/ + nSyll = pam->nCurrSyllable; + while (pam->nCurrSyllable >= 0) { + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P2] == 1) { + /*pause processing*/ + pam_do_pause(this); + } + pam->nCurrSyllable--; + }/*end while (pam->nCurrSyllable>=0)*/ + /*reset syllpointer to original value*/ + pam->nCurrSyllable = nSyll; + return PICOPAM_READY; +}/*pam_adapter_do_pauses*/ + +#ifdef __cplusplus +} +#endif + +/* picopam.c end */ diff --git a/pico/lib/picopam.h b/pico/lib/picopam.h new file mode 100644 index 0000000..18f7730 --- /dev/null +++ b/pico/lib/picopam.h @@ -0,0 +1,79 @@ +/* + * 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 picopam.h + * + * Phonetic to Acoustic Mapping PU - Header file + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +/** + * @addtogroup picopam + + * Phonetic to acoustic mapping module \n + * + * This module is responsible for mapping the phonetic domain features generated from text analysis + * into parametric representations suitable for signal generation. As such it is the interface + * between text analysis and signal generation + * + * Most the processing of PAM is logically splittable as follows + * - building a suitable symbolic feature vector set for the sentence + * - Feeding Decision Trees with the symbolic seqence vector set + * - Colecting the parametric output of the Decision trees into suitable items to be sent to following PU's + * + * To perform the decision tree feeding and output collection the PU uses an internal buffer. This + * buffer is used several times with different meanings. + * - While building the symbolic feature vector set for the sentence this data structure stores syllable relevant data. + * The corresponding phonetic data is stored outside as a single string of phonetic id's for all the sentence. + * - While feeding the decision trees the data structure is used to represent data for phonemes of the syllable + * - Addiotional data strucures are mantained to temporarily store items not pertaining to the PAM processing, for later resynchronization + * + * A quite detailed description of PAM processing is in the Know How section of the repository. + */ + +#ifndef PICOPAM_H_ +#define PICOPAM_H_ + +#include "picodata.h" +#include "picokdt.h" +#include "picokpdf.h" +#include "picoktab.h" +#include "picokdbg.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/*------------------------------------------------------------------ +Service routines +------------------------------------------------------------------*/ +picodata_ProcessingUnit picopam_newPamUnit( + picoos_MemoryManager mm, picoos_Common common, + picodata_CharBuffer cbIn, picodata_CharBuffer cbOut, + picorsrc_Voice voice); + +#ifdef __cplusplus +} +#endif +#endif /*PICOPAM_H_*/ diff --git a/pico/lib/picopltf.h b/pico/lib/picopltf.h new file mode 100644 index 0000000..0cf2659 --- /dev/null +++ b/pico/lib/picopltf.h @@ -0,0 +1,73 @@ +/* + * 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 picopltf.h + * + * Header file (only) to define platform symbols. + * + * Refer to http://predef.sourceforge.net/ for a comprehensive list + * of pre-defined C/C++ compiler macros. + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + */ + +#if !defined(__PICOPLTF_H__) +#define __PICOPLTF_H__ + +#define ENDIANNESS_BIG 1 +#define ENDIANNESS_LITTLE 2 + +/* * platform identifiers ***/ +#define PICO_Windows 1 /* Windows */ +#define PICO_MacOSX 5 /* Macintosh OS X */ +#define PICO_Linux 7 /* Linux */ + +/* * definition of current platform ***/ +#if !defined(PICO_PLATFORM) +#if defined(_WIN32) +#define PICO_PLATFORM PICO_Windows +#elif defined(__APPLE__) && defined(__MACH__) +#define PICO_PLATFORM PICO_MacOSX +#elif defined(linux) || defined(__linux__) || defined(__linux) +#define PICO_PLATFORM PICO_Linux +#else +#error PICO_PLATFORM not defined +#endif +#endif /* !defined(PICO_PLATFORM) */ + + +/* * symbol PICO_PLATFORM_STRING to define platform as string ***/ +#if (PICO_PLATFORM == PICO_Windows) +#define PICO_PLATFORM_STRING "Windows" +#elif (PICO_PLATFORM == PICO_MacOSX) +#define PICO_PLATFORM_STRING "MacOSX" +#elif (PICO_PLATFORM == PICO_Linux) +#define PICO_PLATFORM_STRING "Linux" +#elif (PICO_PLATFORM == PICO_GENERIC) +#define PICO_PLATFORM_STRING "UnknownPlatform" +#endif + +#if (PICO_PLATFORM == PICO_MacOSX) +#define PICO_ENDIANNESS ENDIANNESS_BIG +#else +#define PICO_ENDIANNESS ENDIANNESS_LITTLE +#endif + +#endif /* !defined(__PICOPLTF_H__) */ diff --git a/pico/lib/picopr.c b/pico/lib/picopr.c new file mode 100644 index 0000000..f54734a --- /dev/null +++ b/pico/lib/picopr.c @@ -0,0 +1,3550 @@ +/* + * 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 picopr.c + * + * text preprocessor + * + * 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 "picobase.h" +#include "picodbg.h" +#include "picodata.h" +#include "picokpr.h" +#include "picopr.h" +#include "picoktab.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* *****************************************************************************/ +/* constants */ +/* *****************************************************************************/ + +#define PR_TRACE_MEM FALSE +#define PR_TRACE_MAX_MEM FALSE +#define PR_TRACE_PATHCOST TRUE + +#define PR_WORK_MEM_SIZE 10000 +#define PR_DYN_MEM_SIZE 7000 + +#define PR_ENABLED TRUE + +#define PR_MAX_NR_ITERATIONS 1000; + +#define SPEC_CHAR "\\/" + +#define PICO_ERR_CONTEXT_NOT_FOUND PICO_ERR_OTHER +#define PICO_ERR_MAX_PREPROC_PATH_LEN_REACHED PICO_ERR_OTHER + +#define IN_BUF_SIZE 255 +#define OUT_BUF_SIZE IN_BUF_SIZE + 3 * PICODATA_ITEM_HEADSIZE + 3 + +#define PR_MAX_NR_PREPROC (1 + PICOKNOW_MAX_NUM_UTPP) + +#define PR_MAX_PATH_LEN 130 +#define PR_MAX_DATA_LEN IN_BUF_SIZE +#define PR_MAX_DATA_LEN_Z PR_MAX_DATA_LEN + 1 /* all strings in picopr should use this constant + to ensure zero termination */ +#define PR_COST_INIT 100000 +#define PR_COST 10 +#define PR_EOL '\n' + +/* Bit mask constants for token sets with parameters */ +#define PR_TSE_MASK_OUT (1<pr_DynMem. Dynamic memory has + to be deallocated again with pr_DEALLOCATE. + Working memory is allocated in pr_subobj_t->pr_WorkMem. Working memory is stack + based and may not to be deallocated with pr_DEALLOCATE, but with pr_resetMemState + to a state previously saved with pr_getMemState. +*/ + +static void pr_ALLOCATE (picodata_ProcessingUnit this, pr_MemTypes mType, void * * adr, unsigned int byteSize) + /* allocates 'byteSize' bytes in the memery partition given by 'mType' */ +{ + pr_subobj_t * pr = (pr_subobj_t *) this->subObj; + picoos_int32 incrUsedBytes, prevmaxDynMemSize; + + if (mType == pr_WorkMem) { + if ((pr->workMemTop + byteSize) < PR_WORK_MEM_SIZE) { + (*adr) = (void *)(&(pr->pr_WorkMem[pr->workMemTop])); + byteSize = ((byteSize + PICOOS_ALIGN_SIZE - 1) / PICOOS_ALIGN_SIZE) * PICOOS_ALIGN_SIZE; + pr->workMemTop += byteSize; +#if PR_TRACE_MEM + PICODBG_INFO(("pr_WorkMem: +%u, tot:%i of %i", byteSize, pr->workMemTop, PR_WORK_MEM_SIZE)); +#endif + + if (pr->workMemTop > pr->maxWorkMemTop) { + pr->maxWorkMemTop = pr->workMemTop; +#if PR_TRACE_MAX_MEM + PICODBG_INFO(("new max pr_WorkMem: %i of %i", pr->workMemTop, PR_WORK_MEM_SIZE)); +#endif + } + } + else { + (*adr) = NULL; + PICODBG_ERROR(("pr out of working memory")); + picoos_emRaiseException(this->common->em, PICO_EXC_OUT_OF_MEM, (picoos_char *)"pr out of dynamic memory", (picoos_char *)""); + pr->outOfMemory = TRUE; + } + } + else if (mType == pr_DynMem) { + (*adr) = picoos_allocate(pr->dynMemMM, byteSize); + if ((*adr) != NULL) { + prevmaxDynMemSize = pr->maxDynMemSize; + picoos_getMemUsage(pr->dynMemMM, 1, &pr->dynMemSize, &incrUsedBytes, &pr->maxDynMemSize); +#if PR_TRACE_MEM + PICODBG_INFO(("pr_DynMem : +%i, tot:%i of %i", incrUsedBytes, pr->dynMemSize, PR_DYN_MEM_SIZE)); +#endif + +#if PR_TRACE_MAX_MEM + if (pr->maxDynMemSize > prevmaxDynMemSize) { + PICODBG_INFO(("new max pr_DynMem : %i of %i", pr->maxDynMemSize, PR_DYN_MEM_SIZE)); + } +#endif + } + else { + PICODBG_ERROR(("pr out of dynamic memory")); + picoos_emRaiseException(this->common->em, PICO_EXC_OUT_OF_MEM, (picoos_char *)"pr out of dynamic memory", (picoos_char *)""); + pr->outOfMemory = TRUE; + } + } + else { + (*adr) = NULL; + } +} + + +static void pr_DEALLOCATE (picodata_ProcessingUnit this, pr_MemTypes mType, void * * adr) +{ + pr_subobj_t * pr = (pr_subobj_t *) this->subObj; + picoos_int32 incrUsedBytes; + if (mType == pr_WorkMem) { + PICODBG_INFO(("not possible; use pr_resetMemState instead")); + } + else if (mType == pr_DynMem) { + picoos_deallocate(pr->dynMemMM, &(*adr)); + picoos_getMemUsage(pr->dynMemMM, 1, &pr->dynMemSize, &incrUsedBytes, &pr->maxDynMemSize); +#if PR_TRACE_MEM + PICODBG_INFO(("pr_DynMem : %i, tot:%i of %i: adr: %u", incrUsedBytes, pr->dynMemSize, PR_DYN_MEM_SIZE, *adr)); +#endif + } + else { + (*adr) = NULL; + } +} + + +static void pr_getMemState(picodata_ProcessingUnit this, pr_MemTypes mType, picoos_uint32 *lmemState) +{ + pr_subobj_t * pr = (pr_subobj_t *) this->subObj; + mType = mType; /* avoid warning "var not used in this function"*/ + *lmemState = pr->workMemTop; +} + + +static void pr_resetMemState(picodata_ProcessingUnit this, pr_MemTypes mType, picoos_uint32 lmemState) +{ + pr_subobj_t * pr = (pr_subobj_t *) this->subObj; + +#if PR_TRACE_MEM + PICODBG_INFO(("pr_WorkMem: -%i, tot:%i of %i", pr->workMemTop-lmemState, lmemState, PR_WORK_MEM_SIZE)); +#endif + mType = mType; /* avoid warning "var not used in this function"*/ + pr->workMemTop = lmemState; +} + + +/* *****************************************************************************/ +/* string operations */ + +static picoos_int32 pr_strlen(const picoos_uchar * str) +{ + picoos_int32 i; + + i=0; + while ((i= length) { + return length; + } else { + i = pos + len; + while (i < length) { + str[pos] = str[i]; + i++; + pos++; + } + str[pos] = 0; + return pos; + } +} + + +static picoos_bool pr_strEqual(picoos_uchar * str1, picoos_uchar * str2) +{ + return (picoos_strcmp((picoos_char *)str1, (picoos_char *)str2) == 0); +} + + +static void pr_int_to_string(picoos_int32 n, picoos_uchar * str, picoos_int32 maxstrlen) +{ + picoos_int32 i, len; + picoos_bool negative=FALSE; + + len = 0; + str[0] = 0; + if (n<0) { + negative = TRUE; + n = -n; + len++; + } + i = n; + + while (i>0) { + i = i / 10; + len++; + } + + if (len0) && (len>0)) { + len--; + str[len] = i % 10 + '0'; + i = i / 10; + } + if (negative) { + len--; + str[len] = '-'; + } + } +} +/* *****************************************************************************/ + +static void pr_firstLetterToLowerCase (const picoos_uchar src[], picoos_uchar dest[]) +{ + + picoos_int32 i; + picoos_int32 j; + picoos_int32 l; + picoos_bool done; + + i = 0; + j = 0; + l = picobase_det_utf8_length(src[0]); + while ((i < l) && (j < PR_MAX_DATA_LEN)) { + dest[j] = src[i]; + i++; + j++; + } + if (j < PR_MAX_DATA_LEN) { + dest[j] = 0; + } + picobase_lowercase_utf8_str(dest, (picoos_char*)dest, PR_MAX_DATA_LEN, &done); + j = picobase_det_utf8_length(dest[0]); + l = pr_strlen(src); + while ((i < l) && (j < PR_MAX_DATA_LEN)) { + dest[j] = src[i]; + i++; + j++; + } + dest[j] = 0; +} + + +static picoos_int32 tok_tokenDigitStrToInt (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_uchar stokenStr[]) +{ + picoos_uint32 i; + picoos_uint32 l; + picoos_int32 id; + picoos_int32 val; + picoos_uint32 n; + picobase_utf8char utf8char; + + val = 0; + i = 0; + l = pr_strlen(stokenStr); + while (i < l) { + picobase_get_next_utf8char(stokenStr, PR_MAX_DATA_LEN, & i, utf8char); + id = picoktab_graphOffset(pr->graphs, utf8char); + if (id > 0) { + if (picoktab_getIntPropValue(pr->graphs, id, &n)) { + val = (10 * val) + n; + } else { + val = ((10 * val) + (int)((int)utf8char[0] - (int)'0')); + } + } else if ((utf8char[0] >= '0') && (utf8char[0] <= '9')) { + val = 10 * val + ((int)utf8char[0] - (int)'0'); + } + } + return val; +} + + +static picoos_bool pr_isLatinNumber (picoos_uchar str[], picoos_int32 * val) +{ + + picoos_uint32 li; + picoos_uint32 llen; + picoos_uchar lact; + picoos_uchar lnext; + picoos_uchar lprev; + picoos_uchar llatinI; + picoos_uchar llatinV; + picoos_uchar llatinX; + picoos_uchar llatinL; + picoos_uchar llatinC; + picoos_uchar llatinD; + picoos_uchar llatinM; + picoos_int32 lseq; + picobase_utf8char utf8; + + *val = 0; + llen = picobase_utf8_length(str, PR_MAX_DATA_LEN); + if (llen > 0) { + li = 0; + picobase_get_next_utf8char(str, PR_MAX_DATA_LEN, & li,utf8); + if (picobase_is_utf8_uppercase(utf8, PICOBASE_UTF8_MAXLEN)) { + llatinI = 'I'; + llatinV = 'V'; + llatinX = 'X'; + llatinL = 'L'; + llatinC = 'C'; + llatinD = 'D'; + llatinM = 'M'; + } else { + llatinI = 'i'; + llatinV = 'v'; + llatinX = 'x'; + llatinL = 'l'; + llatinC = 'c'; + llatinD = 'd'; + llatinM = 'm'; + } + lseq = 1000; + li = 0; + while (li < llen) { + if (li > 0) { + lprev = str[li - 1]; + } else { + lprev = 0; + } + lact = str[li]; + if (li < (llen - 1)) { + lnext = str[li + 1]; + } else { + lnext = 0; + } + if ((lseq > 1) && (lact == llatinI)) { + if ((lprev != lact) && (lseq >= 4)) { + if (lnext == llatinV) { + *val = *val + 4; + li++; + lseq = 1; + } else if (lnext == llatinX) { + *val = *val + 9; + li++; + lseq = 1; + } else { + *val = *val + 1; + lseq = 3; + } + } else { + *val = *val + 1; + lseq = lseq - 1; + } + } else if ((lseq > 5) && (lact == llatinV)) { + *val = *val + 5; + lseq = 5; + } else if ((lseq > 10) && (lact == llatinX)) { + if ((lprev != lact) && (lseq >= 40)) { + if (lnext == llatinL) { + *val = *val + 40; + li++; + lseq = 10; + } else if (lnext == llatinC) { + *val = *val + 90; + li++; + lseq = 10; + } else { + *val = *val + 10; + lseq = 30; + } + } else { + *val = *val + 10; + lseq = lseq - 10; + } + } else if ((lseq > 50) && (lact == llatinL)) { + *val = *val + 50; + lseq = 50; + } else if ((lseq > 100) && (lact == llatinC)) { + if ((lprev != lact) && (lseq >= 400)) { + if (lnext == llatinD) { + *val = *val + 400; + li++; + lseq = 100; + } else if (lnext == llatinM) { + *val = *val + 900; + li++; + lseq = 100; + } else { + *val = *val + 100; + lseq = 300; + } + } else { + *val = *val + 100; + lseq = lseq - 100; + } + } else if ((lseq > 500) && (lact == llatinD)) { + *val = *val + 500; + lseq = 500; + } else if ((lseq >= 1000) && (lact == llatinM)) { + *val = *val + 1000; + } else { + return FALSE; + } + li++; + } + } + return TRUE; +} + + +static picoos_bool pr_isSUC (picoos_uchar str[]) +{ + + picoos_int32 li; + picoos_bool lis; + picobase_utf8char lutf; + picoos_int32 lj; + picoos_int32 ll; + picoos_bool luc; + + li = 0; + lis = TRUE; + luc = TRUE; + while (lis && (li < PR_MAX_DATA_LEN) && (str[li] != 0)) { + lj = 0; + ll = picobase_det_utf8_length(str[li]); + while (lj < ll) { + lutf[lj] = str[li]; + lj++; + li++; + } + lutf[lj] = 0; + if (luc) { + lis = lis && picobase_is_utf8_uppercase(lutf,PICOBASE_UTF8_MAXLEN+1); + } else { + lis = lis && picobase_is_utf8_lowercase(lutf,PICOBASE_UTF8_MAXLEN+1); + } + luc = FALSE; + } + return lis; +} + +/* *****************************************************************************/ + +static picoos_bool pr_isCmdType (pr_ioItemPtr it, picoos_uint8 type) +{ + if ((it != NULL) && (it->head.type == PICODATA_ITEM_CMD) && (it->head.info1 == type)) { + return TRUE; + } else { + return FALSE; + } +} + + +static picoos_bool pr_isCmdInfo2 (pr_ioItemPtr it, picoos_uint8 info2) +{ + if ((it != NULL) && (it->head.type == PICODATA_ITEM_CMD) && (it->head.info2 == info2)) { + return TRUE; + } else { + return FALSE; + } +} + + +static void pr_initPathEle (struct pr_PathEle * ele) +{ + ele->rnetwork = NULL; + ele->rtok = 0; + ele->ritemid = -1; + ele->rdepth = 1; + ele->rlState = PR_LSInit; + ele->rcompare = -1; + ele->rprodname = 0; + ele->rprodprefcost = 0; +} + +/* *****************************************************************************/ + +static void pr_disposeProdList (register picodata_ProcessingUnit this, pr_ProdList * prodList) +{ + pr_ProdList p; + + while ((*prodList) != NULL) { + p = (*prodList); + (*prodList) = (*prodList)->rNext; + picoos_deallocate(this->common->mm, (void *) &p); + } +} + + +static pico_Status pr_addContext (register picodata_ProcessingUnit this, pr_subobj_t * pr, pr_ContextList * ctxList, picokpr_VarStrPtr contextNamePtr, picokpr_VarStrPtr netNamePtr, picokpr_VarStrPtr prodNamePtr) +{ + picokpr_Preproc net; + pr_ContextList ctx; + pr_ProdList prod; + int i; + picokpr_VarStrPtr strp; + picoos_int32 lprodarrlen; + + ctx = (*ctxList); + while ((ctx != NULL) && !(pr_strEqual(contextNamePtr, ctx->rContextName))) { + ctx = ctx->rNext; + } + if (ctx == NULL) { + ctx = picoos_allocate(this->common->mm, sizeof(pr_Context)); + if (ctx == NULL) { + return PICO_EXC_OUT_OF_MEM; + } + ctx->rNext = (*ctxList); + ctx->rProdList = NULL; + ctx->rContextName = contextNamePtr; + (*ctxList) = ctx; + } + i = 0; + net = pr->preproc[i]; + while ((ipreproc[i]; + } + if (net != NULL) { + i = 0; + strp = picokpr_getVarStrPtr(net, picokpr_getProdNameOfs(net, i)); + lprodarrlen = picokpr_getProdArrLen(net); + while ((i < lprodarrlen) && !(pr_strEqual(prodNamePtr, strp))) { + i++; + if (i < lprodarrlen) { + strp = picokpr_getVarStrPtr(net, picokpr_getProdNameOfs(net, i)); + } + } + if (i < lprodarrlen) { + prod = picoos_allocate(this->common->mm, sizeof(pr_Prod)); + if (prod == NULL) { + return PICO_EXC_OUT_OF_MEM; + } + prod->rNetwork = net; + prod->rProdOfs = i; + prod->rNext = ctx->rProdList; + ctx->rProdList = prod; + } + } + return PICO_OK; +} + + +static pico_Status pr_createContextList (register picodata_ProcessingUnit this) +{ + pr_subobj_t * pr = (pr_subobj_t *) this->subObj; + picokpr_VarStrPtr ctxNamePtr; + picokpr_VarStrPtr netNamePtr; + picokpr_VarStrPtr prodNamePtr; + picoos_int32 p, i, n; + pico_Status status; + + pr->ctxList = NULL; + for (p=0; ppreproc[p] != NULL) { + n = picokpr_getCtxArrLen(pr->preproc[p]); + for (i = 1; ipreproc[p], picokpr_getCtxCtxNameOfs(pr->preproc[p], i)); + netNamePtr = picokpr_getVarStrPtr(pr->preproc[p], picokpr_getCtxNetNameOfs(pr->preproc[p], i)); + prodNamePtr = picokpr_getVarStrPtr(pr->preproc[p], picokpr_getCtxProdNameOfs(pr->preproc[p], i)); + status = pr_addContext(this, pr, &pr->ctxList, ctxNamePtr,netNamePtr, prodNamePtr); + if (status != PICO_OK) { + return status; + } + } + } + } + return PICO_OK; +} + + +static void pr_disposeContextList (register picodata_ProcessingUnit this) +{ + pr_subobj_t * pr = (pr_subobj_t *) this->subObj; + pr_ContextList c; + + while (pr->ctxList != NULL) { + c = pr->ctxList; + pr->ctxList = pr->ctxList->rNext; + pr_disposeProdList(this, & c->rProdList); + picoos_deallocate(this->common->mm, (void *) &c); + } +} + + +static pr_ContextList pr_findContext (pr_ContextList contextList, picoos_uchar contextName[]) +{ + pr_ContextList context; + + context = contextList; + while ((context != NULL) && !(pr_strEqual(context->rContextName,contextName))) { + context = context->rNext; + } + return context; +} + + +static void pr_setContext (register picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_uchar context[]) +{ + + pr_ContextList ctx; + + ctx = pr_findContext(pr->ctxList,context); + if (ctx != NULL) { + pr->actCtx = ctx; + pr->actCtxChanged = TRUE; + } else { + PICODBG_WARN(("context '%s' not found; no change",context)); + picoos_emRaiseWarning(this->common->em, PICO_ERR_CONTEXT_NOT_FOUND, (picoos_char*)"context '%s' not found; no change",(picoos_char*)context); + } +} + +/* *****************************************************************************/ +/* item handling routines */ + + +static picoos_uint32 pr_copyData(picoos_uint8 * dest, const picoos_uint8 * src, picoos_int32 nrBytes, picoos_bool zeroTerm) +{ + picoos_int32 i=0; + + if ((src != NULL) && (dest != NULL)) { + i = 0; + while ((inext = NULL; + item->val = 0; + item->head.len = 0; + item->strci = NULL; + item->strcis = NULL; + item->suc = FALSE; + item->alc = FALSE; + item->auc = FALSE; +} + + +static void pr_newItem (picodata_ProcessingUnit this, pr_MemTypes mType, pr_ioItemPtr * item, picoos_uint8 itemType, picoos_int32 size, picoos_bool inItem) +{ + pr_subobj_t * pr = (pr_subobj_t *) this->subObj; + + if (mType == pr_WorkMem) { + pr_ALLOCATE(this, mType, (void * *) & (*item),PR_IOITEM_MIN_SIZE+size+1); + if (pr->outOfMemory) return; + pr_initItem(this, *item); + } + else if ((mType == pr_DynMem) && inItem) { + pr_ALLOCATE(this, mType, (void * *) & (*item), PR_IOITEM_MIN_SIZE+3*size+3); + if (pr->outOfMemory) return; + pr_initItem(this, *item); + if (itemType == PICODATA_ITEM_TOKEN) { + (*item)->strci = &((*item)->data[size+1]); + (*item)->strcis = &((*item)->data[2*size+2]); + (*item)->strci[0] = 0; + (*item)->strcis[0] = 0; + } + } + else if ((mType == pr_DynMem) && !inItem) { + pr_ALLOCATE(this, mType, (void * *) & (*item), PR_IOITEM_MIN_SIZE+size+1); + if (pr->outOfMemory) return; + pr_initItem(this, *item); + } + + (*item)->data[0] = 0; +} + + +static void pr_copyItemContent (picodata_ProcessingUnit this, pr_ioItem * inItem, pr_ioItem * outItem) +{ + if (outItem != NULL) { + outItem->next = inItem->next; + outItem->val = inItem->val; + outItem->head = inItem->head; + outItem->suc = inItem->suc; + outItem->alc = inItem->alc; + outItem->auc = inItem->auc; + if (inItem->head.len > 0 ) { + pr_copyData(outItem->data, inItem->data, inItem->head.len, /*zeroTerm*/TRUE); + pr_copyData(outItem->strci, inItem->strci, inItem->head.len, /*zeroTerm*/TRUE); + pr_copyData(outItem->strcis, inItem->strcis, inItem->head.len, /*zeroTerm*/TRUE); + } + } +} + + +static void pr_copyItem (picodata_ProcessingUnit this, pr_MemTypes mType, pr_ioItemPtr inItem, pr_ioItemPtr * outItem) +{ + pr_subobj_t * pr = (pr_subobj_t *) this->subObj; + + if (inItem != NULL) { + pr_newItem(this, mType,& (*outItem), inItem->head.type, inItem->head.len, FALSE); + if (pr->outOfMemory) return; + pr_copyItemContent(this, inItem, *outItem); + } + else { + outItem = NULL; + } +} + + +static void pr_startItemList (pr_ioItemPtr * firstItem, pr_ioItemPtr * lastItem) +{ + *firstItem = NULL; + *lastItem = NULL; +} + + +static void pr_appendItem (picodata_ProcessingUnit this, pr_ioItemPtr * firstItem, pr_ioItemPtr * lastItem, pr_ioItemPtr item) +{ + if (item != NULL) { + item->next = NULL; + if ((*lastItem) == NULL) { + *firstItem = item; + } else { + (*lastItem)->next = item; + } + (*lastItem) = item; + } +} + + +static void pr_disposeItem (picodata_ProcessingUnit this, pr_ioItemPtr * item) +{ + if ((*item) != NULL) { + pr_DEALLOCATE(this, pr_DynMem, (void * *) & (*item)); + } +} + + +static void pr_putItem (picodata_ProcessingUnit this, pr_subobj_t * pr, + pr_ioItemPtr * first, pr_ioItemPtr * last, + picoos_uint8 itemType, picoos_uint8 info1, picoos_uint8 info2, + picoos_uint16 val, + picoos_uchar str[]) +{ + picoos_int32 i; + pr_ioItemPtr item; + + pr->tmpItem.next = NULL; + pr->tmpItem.val = 0; + pr->tmpItem.head.type = itemType; + pr->tmpItem.head.info1 = info1; + pr->tmpItem.head.info2 = info2; + + pr_initItem(this, &pr->tmpItem); + switch (itemType) { + case PICODATA_ITEM_CMD: + switch (info1) { + case PICODATA_ITEMINFO1_CMD_CONTEXT: + case PICODATA_ITEMINFO1_CMD_VOICE: + case PICODATA_ITEMINFO1_CMD_MARKER: + case PICODATA_ITEMINFO1_CMD_PLAY: + case PICODATA_ITEMINFO1_CMD_SAVE: + case PICODATA_ITEMINFO1_CMD_UNSAVE: + case PICODATA_ITEMINFO1_CMD_PROSDOMAIN: + pr->tmpItem.head.len = picoos_strlen((picoos_char*)str); + for (i=0; itmpItem.head.len; i++) { + pr->tmpItem.data[i] = str[i]; + } + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, & item); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),item); + break; + case PICODATA_ITEMINFO1_CMD_IGNSIG: + case PICODATA_ITEMINFO1_CMD_IGNORE: + case PICODATA_ITEMINFO1_CMD_FLUSH: + pr->tmpItem.head.len = 0; + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, & item); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),item); + break; + case PICODATA_ITEMINFO1_CMD_SPEED: + case PICODATA_ITEMINFO1_CMD_PITCH: + case PICODATA_ITEMINFO1_CMD_VOLUME: + case PICODATA_ITEMINFO1_CMD_SPELL: + case PICODATA_ITEMINFO1_CMD_SIL: + pr->tmpItem.head.len = 2; + pr->tmpItem.data[0] = val % 256; + pr->tmpItem.data[1] = val / 256; + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, & item); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),item); + break; + case PICODATA_ITEMINFO1_CMD_PHONEME: + PICODBG_WARN(("phoneme command not yet implemented")); + break; + default: + PICODBG_WARN(("pr_putItem: unknown command type")); + } + break; + case PICODATA_ITEM_TOKEN: + pr->tmpItem.head.len = picoos_strlen((picoos_char*)str); + for (i=0; itmpItem.head.len; i++) { + pr->tmpItem.data[i] = str[i]; + } + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, & item); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),item); + break; + default: + PICODBG_WARN(("pr_putItem: unknown item type")); + } +} + + +static void pr_appendItemToOutItemList (picodata_ProcessingUnit this, pr_subobj_t * pr, + pr_ioItemPtr * firstItem, pr_ioItemPtr * lastItem, pr_ioItemPtr item) +{ + pr_ioItemPtr litem; + picoos_int32 li; + picoos_int32 li2; + picoos_int32 lid; + picoos_int32 ln; + picoos_int32 ln2; + picoos_uint8 ltype; + picoos_int8 lsubtype; + picoos_uchar lstr[10]; + picoos_bool ldone; + + item->next = NULL; + if (((pr->spellMode != 0) && (item->head.type == PICODATA_ITEM_TOKEN) && (item->head.info1 != PICODATA_ITEMINFO1_TOKTYPE_SPACE))) { + li = 0; + ln = pr_strlen(item->data); + while (li < ln) { + ln2 = picobase_det_utf8_length(item->data[li]); + for (li2 = 0; li2data[li]; + li++; + } + lstr[ln2] = 0; + lid = picoktab_graphOffset(pr->graphs, lstr); + if ((lid > 0) && picoktab_getIntPropTokenType(pr->graphs, lid, <ype) && + ((ltype == PICODATA_ITEMINFO1_TOKTYPE_LETTERV) /*|| (ltype == PICODATA_ITEMINFO1_TOKTYPE_DIGIT)*/)) { + ln2 = pr_strcat(lstr,(picoos_uchar*)SPEC_CHAR); + picoktab_getIntPropTokenSubType(pr->graphs,lid, &lsubtype); + } + else { + ltype = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; + lsubtype = -(1); + } + pr_newItem(this, pr_DynMem,& litem, PICODATA_ITEM_TOKEN, ln2, /*inItem*/FALSE); + if (pr->outOfMemory) return; + litem->head.type = PICODATA_ITEM_TOKEN; + litem->head.info1 = item->head.info1; + litem->head.info2 = item->head.info2; + pr_strcpy(litem->data, lstr); + litem->data[ln2] = 0; + litem->head.len = ln2; + if (litem->head.info1 == PICODATA_ITEMINFO1_TOKTYPE_DIGIT) { + litem->val = tok_tokenDigitStrToInt(this, pr, litem->data); + } else { + litem->val = 0; + } + picobase_lowercase_utf8_str(litem->data,litem->strci,PR_MAX_DATA_LEN, &ldone); + pr_firstLetterToLowerCase(litem->data,litem->strcis); + litem->alc = picobase_is_utf8_lowercase(litem->data,PR_MAX_DATA_LEN); + litem->auc = picobase_is_utf8_uppercase(litem->data,PR_MAX_DATA_LEN); + litem->suc = pr_isSUC(litem->data); + + pr_appendItem(this, firstItem, lastItem, litem); + if (pr->spellMode == PR_SPELL_WITH_SENTENCE_BREAK) { + pr_newItem(this, pr_DynMem,& litem, PICODATA_ITEM_TOKEN, 2, /*inItem*/FALSE); + if (pr->outOfMemory) return; + litem->head.type = PICODATA_ITEM_TOKEN; + litem->head.info1 = PICODATA_ITEMINFO1_TOKTYPE_CHAR; + litem->head.info2 = -1; + litem->head.len = 1; + litem->data[0] = ','; + litem->data[1] = 0; + litem->strci[0] = ','; + litem->strci[1] = 0; + litem->strcis[0] = ','; + litem->strcis[1] = 0; + litem->val = 0; + pr_appendItem(this, firstItem, lastItem, litem); + } else if (pr->spellMode == PR_SPELL_WITH_SENTENCE_BREAK) { + pr_newItem(this, pr_DynMem,& litem, PICODATA_ITEM_CMD, 0, /*inItem*/FALSE); + if (pr->outOfMemory) return; + litem->head.type = PICODATA_ITEM_CMD; + litem->head.info1 = PICODATA_ITEMINFO1_CMD_FLUSH; + litem->head.info2 = PICODATA_ITEMINFO2_NA; + litem->head.len = 0; + pr_appendItem(this, firstItem, lastItem,litem); + } else if (pr->spellMode > 0) { + pr_newItem(this, pr_DynMem,& litem, PICODATA_ITEM_CMD, 2, /*inItem*/FALSE); + if (pr->outOfMemory) return; + litem->head.type = PICODATA_ITEM_CMD; + litem->head.info1 = PICODATA_ITEMINFO1_CMD_SIL; + litem->head.info2 = PICODATA_ITEMINFO2_NA; + litem->head.len = 2; + litem->data[0] = pr->spellMode % 256; + litem->data[1] = pr->spellMode / 256; + pr_appendItem(this, firstItem, lastItem, litem); + } + } + pr_disposeItem(this, & item); + } else if (pr_isCmdType(item, PICODATA_ITEMINFO1_CMD_SPELL) && pr_isCmdInfo2(item, PICODATA_ITEMINFO2_CMD_START)) { + pr->spellMode = item->data[0]+256*item->data[1]; + pr_disposeItem(this, & item); + } else if (pr_isCmdType(item, PICODATA_ITEMINFO1_CMD_SPELL) && pr_isCmdInfo2(item, PICODATA_ITEMINFO2_CMD_END)) { + pr->spellMode = 0; + pr_disposeItem(this, & item); + } else { + pr_appendItem(this, firstItem,lastItem,item); + } +} + + +/* *****************************************************************************/ + +static pr_OutItemVarPtr pr_findVariable (pr_OutItemVarPtr vars, picoos_int32 id) +{ + while ((vars != NULL) && (vars->id != id)) { + vars = vars->next; + } + if ((vars != NULL)) { + return vars; + } else { + return NULL; + } +} + + +static void pr_genCommands (picodata_ProcessingUnit this, pr_subobj_t * pr, + picokpr_Preproc network, picokpr_OutItemArrOffset outitem, pr_OutItemVarPtr vars, pr_ioItemPtr * first, pr_ioItemPtr * last) +{ + + pr_ioItemPtr litem; + pr_OutItemVarPtr lvar; + picoos_uint8 lcmd; + picoos_uint8 linfo2; + picoos_bool ldone; +#if 0 + picoos_int32 lphontype; +#endif + picokpr_VarStrPtr lstrp; + picoos_int32 lnum; + pr_ioItemPtr lf; + pr_ioItemPtr ll; + picoos_int32 lf0beg; + picoos_int32 lf0end; + ShortStrParam lxfadebeg; + ShortStrParam lxfadeend; + picoos_bool lout; + picoos_int32 ltype; + picoos_int32 argOfs; + picoos_int32 nextOfs; + picoos_int32 nextOfs2; + picoos_int32 nextOfs3; + picoos_int32 nextOfs4; + picoos_uchar alphabet[32]; + + lcmd = 0; + lnum = 0; + litem = NULL; + ltype = picokpr_getOutItemType(network, outitem); + switch (ltype) { + case PR_OIgnore: + if (picokpr_getOutItemVal(network, outitem) == 0) { + pr_putItem(this, pr, & (*first),& (*last),PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_IGNORE,PICODATA_ITEMINFO2_CMD_START,0,(picoos_uchar*)""); + } else { + pr_putItem(this, pr, & (*first),& (*last),PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_IGNORE,PICODATA_ITEMINFO2_CMD_END,0,(picoos_uchar*)""); + } + break; + case PR_OPitch: case PR_OSpeed: case PR_OVolume: + switch (ltype) { + case PR_OPitch: + lcmd = PICODATA_ITEMINFO1_CMD_PITCH; + lnum = PICO_PITCH_DEFAULT; + break; + case PR_OSpeed: + lcmd = PICODATA_ITEMINFO1_CMD_SPEED; + lnum = PICO_SPEED_DEFAULT; + break; + case PR_OVolume: + lcmd = PICODATA_ITEMINFO1_CMD_VOLUME; + lnum = PICO_VOLUME_DEFAULT; + break; + default: + break; + } + if ((picokpr_getOutItemArgOfs(network, outitem) != 0)) { + switch (picokpr_getOutItemType(network, picokpr_getOutItemArgOfs(network, outitem))) { + case PR_OVal: + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, lcmd,PICODATA_ITEMINFO2_CMD_ABSOLUTE, picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, outitem)),(picoos_uchar*)""); + break; + case PR_OVar: + lvar = pr_findVariable(vars,picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, outitem))); + if ((lvar != NULL) && (lvar->first != NULL) && (lvar->first->head.type == PICODATA_ITEM_TOKEN)) { + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,PICODATA_ITEMINFO2_CMD_ABSOLUTE,picoos_atoi((picoos_char*)lvar->first->data),(picoos_uchar*)""); + } + break; + default: + pr_startItemList(& lf,& ll); + pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, outitem),vars,& lf,& ll); + if (pr->outOfMemory) return; + if (((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN))) { + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,PICODATA_ITEMINFO2_CMD_ABSOLUTE,picoos_atoi((picoos_char*)lf->data),(picoos_uchar*)""); + } + break; + } + } else { + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,PICODATA_ITEMINFO2_CMD_ABSOLUTE,lnum,(picoos_uchar*)""); + } + break; + + case PR_OPhonSVOXPA: case PR_OPhonSAMPA: + if (picokpr_getOutItemArgOfs(network, outitem) != 0) { + if (ltype == PR_OPhonSVOXPA) { + picoos_strlcpy(alphabet, PICODATA_SVOXPA, sizeof(alphabet)); + } + else { + picoos_strlcpy(alphabet, PICODATA_SAMPA, sizeof(alphabet)); + } + pr_startItemList(& lf,& ll); + pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, outitem),vars,& lf,& ll); + if (pr->outOfMemory) return; + if (lf != NULL) { + ldone = FALSE; + if (lf->head.type == PICODATA_ITEM_TOKEN) { + if (picodata_mapPAStrToPAIds(pr->transducer, this->common, pr->xsampa_parser, pr->svoxpa_parser, pr->xsampa2svoxpa_mapper, lf->data, alphabet, pr->tmpStr1, sizeof(pr->tmpStr1)-1) == PICO_OK) { + pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PHONEME, + PICODATA_ITEMINFO2_CMD_START, 0, pr->tmpStr1); + ldone = TRUE; + } + else { + PICODBG_WARN(("cannot map phonetic string '%s'; synthesizeing text instead", lf->data)); + picoos_emRaiseWarning(this->common->em, PICO_ERR_OTHER,(picoos_char*)"", (picoos_char*)"cannot map phonetic string '%s'; synthesizing text instead", lf->data); + } + } + if (ldone) { + lf = lf->next; + while (lf != NULL) { + if (lf->head.type == PICODATA_ITEM_TOKEN) { + pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_TOKEN, PICODATA_ITEMINFO1_CMD_PHONEME, + PICODATA_ITEMINFO2_CMD_END, 0, (picoos_char *)""); + } + lf = lf->next; + } + pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PHONEME, + PICODATA_ITEMINFO2_CMD_END, 0, (picoos_char *)""); + } + } + } + break; + + case PR_OSent: + pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); + break; + case PR_OPara: + pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); + if (picokpr_getOutItemVal(network, outitem) == 1) { + pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SIL, PICODATA_ITEMINFO2_NA, PICO_PARAGRAPH_PAUSE_DUR, (picoos_uchar*)""); + } + break; + case PR_OBreak: + if ((picokpr_getOutItemArgOfs(network, outitem) != 0)) { + switch (picokpr_getOutItemType(network, picokpr_getOutItemArgOfs(network, outitem))) { + case PR_OVal: + pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SIL, PICODATA_ITEMINFO2_NA, picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, outitem)), (picoos_uchar*)""); + break; + case PR_OVar: + lvar = pr_findVariable(vars,picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, outitem))); + if ((lvar != NULL) && (lvar->first != NULL) && (lvar->first->head.type == PICODATA_ITEM_TOKEN)) { + pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SIL, PICODATA_ITEMINFO2_NA, picoos_atoi((picoos_char*)lvar->first->data), (picoos_uchar*)""); + } + break; + default: + pr_startItemList(& lf,& ll); + pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, outitem),vars,& lf,& ll); + if (pr->outOfMemory) return; + if (((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN))) { + pr_putItem(this, pr, & (*first),& (*last), PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SIL, PICODATA_ITEMINFO2_NA, picoos_atoi((picoos_char*)lf->data), (picoos_uchar*)""); + } + break; + } + } + break; + case PR_OVoice: case PR_OContext: case PR_OMark: + if (picokpr_getOutItemType(network, outitem) == PR_OVoice) { + lcmd = PICODATA_ITEMINFO1_CMD_VOICE; + pr->tmpStr1[0] = 0; + lnum = 1; + } else if (picokpr_getOutItemType(network, outitem) == PR_OContext) { + lcmd = PICODATA_ITEMINFO1_CMD_CONTEXT; + pr_strcpy(pr->tmpStr1, (picoos_uchar*)PICO_CONTEXT_DEFAULT); + lnum = 1; + } else if ((picokpr_getOutItemType(network, outitem) == PR_OMark)) { + lcmd = PICODATA_ITEMINFO1_CMD_MARKER; + pr->tmpStr1[0] = 0; + lnum = 0; + } + if (picokpr_getOutItemArgOfs(network, outitem) != 0) { + switch (picokpr_getOutItemType(network, picokpr_getOutItemArgOfs(network, outitem))) { + case PR_OVar: + lvar = pr_findVariable(vars,picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, outitem))); + if (lvar != NULL) { + litem = lvar->first; + } + pr->tmpStr1[0] = 0; + while (litem != NULL) { + if (litem->head.type == PICODATA_ITEM_TOKEN) { + pr_strcat(pr->tmpStr1,litem->data); + } + litem = litem->next; + } + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, lcmd,lnum,0,pr->tmpStr1); + break; + case PR_OStr: + if (picokpr_getOutItemStrOfs(network, picokpr_getOutItemArgOfs(network, outitem)) != 0) { + lstrp = picokpr_getOutItemStr(network, picokpr_getOutItemArgOfs(network, outitem)); + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,lnum,0,lstrp); + } + break; + default: + pr_startItemList(& lf,& ll); + pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, outitem),vars,& lf,& ll); + if (pr->outOfMemory) return; + if (((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN))) { + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,lnum,0,lf->data); + } + break; + } + } else { + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,lnum,0,pr->tmpStr1); + } + break; + case PR_OGenFile: + if (picokpr_getOutItemArgOfs(network, outitem) != 0) { + lcmd = PICODATA_ITEMINFO1_CMD_SAVE; + } else { + lcmd = PICODATA_ITEMINFO1_CMD_UNSAVE; + } + pr->tmpStr1[0] = 0; + lnum = 0; + if (picokpr_getOutItemArgOfs(network, outitem) != 0) { + switch (picokpr_getOutItemType(network, picokpr_getOutItemArgOfs(network, outitem))) { + case PR_OVar: + lvar = pr_findVariable(vars,picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, outitem))); + if (lvar != NULL) { + litem = lvar->first; + } + pr->tmpStr1[0] = 0; + while (litem != NULL) { + if (litem->head.type == PICODATA_ITEM_TOKEN) { + pr_strcat(pr->tmpStr1,litem->data); + } + litem = litem->next; + } + if ((lnum = picodata_getPuTypeFromExtension(pr->tmpStr1, /*input*/FALSE)) != PICODATA_ITEMINFO2_CMD_TO_UNKNOWN) { + if (pr->saveFile[0] != 0) { + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_UNSAVE, + picodata_getPuTypeFromExtension(pr->saveFile, /*input*/FALSE),0,pr->saveFile); + } + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, lcmd,lnum,0,pr->tmpStr1); + pr_strcpy(pr->saveFile, pr->tmpStr1); + } + break; + case PR_OStr: + if (picokpr_getOutItemStrOfs(network, picokpr_getOutItemArgOfs(network, outitem)) != 0) { + lstrp = picokpr_getOutItemStr(network, picokpr_getOutItemArgOfs(network, outitem)); + if ((lnum = picodata_getPuTypeFromExtension(lstrp, /*input*/FALSE)) != PICODATA_ITEMINFO2_CMD_TO_UNKNOWN) { + if (pr->saveFile[0] != 0) { + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_UNSAVE, + picodata_getPuTypeFromExtension(pr->saveFile, /*input*/FALSE),0,pr->saveFile); + } + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, lcmd,lnum,0,lstrp); + pr_strcpy(pr->saveFile, lstrp); + } + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,lnum,0,lstrp); + } + break; + default: + pr_startItemList(& lf,& ll); + pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, outitem),vars,& lf,& ll); + if (pr->outOfMemory) return; + if (((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN))) { + if ((lnum = picodata_getPuTypeFromExtension(lf->data, /*input*/FALSE)) != PICODATA_ITEMINFO2_CMD_TO_UNKNOWN) { + if (pr->saveFile[0] != 0) { + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_UNSAVE, + picodata_getPuTypeFromExtension(pr->saveFile, /*input*/FALSE),0,pr->saveFile); + } + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, lcmd,lnum,0,lf->data); + pr_strcpy(pr->saveFile, lf->data); + } + } + break; + } +/* + } else { + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,lnum,0,pr->tmpStr1); +*/ + } + break; + case PR_OUseSig: case PR_OPlay: + lout = FALSE; + lf0beg = -(1); + lf0end = -(1); + lxfadebeg[0] = 0; + lxfadeend[0] = 0; + pr->tmpStr1[0] = 0; + if ((picokpr_getOutItemType(network, outitem) == PR_OUseSig)) { + lcmd = PICODATA_ITEMINFO1_CMD_IGNSIG; + } else { + lcmd = PICODATA_ITEMINFO1_CMD_IGNORE; + } + if (picokpr_getOutItemArgOfs(network, outitem) != 0) { + linfo2 = PICODATA_ITEMINFO2_CMD_START; + } else { + linfo2 = PICODATA_ITEMINFO2_CMD_END; + } + if (picokpr_getOutItemArgOfs(network, outitem) != 0) { + switch (picokpr_getOutItemType(network, picokpr_getOutItemArgOfs(network, outitem))) { + case PR_OVar: + lvar = pr_findVariable(vars,picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, outitem))); + if (lvar != NULL) { + litem = lvar->first; + } + pr->tmpStr1[0] = 0; + while (litem != NULL) { + if (litem->head.type == PICODATA_ITEM_TOKEN) { + pr_strcat(pr->tmpStr1,litem->data); + } + litem = litem->next; + } + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PLAY, + picodata_getPuTypeFromExtension(pr->tmpStr1, /*input*/TRUE),0, pr->tmpStr1); + lout = TRUE; + break; + case PR_OStr: + if (picokpr_getOutItemStrOfs(network, picokpr_getOutItemArgOfs(network, outitem)) != 0) { + lstrp = picokpr_getOutItemStr(network, picokpr_getOutItemArgOfs(network, outitem)); + pr_strcpy(pr->tmpStr1, lstrp); + lout = TRUE; + } + break; + default: + pr_startItemList(& lf,& ll); + pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, outitem),vars,& lf,& ll); + if (pr->outOfMemory) return; + if ((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN)) { + pr_strcpy(pr->tmpStr1, lf->data); + lout = TRUE; + } + break; + } + } + argOfs = picokpr_getOutItemArgOfs(network, outitem); + if (argOfs != 0) { + nextOfs = picokpr_getOutItemNextOfs(network, outitem); + if (nextOfs != 0) { + if (picokpr_getOutItemType(network, nextOfs) == PR_OVal) { + lf0beg = picokpr_getOutItemVal(network, nextOfs); + } + nextOfs2 = picokpr_getOutItemNextOfs(network, nextOfs); + if (nextOfs2 != 0) { + if (picokpr_getOutItemType(network, nextOfs2) == PR_OVal) { + lf0end = picokpr_getOutItemVal(network, nextOfs2); + } + nextOfs3 = picokpr_getOutItemNextOfs(network, nextOfs2); + if (nextOfs3 != 0) { + if ((picokpr_getOutItemType(network, nextOfs3) == PR_OStr) && (picokpr_getOutItemStrOfs(network, nextOfs3) != 0)) { + lstrp = picokpr_getOutItemStr(network, nextOfs3); + pr_strcpy(lxfadebeg, lstrp); + } + nextOfs4 = picokpr_getOutItemNextOfs(network, nextOfs3); + if (nextOfs4 != 0) { + if ((picokpr_getOutItemType(network, nextOfs4) == PR_OStr) && (picokpr_getOutItemStrOfs(network, nextOfs4) != 0)) { + lstrp = picokpr_getOutItemStr(network, nextOfs4); + pr_strcpy(lxfadeend, lstrp); + } + } + } + } + } + } + if (lout) { + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,PICODATA_ITEMINFO1_CMD_PLAY, + picodata_getPuTypeFromExtension(pr->tmpStr1, /*input*/TRUE),0,pr->tmpStr1); + } + pr_putItem(this, pr,& (*first),& (*last),PICODATA_ITEM_CMD,lcmd,linfo2,0,(picoos_uchar*)""); + break; + default: + PICODBG_INFO(("unknown command")); + break; + } +} + + +static void pr_getOutputItemList (picodata_ProcessingUnit this, + pr_subobj_t * pr, + picokpr_Preproc network, + picokpr_OutItemArrOffset outitem, + pr_OutItemVarPtr vars, + pr_ioItemPtr * first, + pr_ioItemPtr * last) +{ + + picokpr_OutItemArrOffset lo; + picoos_int32 llen; + picoos_int32 llen2; + picokpr_VarStrPtr lstrp; + picoos_int32 lval32; + picoos_int32 li; + picoos_int32 li2; + picoos_int32 ln; + picoos_int32 ln2; + pr_ioItemPtr litem2; + pr_ioItemPtr lf; + pr_ioItemPtr ll; + picoos_int32 lid; + picoos_uint8 ltype; + picoos_int8 lsubtype; + pr_OutItemVarPtr lvar; + picoos_int32 lspellmode; + picoos_int32 largOfs; + picoos_int32 lnextOfs; + + + lo = outitem; + while (lo != 0) { + switch (picokpr_getOutItemType(network, lo)) { + case PR_OStr: + lstrp = picokpr_getOutItemStr(network, lo); + if (pr->outOfMemory) return; + pr_initItem(this, &pr->tmpItem); + pr->tmpItem.head.type = PICODATA_ITEM_TOKEN; + pr->tmpItem.head.info1 = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; + pr->tmpItem.head.info2 = -1; + pr->tmpItem.head.len = pr_strcpy(pr->tmpItem.data, lstrp); + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),litem2); + break; + case PR_OVar: + lvar = pr_findVariable(vars,picokpr_getOutItemVal(network, lo)); + if (lvar != NULL) { + lf = lvar->first; + } else { + lf = NULL; + } + while (lf != NULL) { + pr_copyItem(this, pr_WorkMem,& (*lf),& litem2); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),litem2); + lf = lf->next; + } + break; + case PR_OSpell: + lspellmode = PR_SPELL; + largOfs = picokpr_getOutItemArgOfs(network, lo); + if ((largOfs!= 0) && ((lnextOfs = picokpr_getOutItemNextOfs(network, largOfs)) != 0)) { + lspellmode = picokpr_getOutItemVal(network, lnextOfs); + } + pr_startItemList(& lf,& ll); + pr_getOutputItemList(this, pr, network,largOfs,vars,& lf,& ll); + if (pr->outOfMemory) return; + while (lf != NULL) { + switch (lf->head.type) { + case PICODATA_ITEM_TOKEN: + li = 0; + ln = pr_strlen(lf->data); + while (li < ln) { + pr_initItem(this, &pr->tmpItem); + if (pr->outOfMemory) return; + pr->tmpItem.head.type = PICODATA_ITEM_TOKEN; + pr->tmpItem.head.info1 = lf->head.info1; + pr->tmpItem.head.info2 = lf->head.info2; + pr->tmpItem.head.len = picobase_det_utf8_length(lf->data[li]); + for (li2 = 0; li2 < pr->tmpItem.head.len; li2++) { + pr->tmpItem.data[li2] = lf->data[li]; + li++; + } + pr->tmpItem.data[pr->tmpItem.head.len] = 0; + pr->tmpItem.val = 0; + lid = picoktab_graphOffset(pr->graphs,pr->tmpItem.data); + if (lid > 0) { + if (picoktab_getIntPropTokenType(pr->graphs, lid, <ype)) { + if ((ltype == PICODATA_ITEMINFO1_TOKTYPE_LETTERV)/* || (ltype == PICODATA_ITEMINFO1_TOKTYPE_DIGIT)*/) { + pr->tmpItem.head.len = pr_strcat(pr->tmpItem.data,(picoos_uchar*)SPEC_CHAR); + } + } + picoktab_getIntPropTokenSubType(pr->graphs, lid, &lsubtype); + } else { + ltype = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; + lsubtype = -(1); + } + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last), litem2); + if (lspellmode == PR_SPELL_WITH_PHRASE_BREAK) { + pr_initItem(this, &pr->tmpItem); + pr->tmpItem.head.type = PICODATA_ITEM_TOKEN; + pr->tmpItem.head.info1 = PICODATA_ITEMINFO1_TOKTYPE_CHAR; + pr->tmpItem.head.info2 = lsubtype; + pr->tmpItem.head.len = 1; + pr->tmpItem.data[0] = ','; + pr->tmpItem.data[1] = 0; + pr->tmpItem.val = 0; + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),litem2); + } else if (lspellmode == PR_SPELL_WITH_SENTENCE_BREAK) { + pr_initItem(this, &pr->tmpItem); + pr->tmpItem.head.type = PICODATA_ITEM_CMD; + pr->tmpItem.head.info1 = PICODATA_ITEMINFO1_CMD_FLUSH; + pr->tmpItem.head.info2 = PICODATA_ITEMINFO2_NA; + pr->tmpItem.head.len = 0; + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),litem2); + } else if (lspellmode > 0) { + pr_initItem(this, &pr->tmpItem); + pr->tmpItem.head.type = PICODATA_ITEM_TOKEN; + pr->tmpItem.head.info1 = PICODATA_ITEMINFO1_TOKTYPE_CHAR; + pr->tmpItem.head.info2 = lsubtype; + pr->tmpItem.head.len = 1; + pr->tmpItem.data[0] = ','; + pr->tmpItem.data[1] = 0; + pr->tmpItem.val = 0; + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),litem2); + } + } + break; + default: + pr_copyItem(this, pr_WorkMem,& (*lf),& litem2); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),litem2); + break; + } + ll = lf; + lf = lf->next; + ll->next = NULL; + } + break; + case PR_OConcat: + pr_startItemList(& lf,& ll); + pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, lo),vars,& lf,& ll); + if (pr->outOfMemory) return; + pr_initItem(this, &pr->tmpItem); + pr->tmpItem.head.type = PICODATA_ITEM_TOKEN; + pr->tmpItem.head.info1 = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; + pr->tmpItem.head.info2 = -(1); + pr->tmpItem.head.len = 0; + pr->tmpItem.data[0] = 0; + pr->tmpItem.val = 0; + while (lf != NULL) { + switch (lf->head.type) { + case PICODATA_ITEM_TOKEN: + pr->tmpItem.head.len = pr_strcat(pr->tmpItem.data,lf->data); + break; + case PICODATA_ITEM_CMD: + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),litem2); + + pr_copyItem(this, pr_WorkMem, lf, &litem2); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),litem2); + + pr_initItem(this, &pr->tmpItem); + pr->tmpItem.head.type = PICODATA_ITEM_TOKEN; + pr->tmpItem.head.info1 = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; + pr->tmpItem.head.info2 = -(1); + pr->tmpItem.head.len = 0; + pr->tmpItem.data[0] = 0; + pr->tmpItem.val = 0; + break; + default: + break; + } + lf = lf->next; + } + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),litem2); + break; + case PR_ORomanToCard: + pr_startItemList(& lf,& ll); + pr_getOutputItemList(this, pr, network,picokpr_getOutItemArgOfs(network, lo),vars,& lf,& ll); + if (pr->outOfMemory) return; + if ((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN)) { + pr_initItem(this, &pr->tmpItem); + pr_copyItemContent(this, lf, &pr->tmpItem); + if (pr_isLatinNumber(lf->data, & lval32)) { + pr_int_to_string(lval32, (picoos_char *)pr->tmpItem.data, PR_MAX_DATA_LEN_Z); + pr->tmpItem.head.len = pr_strlen(pr->tmpItem.data); + pr->tmpItem.val = lval32; + } + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); + pr_appendItem(this, & (*first),& (*last),litem2); + } + break; + case PR_OVal: + break; + case PR_OLeft: + pr_startItemList(& lf,& ll); + pr_getOutputItemList(this, pr, network,picokpr_getOutItemNextOfs(network, picokpr_getOutItemArgOfs(network, lo)),vars,& lf,& ll); + if (pr->outOfMemory) return; + if ((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN)) { + pr_initItem(this, &pr->tmpItem); + pr_copyItemContent(this, lf, &pr->tmpItem); + llen = lf->head.len; + llen2 = picobase_utf8_length(pr->tmpItem.data,PR_MAX_DATA_LEN); + ln = 0; + ln2 = 0; + largOfs = picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, lo)); + while ((ln < llen) && (ln2 < llen2) && (ln2 < largOfs)) { + ln = ln + picobase_det_utf8_length(pr->tmpItem.data[ln]); + ln2++; + } + pr->tmpItem.data[ln] = 0; + pr->tmpItem.head.len = ln; + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, &litem2); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),litem2); + } + break; + case PR_ORight: + pr_startItemList(& lf,& ll); + pr_getOutputItemList(this, pr, network,picokpr_getOutItemNextOfs(network, picokpr_getOutItemArgOfs(network, lo)),vars,& lf,& ll); + if (pr->outOfMemory) return; + if ((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN)) { + pr_initItem(this, &pr->tmpItem); + pr_copyItemContent(this, lf, & pr->tmpItem); + llen = lf->head.len; + llen2 = picobase_utf8_length(pr->tmpItem.data,PR_MAX_DATA_LEN); + ln = 0; + ln2 = 0; + while ((ln < llen) && (ln2 < llen2) && (ln2 < (llen2 - picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, lo))))) { + ln = ln + picobase_det_utf8_length(pr->tmpItem.data[ln]); + ln2++; + } + pr->tmpItem.head.len = pr_removeSubstring(0,ln,pr->tmpItem.data); + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, & litem2); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),litem2); + } + break; + case PR_OItem: + pr_startItemList(& lf,& ll); + pr_getOutputItemList(this, pr, network,picokpr_getOutItemNextOfs(network, picokpr_getOutItemArgOfs(network, lo)),vars,& lf,& ll); + if (pr->outOfMemory) return; + ln = picokpr_getOutItemVal(network, picokpr_getOutItemArgOfs(network, lo)); + li = 1; + while ((li < ln) && (lf != NULL)) { + lf = lf->next; + li++; + } + if ((lf != NULL) && (li == ln) && (lf->head.type == PICODATA_ITEM_TOKEN)) { + pr_copyItem(this, pr_WorkMem, lf, & litem2); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),litem2); + } + break; + case PR_ORLZ: + pr_startItemList(& lf,& ll); + pr_getOutputItemList(this, pr, network, picokpr_getOutItemArgOfs(network, lo),vars,& lf,& ll); + if (pr->outOfMemory) return; + if ((lf != NULL) && (lf->head.type == PICODATA_ITEM_TOKEN)) { + pr_initItem(this, &pr->tmpItem); + pr_copyItemContent(this, lf, & pr->tmpItem); + li = 0; + while ((li < lf->head.len) && (pr->tmpItem.data[li] == '0')) { + li++; + } + pr->tmpItem.head.len = pr_removeSubstring(0,li,pr->tmpItem.data); + pr_copyItem(this, pr_WorkMem, &pr->tmpItem, & litem2); + if (pr->outOfMemory) return; + pr_appendItem(this, & (*first),& (*last),litem2); + } + break; + case PR_OIgnore: case PR_OPitch: case PR_OSpeed: case PR_OVolume: case PR_OPhonSVOXPA: case PR_OPhonSAMPA: case PR_OBreak: case PR_OMark: case PR_OPara: case PR_OSent: case PR_OPlay: + case PR_OUseSig: case PR_OGenFile: case PR_OAudioEdit: case PR_OContext: case PR_OVoice: + pr_genCommands(this, pr, network,lo,vars,& (*first),& (*last)); + if (pr->outOfMemory) return; + break; + default: + PICODBG_INFO(("unkown command")); + break; + } + lo = picokpr_getOutItemNextOfs(network, lo); + } +} + + +static picoos_int32 pr_attrVal (picokpr_Preproc network, picokpr_TokArrOffset tok, pr_TokSetEleWP type) +{ + + pr_TokSetEleWP tse; + picoos_int32 n; + picokpr_TokSetWP set; + + n = 0; + tse = PR_FIRST_TSE_WP; + set = picokpr_getTokSetWP(network, tok); + while (tse < type) { + if (((1<rbestpath.rlen) { + with__0 = & pr->rbestpath.rele[*i]; + li = 0; + if (*i > 0) { + while ((li < 127) && (li < pr->rbestpath.rele[*i].rdepth)) { + pr->lspaces[li++] = ' '; + } + } + pr->lspaces[li] = 0; + if (with__0->rprodname != 0) { + PICODBG_INFO(("pp path :%s%s(", pr->lspaces, picokpr_getVarStrPtr(with__0->rnetwork,with__0->rprodname))); + } + if ((pr->ritems[with__0->ritemid+1] != NULL) && (pr->ritems[with__0->ritemid+1]->head.type == PICODATA_ITEM_TOKEN)) { + PICODBG_INFO(("pp in (1): %s'%s'", pr->lspaces, pr->ritems[with__0->ritemid+1]->data)); + } + if ((pr->ritems[with__0->ritemid+1] != NULL)) { + while ((pr->rinItemList != NULL) && (pr->rinItemList != pr->ritems[with__0->ritemid+1]) && (pr->rinItemList->head.type != PICODATA_ITEM_TOKEN)) { + lit = pr->rinItemList; + pr->rinItemList = pr->rinItemList->next; + lit->next = NULL; + pr_copyItem(this, pr_WorkMem,& (*lit),& lcopy); + if (pr->outOfMemory) return; + pr_disposeItem(this, & lit); + pr_appendItem(this, & (*o),& (*ol),lcopy); + } + if (pr->rinItemList != NULL) { + lit = pr->rinItemList; + pr->rinItemList = pr->rinItemList->next; + lit->next = NULL; + } else { + lit = NULL; + } + } + wpset = picokpr_getTokSetWP(with__0->rnetwork, with__0->rtok); + npset = picokpr_getTokSetNP(with__0->rnetwork, with__0->rtok); + + if ((PR_TSE_MASK_PROD & wpset) != 0) { + if ((PR_TSE_MASK_VAR & wpset) != 0) { + lvar = pr_findVariable(lvars,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEVar)); + if (lvar == NULL) { + pr_ALLOCATE(this, pr_WorkMem, (void *) & lvar,(sizeof (*lvar))); + lvar->next = lvars; + lvar->id = pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEVar); + lvars = lvar; + } + pr_startItemList(& lvar->first,& lvar->last); + pr_getOutput(this, pr, & (*i),(d + 1),& lvar->first,& lvar->last); + if (pr->outOfMemory) return; + } else { + pr_startItemList(& ldit,& ldlit); + pr_getOutput(this, pr, & (*i),(d + 1),& ldit,& ldlit); + if (pr->outOfMemory) return; + } + (*i)++; + } else if ((PR_TSE_MASK_VAR & wpset) != 0) { + lvar = pr_findVariable(lvars,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEVar)); + if (lvar == NULL) { + pr_ALLOCATE(this, pr_WorkMem, (void *) & lvar,(sizeof (*lvar))); + lvar->next = lvars; + lvar->id = pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEVar); + lvars = lvar; + } + if (((PR_TSE_MASK_LEX & wpset) != 0) && ((PR_TSE_MASK_LETTER & npset) == 0)) { + if (lfirst) { + pr_newItem(this, pr_WorkMem,& lit, PICODATA_ITEM_TOKEN, sizeof(struct pr_ioItem), /*inItem*/FALSE); + if (pr->outOfMemory) return; + lit->head.type = PICODATA_ITEM_TOKEN; + lit->head.info1 = pr->ritems[with__0->ritemid+1]->head.info1; + lit->head.info2 = pr->ritems[with__0->ritemid+1]->head.info2; + if (pr->ritems[with__0->ritemid+1]->head.info1 == PICODATA_ITEMINFO1_TOKTYPE_SPACE) { + lit->head.len = pr_strcpy(lit->data, (picoos_uchar*)"_"); + } else { + lit->head.len = pr_strcpy(lit->data, pr->ritems[with__0->ritemid+1]->data); + } + lvar->first = lit; + lvar->last = lit; + lfirst = FALSE; + } else { + if ((pr->ritems[with__0->ritemid+1]->head.info1 == PICODATA_ITEMINFO1_TOKTYPE_SPACE)) { + lvar->last->head.len = pr_strcat(lvar->last->data,(picoos_uchar*)"_"); + } else { + lvar->last->head.len = pr_strcat(lvar->last->data,pr->ritems[with__0->ritemid+1]->data); + } + lvar->last->head.info1 = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; + lvar->last->head.info2 = -(1); + } + } else { + lvar->first = pr->ritems[with__0->ritemid+1]; + lvar->last = pr->ritems[with__0->ritemid+1]; + } + (*i)++; + } else if ((PR_TSE_MASK_OUT & wpset) != 0) { + pr_getOutputItemList(this, pr, with__0->rnetwork,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEOut),lvars,& (*o),& (*ol)); + if (pr->outOfMemory) return; + (*i)++; + } else if (((*i) < (pr->rbestpath.rlen - 1)) && (d != pr->rbestpath.rele[(*i) + 1].rdepth)) { + if ((*i > 0) && (with__0->rdepth-1) == pr->rbestpath.rele[*i + 1].rdepth) { + li = 0; + while ((li < 127) && (li < with__0->rdepth-1)) { + pr->lspaces[li++] = ' '; + } + pr->lspaces[li] = 0; + PICODBG_INFO(("pp path :%s)", pr->lspaces)); + } + return; + } else { + (*i)++; + } + if ((PR_TSE_MASK_LEX & wpset) == 0) { + lfirst = TRUE; + } + } + li = 0; + while ((li < 127) && (li < pr->rbestpath.rele[*i].rdepth-1)) { + pr->lspaces[li++] = ' '; + } + pr->lspaces[li] = 0; + PICODBG_INFO(("pp path :%s)", pr->lspaces)); +} + + +static void pr_outputPath (picodata_ProcessingUnit this, pr_subobj_t * pr) +{ + register struct pr_PathEle * with__0; + picoos_int32 li; + pr_ioItemPtr lf; + pr_ioItemPtr ll; + pr_ioItemPtr lit; + pr_ioItemPtr lit2; + pr_MemState lmemState; + picoos_bool lastPlayFileFound; + + pr_getMemState(this, pr_WorkMem, & lmemState); + lf = NULL; + ll = NULL; + li = -(1); + pr_getOutput(this, pr, & li,1,& lf,& ll); + if (pr->outOfMemory) return; + lastPlayFileFound = TRUE; + while (lf != NULL) { + lit = lf; + lf = lf->next; + lit->next = NULL; + if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PLAY)) { + lastPlayFileFound = picoos_FileExists(this->common, (picoos_char*)lit->data); + if (!lastPlayFileFound) { + PICODBG_WARN(("file '%s' not found; synthesizing enclosed text instead", lit->data)); + picoos_emRaiseWarning(this->common->em, PICO_EXC_CANT_OPEN_FILE, (picoos_char*)"", (picoos_char*)"file '%s' not found; synthesizing enclosed text instead",lit->data); + } + } + if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PHONEME) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_START)) { + pr->insidePhoneme = TRUE; + } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PHONEME)&& pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_END)) { + pr->insidePhoneme = FALSE; + } + if ((pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PLAY) && !lastPlayFileFound)) { + } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_IGNORE) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_START)) { + if (lastPlayFileFound) { + pr->rignore++; + } + } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_IGNORE) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_END)) { + if (lastPlayFileFound) { + if (pr->rignore > 0) { + pr->rignore--; + } + } + } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_IGNSIG) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_START) && !lastPlayFileFound) { + } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_IGNSIG) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_END) && !lastPlayFileFound) { + } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_CONTEXT)) { + if (pr->rignore <= 0) { + pr_setContext(this, pr, lit->data); + } + } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_VOICE)) { + if (pr->rignore <= 0) { + pr_copyItem(this, pr_DynMem,lit,& lit2); + if (pr->outOfMemory) return; + pr_appendItem(this, & pr->routItemList,& pr->rlastOutItem, lit2); + } + } else { + if ((pr->rignore <= 0) && !(pr->insidePhoneme && (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PLAY) || + pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_IGNSIG)))) { + PICODBG_INFO(("pp out(1): '%s'", lit->data)); + pr_copyItem(this, pr_DynMem,lit,& lit2); + if (pr->outOfMemory) return; + pr_appendItemToOutItemList(this, pr, & pr->routItemList,& pr->rlastOutItem,lit2); + if (pr->outOfMemory) return; + } + } + } + for (li = 0; lirbestpath.rlen; li++) { + with__0 = & pr->rbestpath.rele[li]; + pr_disposeItem(this, & pr->ritems[with__0->ritemid+1]); + } + pr_resetMemState(this, pr_WorkMem, lmemState); +} + +/* *****************************************************************************/ + +static void pr_compare (picoos_uchar str1lc[], picoos_uchar str2[], picoos_int16 * result) +{ + + picoos_int32 i; + picoos_int32 j; + picoos_int32 l; + picoos_uint32 pos; + picoos_bool finished1; + picoos_bool finished2; + picoos_bool done; + picobase_utf8char utf8char; + + pos = 0; + l = picobase_get_next_utf8char(str2, PR_MAX_DATA_LEN, & pos,utf8char); + picobase_lowercase_utf8_str(utf8char,(picoos_char*)utf8char,PICOBASE_UTF8_MAXLEN+1, &done); + l = picobase_det_utf8_length(utf8char[0]); + j = 0; + i = 0; + while ((i < PR_MAX_DATA_LEN) && (str1lc[i] != 0) && (l > 0) && (j <= 3) && (str1lc[i] == utf8char[j])) { + i++; + j++; + if (j >= l) { + l = picobase_get_next_utf8char(str2, PR_MAX_DATA_LEN, & pos,utf8char); + picobase_lowercase_utf8_str(utf8char,(picoos_char*)utf8char,PICOBASE_UTF8_MAXLEN+1, &done); + l = picobase_det_utf8_length(utf8char[0]); + j = 0; + } + } + finished1 = (i >= PR_MAX_DATA_LEN) || (str1lc[i] == 0); + finished2 = (j > 3) || (utf8char[j] == 0); + if (finished1 && finished2) { + *result = PR_EQUAL; + } else if (finished1) { + *result = PR_SMALLER; + } else if (finished2) { + *result = PR_LARGER; + } else { + if (str1lc[i] < utf8char[j]) { + *result = PR_SMALLER; + } else { + *result = PR_LARGER; + } + } +} + + +static picoos_bool pr_hasToken (picokpr_TokSetWP * tswp, picokpr_TokSetNP * tsnp) +{ + return (((( PR_TSE_MASK_SPACE | PR_TSE_MASK_DIGIT | PR_TSE_MASK_LETTER | PR_TSE_MASK_SEQ + | PR_TSE_MASK_CHAR | PR_TSE_MASK_BEGIN | PR_TSE_MASK_END) & (*tsnp)) != 0) || + ((PR_TSE_MASK_LEX & (*tswp)) != 0)); +} + + +static picoos_bool pr_getNextToken (picodata_ProcessingUnit this, pr_subobj_t * pr) +{ + register struct pr_PathEle * with__0; + picoos_int32 len; + picokpr_TokSetNP npset; + + len = pr->ractpath.rlen; + with__0 = & pr->ractpath.rele[len - 1]; + npset = picokpr_getTokSetNP(with__0->rnetwork, with__0->rtok); + if ((len > 0) && (pr->ractpath.rlen < PR_MAX_PATH_LEN) && ((PR_TSE_MASK_NEXT & npset) != 0)) { + pr_initPathEle(& pr->ractpath.rele[len]); + pr->ractpath.rele[len].rnetwork = with__0->rnetwork; + pr->ractpath.rele[len].rtok = picokpr_getTokNextOfs(with__0->rnetwork, with__0->rtok); + pr->ractpath.rele[len].rdepth = with__0->rdepth; + pr->ractpath.rlen++; + return TRUE; + } else { + if (len >= PR_MAX_PATH_LEN) { + PICODBG_INFO(("max path len reached (pr_getNextToken)")); + } + return FALSE; + } +} + + +static picoos_bool pr_getAltToken (picodata_ProcessingUnit this, pr_subobj_t * pr) +{ + register struct pr_PathEle * with__0; + picokpr_TokArrOffset lTok; + picokpr_TokSetNP npset; + + + with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; + if ((pr->ractpath.rlen > 0) && (pr->ractpath.rlen < PR_MAX_PATH_LEN)) { + npset = picokpr_getTokSetNP(with__0->rnetwork, with__0->rtok); + if (with__0->rcompare == PR_SMALLER) { + if ((PR_TSE_MASK_ALTL & npset) != 0) { + lTok = picokpr_getTokAltLOfs(with__0->rnetwork, with__0->rtok); + } else { + return FALSE; + } + } else { + if ((PR_TSE_MASK_ALTR & npset) != 0) { + lTok = picokpr_getTokAltROfs(with__0->rnetwork, with__0->rtok); + } else { + return FALSE; + } + } + with__0->rlState = PR_LSInit; + with__0->rtok = lTok; + with__0->ritemid = -1; + with__0->rcompare = -1; + with__0->rprodname = 0; + with__0->rprodprefcost = 0; + return TRUE; + } else { + if (pr->ractpath.rlen >= PR_MAX_PATH_LEN) { + PICODBG_INFO(("max path len reached (pr_getAltToken)")); + } + return FALSE; + } +} + + +static picoos_bool pr_findProduction (picodata_ProcessingUnit this, pr_subobj_t * pr, + picoos_uchar str[], picokpr_Preproc * network, picokpr_TokArrOffset * tokOfs) +{ + picoos_bool found; + picoos_int32 p; + picoos_int32 ind; + picoos_int32 i; + picoos_bool done; + picokpr_VarStrPtr lstrp; + picoos_int32 lprodarrlen; + + ind = 0; + pr_getTermPartStr(str,& ind,'.',pr->tmpStr1,& done); + pr_getTermPartStr(str,& ind,'.',pr->tmpStr2,& done); + found = FALSE; + + for (p=0; ppreproc[p] != NULL)) { + if (pr_strEqual(pr->tmpStr1, picokpr_getPreprocNetName(pr->preproc[p]))) { + i = 0; + lprodarrlen = picokpr_getProdArrLen(pr->preproc[p]); + while (!found && (i <= (lprodarrlen - 1))) { + lstrp = picokpr_getVarStrPtr(pr->preproc[p],picokpr_getProdNameOfs(pr->preproc[p], i)); + if (pr_strEqual(pr->tmpStr2, lstrp)) { + *network = pr->preproc[p]; + *tokOfs = picokpr_getProdATokOfs(pr->preproc[p], i); + return TRUE; + } + i++; + } + } + } + } + return FALSE; +} + + +static picoos_bool pr_getProdToken (picodata_ProcessingUnit this, pr_subobj_t * pr) +{ + register struct pr_PathEle * with__0; + picokpr_VarStrPtr lstrp; + picokpr_TokSetWP wpset; + + if ((pr->ractpath.rlen > 0) && (pr->ractpath.rlen < PR_MAX_PATH_LEN)) { + with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; + wpset = picokpr_getTokSetWP(with__0->rnetwork, with__0->rtok); + if ((PR_TSE_MASK_PROD & wpset) != 0) { + if ((PR_TSE_MASK_PRODEXT & wpset) != 0) { + pr_initPathEle(& pr->ractpath.rele[pr->ractpath.rlen]); + lstrp = picokpr_getVarStrPtr(with__0->rnetwork, pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEProdExt)); + if (pr_findProduction(this, pr, lstrp,& pr->ractpath.rele[pr->ractpath.rlen].rnetwork,& pr->ractpath.rele[pr->ractpath.rlen].rtok)) { + with__0->rprodname = picokpr_getProdNameOfs(with__0->rnetwork, pr_attrVal(with__0->rnetwork, with__0->rtok,PR_TSEProd)); + with__0->rprodprefcost = picokpr_getProdPrefCost(with__0->rnetwork, pr_attrVal(with__0->rnetwork,with__0->rtok,PR_TSEProd)); + pr->ractpath.rele[pr->ractpath.rlen].rdepth = with__0->rdepth + 1; + pr->ractpath.rlen++; + return TRUE; + } else { + return FALSE; + } + } else { + pr_initPathEle(& pr->ractpath.rele[pr->ractpath.rlen]); + pr->ractpath.rele[pr->ractpath.rlen].rnetwork = with__0->rnetwork; + pr->ractpath.rele[pr->ractpath.rlen].rtok = picokpr_getProdATokOfs(with__0->rnetwork, pr_attrVal(with__0->rnetwork, with__0->rtok,PR_TSEProd)); + with__0->rprodname = picokpr_getProdNameOfs(with__0->rnetwork, pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEProd)); + with__0->rprodprefcost = picokpr_getProdPrefCost(with__0->rnetwork, pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEProd)); + pr->ractpath.rele[pr->ractpath.rlen].rdepth = with__0->rdepth + 1; + pr->ractpath.rlen++; + return TRUE; + } + } + } + if (pr->ractpath.rlen >= PR_MAX_PATH_LEN) { + PICODBG_INFO(("max path len reached (pr_getProdToken)")); + } + return FALSE; +} + + +static picoos_bool pr_getProdContToken (picodata_ProcessingUnit this, pr_subobj_t * pr) +{ + picoos_int32 li; + + li = pr->ractpath.rlen - 1; + while ((li > 0) && !((pr->ractpath.rele[li].rdepth == (pr->ractpath.rele[pr->ractpath.rlen - 1].rdepth - 1)) && ((PR_TSE_MASK_PROD &picokpr_getTokSetWP(pr->ractpath.rele[li].rnetwork, pr->ractpath.rele[li].rtok)) != 0))) { + li--; + } + if (((li >= 0) && (pr->ractpath.rlen < PR_MAX_PATH_LEN) && (PR_TSE_MASK_NEXT &picokpr_getTokSetNP(pr->ractpath.rele[li].rnetwork, pr->ractpath.rele[li].rtok)) != 0)) { + pr_initPathEle(& pr->ractpath.rele[pr->ractpath.rlen]); + pr->ractpath.rele[pr->ractpath.rlen].rnetwork = pr->ractpath.rele[li].rnetwork; + pr->ractpath.rele[pr->ractpath.rlen].rtok = picokpr_getTokNextOfs(pr->ractpath.rele[li].rnetwork, pr->ractpath.rele[li].rtok); + pr->ractpath.rele[pr->ractpath.rlen].rdepth = pr->ractpath.rele[li].rdepth; + pr->ractpath.rlen++; + return TRUE; + } else { + if (pr->ractpath.rlen >= PR_MAX_PATH_LEN) { + PICODBG_INFO(("max path len reached (pr_getProdContToken)")); + } + return FALSE; + } +} + +/* *****************************************************************************/ + +static picoos_bool pr_getTopLevelToken (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_bool firstprod) +{ + if (firstprod) { + if (pr->actCtx != NULL) { + pr->prodList = pr->actCtx->rProdList; + } else { + pr->prodList = NULL; + } + } else if (pr->prodList != NULL) { + pr->prodList = pr->prodList->rNext; + } + if ((pr->prodList != NULL) && (pr->prodList->rProdOfs != 0) && (picokpr_getProdATokOfs(pr->prodList->rNetwork, pr->prodList->rProdOfs) != 0)) { + pr_initPathEle(& pr->ractpath.rele[pr->ractpath.rlen]); + pr->ractpath.rele[pr->ractpath.rlen].rdepth = 1; + pr->ractpath.rele[pr->ractpath.rlen].rnetwork = pr->prodList->rNetwork; + pr->ractpath.rele[pr->ractpath.rlen].rtok = picokpr_getProdATokOfs(pr->prodList->rNetwork, pr->prodList->rProdOfs); + pr->ractpath.rele[pr->ractpath.rlen].rlState = PR_LSInit; + pr->ractpath.rele[pr->ractpath.rlen].rcompare = -1; + pr->ractpath.rele[pr->ractpath.rlen].rprodname = picokpr_getProdNameOfs(pr->prodList->rNetwork, pr->prodList->rProdOfs); + pr->ractpath.rele[pr->ractpath.rlen].rprodprefcost = picokpr_getProdPrefCost(pr->prodList->rNetwork, pr->prodList->rProdOfs); + pr->ractpath.rlen++; + return TRUE; + } else { + return FALSE; + } +} + + +static picoos_bool pr_getToken (picodata_ProcessingUnit this, pr_subobj_t * pr) +{ + picoos_int32 ln; + picoos_int32 lid; + + ln = (pr->ractpath.rlen - 2); + while ((ln >= 0) && (pr->ractpath.rele[ln].ritemid == -1)) { + ln = ln - 1; + } + if (ln >= 0) { + lid = pr->ractpath.rele[ln].ritemid + 1; + } else { + lid = 0; + } + if (lid < pr->rnritems) { + pr->ractpath.rele[pr->ractpath.rlen - 1].ritemid = lid; + } else { + pr->ractpath.rele[pr->ractpath.rlen - 1].ritemid = -1; + } + return (lid < pr->rnritems); +} + + +static picoos_bool pr_getNextMultiToken (picodata_ProcessingUnit this, pr_subobj_t * pr) +{ + picoos_int32 len; + + len = pr->ractpath.rlen; + if ((len > 0) && (len < PR_MAX_PATH_LEN)) { + pr->ractpath.rele[len].rtok = pr->ractpath.rele[len - 1].rtok; + pr->ractpath.rele[len].ritemid = -(1); + pr->ractpath.rele[len].rcompare = pr->ractpath.rele[len - 1].rcompare; + pr->ractpath.rele[len].rdepth = pr->ractpath.rele[len - 1].rdepth; + pr->ractpath.rele[len].rlState = PR_LSInit; + pr->ractpath.rlen++; + return TRUE; + } else { + if (len >= PR_MAX_PATH_LEN) { + PICODBG_INFO(("max path len reached (pr_getNextMultiToken)")); + } + return FALSE; + } + return FALSE; +} + + +static pr_MatchState pr_matchMultiToken (picodata_ProcessingUnit this, pr_subobj_t * pr, + picokpr_TokSetNP npset, picokpr_TokSetWP wpset) +{ + picoos_bool lcontinue=FALSE; + picoos_bool lmatch=FALSE; + + if (lmatch) { + return PR_MSMatchedMulti; + } else if (lcontinue) { + return PR_MSMatchedContinue; + } else { + return PR_MSNotMatched; + } + pr = pr; /* avoid warning "var not used in this function"*/ + npset = npset; /* avoid warning "var not used in this function"*/ + wpset = wpset; /* avoid warning "var not used in this function"*/ + +} + + +static pr_MatchState pr_matchTokensSpace (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_int32 cmpres, + picokpr_TokSetNP npset, picokpr_TokSetWP wpset) +{ + register struct pr_PathEle * with__0; + picoos_int32 llen; + picoos_int32 lulen; + picoos_int32 li; + picokpr_VarStrPtr lstrp; + picoos_int32 leol; + + with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; + if ((PR_TSE_MASK_SPACE & npset) == 0) { + return PR_MSNotMatched; + } + lstrp = (picokpr_VarStrPtr)&pr->ritems[with__0->ritemid+1]->data; + lulen = picobase_utf8_length(lstrp,PR_MAX_DATA_LEN); + if (((PR_TSE_MASK_LEN & wpset) != 0) && (lulen != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSELen))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_MIN & wpset) != 0) && (lulen < pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMin))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_MAX & wpset) != 0) && (lulen > pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMax))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_STR & wpset) != 0) && (cmpres != PR_EQUAL)) { + return PR_MSNotMatched; + } + if ((PR_TSE_MASK_VAL & wpset) != 0) { + leol = 0; + llen = pr_strlen(lstrp); + for (li = 0; li < llen; li++) { + if (lstrp[li] == PR_EOL) { + leol++; + } + } + if (leol != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEVal)) { + return PR_MSNotMatched; + } + } + if (((PR_TSE_MASK_ID & wpset) != 0) && (pr->ritems[with__0->ritemid+1]->head.info2 != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEID))) { + return PR_MSNotMatched; + } + return PR_MSMatched; +} + + +static pr_MatchState pr_matchTokensDigit (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_int32 cmpres, + picokpr_TokSetNP npset, picokpr_TokSetWP wpset) +{ + register struct pr_PathEle * with__0; + picoos_int32 lulen; + picoos_int32 lval; + picokpr_VarStrPtr lstrp; + + with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; + if ((PR_TSE_MASK_DIGIT & npset) == 0) { + return PR_MSNotMatched; + } + lstrp = (picokpr_VarStrPtr)&pr->ritems[with__0->ritemid+1]->data; + lulen = picobase_utf8_length(lstrp,PR_MAX_DATA_LEN); + if ((((PR_TSE_MASK_LEN & wpset) != 0) && (lulen != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSELen)))) { + return PR_MSNotMatched; + } + lval = pr->ritems[with__0->ritemid+1]->val; + if (((PR_TSE_MASK_MIN & wpset) != 0) && (lval < pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMin))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_MAX & wpset) != 0) && (lval > pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMax))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_STR & wpset) != 0) && (cmpres != PR_EQUAL)) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_VAL & wpset) != 0) && (lval != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEVal))) { + return PR_MSNotMatched; + } + if ((((PR_TSE_MASK_NLZ & npset) != 0) && lstrp[0] == '0')) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_HEAD & wpset) != 0) && !(picokpr_isEqualHead(with__0->rnetwork,lstrp,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEHead)))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_MID & wpset) != 0) && !(picokpr_isEqualMid(with__0->rnetwork,lstrp,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMid)))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_TAIL & wpset) != 0) && !(picokpr_isEqualTail(with__0->rnetwork,lstrp,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSETail)))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_ID & wpset) != 0) && (pr->ritems[with__0->ritemid+1]->head.info2 != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEID))) { + return PR_MSNotMatched; + } + return PR_MSMatched; +} + + +static pr_MatchState pr_matchTokensSeq (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_int32 cmpres, + picokpr_TokSetNP npset, picokpr_TokSetWP wpset) +{ + + register struct pr_PathEle * with__0; + picoos_int32 lulen; + picokpr_VarStrPtr lstrp; + + with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; + + if (!((PR_TSE_MASK_SEQ & npset) != 0)) { + return PR_MSNotMatched; + } + lstrp = (picokpr_VarStrPtr)(void *) &pr->ritems[with__0->ritemid+1]->data; + lulen = picobase_utf8_length(lstrp,PR_MAX_DATA_LEN); + if (((PR_TSE_MASK_LEN & wpset) != 0) && (lulen != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSELen))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_MIN & wpset) != 0) && (lulen < pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMin))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_MAX & wpset) != 0) && (lulen > pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMax))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_STR & wpset) != 0) && (cmpres != PR_EQUAL)) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_HEAD & wpset) != 0) && !(picokpr_isEqualHead(with__0->rnetwork,lstrp,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEHead)))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_MID & wpset) != 0) && !(picokpr_isEqualMid(with__0->rnetwork,lstrp,PR_MAX_DATA_LEN ,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMid)))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_TAIL & wpset) != 0) && !(picokpr_isEqualTail(with__0->rnetwork,lstrp,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSETail)))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_ID & wpset) != 0) && (pr->ritems[with__0->ritemid+1]->head.info2 != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEID))) { + return PR_MSNotMatched; + } + return PR_MSMatched; +} + + +static pr_MatchState pr_matchTokensChar (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_int32 cmpres, + picokpr_TokSetNP npset, picokpr_TokSetWP wpset) +{ + register struct pr_PathEle * with__0; + + with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; + + if (!((PR_TSE_MASK_CHAR & npset) != 0)) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_STR & wpset) != 0) && (cmpres != PR_EQUAL)) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_ID & wpset) != 0) && (pr->ritems[with__0->ritemid+1]->head.info2 != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEID))) { + return PR_MSNotMatched; + } + return PR_MSMatched; +} + + +static pr_MatchState pr_matchTokensLetter (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_int32 cmpres, + picokpr_TokSetNP npset, picokpr_TokSetWP wpset) +{ + + register struct pr_PathEle * with__0; + picoos_int32 lulen; + picoos_int32 lromanval; + + with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; + + if ( !((PR_TSE_MASK_LETTER & npset) != 0)) { + return PR_MSNotMatched; + } + lulen = picobase_utf8_length(pr->ritems[with__0->ritemid+1]->data, PR_MAX_DATA_LEN); + if (((PR_TSE_MASK_LEN & wpset) != 0) && (lulen != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSELen))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_MIN & wpset) != 0) && (lulen < pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMin))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_MAX & wpset) != 0) && (lulen > pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMax))) { + return PR_MSNotMatched; + } + if ((PR_TSE_MASK_CI & npset) != 0) { + if (((PR_TSE_MASK_STR & wpset) != 0) && (cmpres != PR_EQUAL)) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_HEAD & wpset) != 0) && !(picokpr_isEqualHead(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->strci,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEHead)))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_MID & wpset) != 0) && !(picokpr_isEqualMid(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->strci,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMid)))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_TAIL & wpset) != 0) && !(picokpr_isEqualTail(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->strci,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSETail)))) { + return PR_MSNotMatched; + } + } else if ((PR_TSE_MASK_CIS & npset) != 0) { + if (((PR_TSE_MASK_STR & wpset) != 0) && !(picokpr_isEqual(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->strcis,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEStr)))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_HEAD & wpset) != 0) && !(picokpr_isEqualHead(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->strcis,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEHead)))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_MID & wpset) != 0) && !(picokpr_isEqualMid(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->strcis,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMid)))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_TAIL & wpset) != 0) && !(picokpr_isEqualTail(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->strcis,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSETail)))) { + return PR_MSNotMatched; + } + } else { + if (((PR_TSE_MASK_STR & wpset) != 0) && !(picokpr_isEqual(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->data,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEStr)))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_HEAD & wpset) != 0) && !(picokpr_isEqualHead(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->data,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEHead)))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_MID & wpset) != 0) && !(picokpr_isEqualMid(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->data,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEMid)))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_TAIL & wpset) != 0) && !(picokpr_isEqualTail(with__0->rnetwork,pr->ritems[with__0->ritemid+1]->data,PR_MAX_DATA_LEN,pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSETail)))) { + return PR_MSNotMatched; + } + } + if (((PR_TSE_MASK_AUC & npset) != 0) && !(pr->ritems[with__0->ritemid+1]->auc)) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_ALC & npset) != 0) && !(pr->ritems[with__0->ritemid+1]->alc)) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_SUC & npset) != 0) && !(pr->ritems[with__0->ritemid+1]->suc)) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_ROMAN & npset) != 0) && !(pr_isLatinNumber(pr->ritems[with__0->ritemid+1]->data,& lromanval))) { + return PR_MSNotMatched; + } + if (((PR_TSE_MASK_ID & wpset) != 0) && (pr->ritems[with__0->ritemid+1]->head.info2 != pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEID))) { + return PR_MSNotMatched; + } + return PR_MSMatched; +} + + +static pr_MatchState pr_matchTokensBegin (picodata_ProcessingUnit this, pr_subobj_t * pr, + picokpr_TokSetNP npset, picokpr_TokSetWP wpset) +{ + npset = npset; /* avoid warning "var not used in this function"*/ + wpset = wpset; /* avoid warning "var not used in this function"*/ + if ((PR_TSE_MASK_BEGIN &picokpr_getTokSetNP(pr->ractpath.rele[pr->ractpath.rlen - 1].rnetwork, pr->ractpath.rele[pr->ractpath.rlen - 1].rtok)) != 0) { + return PR_MSMatched; + } else { + return PR_MSNotMatched; + } +} + + + +static pr_MatchState pr_matchTokensEnd (picodata_ProcessingUnit this, pr_subobj_t * pr, + picokpr_TokSetNP npset, picokpr_TokSetWP wpset) +{ + npset = npset; /* avoid warning "var not used in this function"*/ + wpset = wpset; /* avoid warning "var not used in this function"*/ + if ((PR_TSE_MASK_END &picokpr_getTokSetNP(pr->ractpath.rele[pr->ractpath.rlen - 1].rnetwork, pr->ractpath.rele[pr->ractpath.rlen - 1].rtok)) != 0) { + return PR_MSMatched; + } else { + return PR_MSNotMatched; + } +} + + +static pr_MatchState pr_matchTokens (picodata_ProcessingUnit this, pr_subobj_t * pr, picoos_int16 * cmpres) +{ + + register struct pr_PathEle * with__0; + picokpr_VarStrPtr lstrp; + picokpr_TokSetNP npset; + picokpr_TokSetWP wpset; + + with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; + npset = picokpr_getTokSetNP(with__0->rnetwork, with__0->rtok); + wpset = picokpr_getTokSetWP(with__0->rnetwork, with__0->rtok); + + *cmpres = PR_EQUAL; + if ((PR_TSE_MASK_STR & wpset) != 0) { + lstrp = picokpr_getVarStrPtr(with__0->rnetwork, pr_attrVal(with__0->rnetwork, with__0->rtok, PR_TSEStr)); + pr_compare(pr->ritems[with__0->ritemid+1]->strci,lstrp,cmpres); + } + if (((PR_TSE_MASK_LEX & wpset) == PR_TSE_MASK_LEX) && ((PR_TSE_MASK_LETTER & npset) == 0)) { + return pr_matchMultiToken(this, pr, npset, wpset); + } else { + switch (pr->ritems[with__0->ritemid+1]->head.info1) { + case PICODATA_ITEMINFO1_TOKTYPE_BEGIN: + return pr_matchTokensBegin(this, pr, npset, wpset); + break; + case PICODATA_ITEMINFO1_TOKTYPE_END: + return pr_matchTokensEnd(this, pr, npset, wpset); + break; + case PICODATA_ITEMINFO1_TOKTYPE_SPACE: + return pr_matchTokensSpace(this, pr, *cmpres, npset, wpset); + break; + case PICODATA_ITEMINFO1_TOKTYPE_DIGIT: + return pr_matchTokensDigit(this, pr, *cmpres, npset, wpset); + break; + case PICODATA_ITEMINFO1_TOKTYPE_LETTER: + return pr_matchTokensLetter(this, pr, *cmpres, npset, wpset); + break; + case PICODATA_ITEMINFO1_TOKTYPE_SEQ: + return pr_matchTokensSeq(this, pr, *cmpres, npset, wpset); + break; + case PICODATA_ITEMINFO1_TOKTYPE_CHAR: + return pr_matchTokensChar(this, pr, *cmpres, npset, wpset); + break; + default: + PICODBG_INFO(("pr_matchTokens: unknown token type")); + return PR_MSNotMatched; + break; + } + } +} + + +static void pr_calcPathCost (struct pr_Path * path) +{ + picoos_int32 li; + picoos_bool lfirst; + picokpr_TokSetWP wpset; + picokpr_TokSetNP npset; +#if PR_TRACE_PATHCOST + picoos_uchar str[1000]; + picoos_uchar * strp; +#endif + +#if PR_TRACE_PATHCOST + str[0] = 0; +#endif + + lfirst = TRUE; + path->rcost = PR_COST_INIT; + for (li = 0; li < path->rlen; li++) { + if (li == 0) { + path->rcost = path->rcost + path->rele[li].rprodprefcost; + } + wpset = picokpr_getTokSetWP(path->rele[li].rnetwork, path->rele[li].rtok); + npset = picokpr_getTokSetNP(path->rele[li].rnetwork, path->rele[li].rtok); + if ((PR_TSE_MASK_COST & wpset) != 0) { + if (((PR_TSE_MASK_LEX & wpset) == PR_TSE_MASK_LEX) && ((PR_TSE_MASK_LETTER & npset) == 0)) { + if (lfirst) { + path->rcost = path->rcost - PR_COST + pr_attrVal(path->rele[li].rnetwork, path->rele[li].rtok, PR_TSECost); + } else { + path->rcost = path->rcost - PR_COST; + } + lfirst = FALSE; + } else { + path->rcost = path->rcost - PR_COST + pr_attrVal(path->rele[li].rnetwork, path->rele[li].rtok, PR_TSECost); + lfirst = TRUE; + } + } else if (pr_hasToken(& wpset,& npset)) { + path->rcost = path->rcost - PR_COST; + } +#if PR_TRACE_PATHCOST + if ((path->rele[li].rprodname != 0)) { + strp = picokpr_getVarStrPtr(path->rele[li].rnetwork, path->rele[li].rprodname); + picoos_strcat(str, (picoos_char *)" "); + picoos_strcat(str, strp); + } +#endif + } +#if PR_TRACE_PATHCOST + PICODBG_INFO(("pp cost: %i %s", path->rcost, str)); +#endif +} + + +void pr_processToken (picodata_ProcessingUnit this, pr_subobj_t * pr) +{ + register struct pr_PathEle * with__0; + picoos_bool ldummy; + picoos_int32 li; + picokpr_TokSetNP npset; + picokpr_TokSetWP wpset; + + do { + pr->rgState = PR_GSContinue; + if ((pr->ractpath.rlen == 0)) { + if (pr_getTopLevelToken(this, pr, FALSE)) { + pr->rgState = PR_GSContinue; + } else if (pr->rbestpath.rlen == 0) { + pr->rgState = PR_GSNotFound; + } else { + pr->rgState = PR_GSFound; + } + } else { + if (pr->maxPathLen < pr->ractpath.rlen) { + pr->maxPathLen = pr->ractpath.rlen; + } + with__0 = & pr->ractpath.rele[pr->ractpath.rlen - 1]; + switch (with__0->rlState) { + case PR_LSInit: + npset = picokpr_getTokSetNP(with__0->rnetwork, with__0->rtok); + wpset = picokpr_getTokSetWP(with__0->rnetwork, with__0->rtok); + if ((PR_TSE_MASK_ACCEPT & npset) != 0){ + if (with__0->rdepth == 1) { + pr_calcPathCost(&pr->ractpath); + if ((pr->rbestpath.rlen == 0) || (pr->ractpath.rcost < pr->rbestpath.rcost)) { + pr->rbestpath.rlen = pr->ractpath.rlen; + pr->rbestpath.rcost = pr->ractpath.rcost; + for (li = 0; li < pr->ractpath.rlen; li++) { + pr->rbestpath.rele[li] = pr->ractpath.rele[li]; + } + } + with__0->rlState = PR_LSGetNextToken; + } else { + with__0->rlState = PR_LSGetProdContToken; + } + } else if ((PR_TSE_MASK_PROD & wpset) != 0) { + with__0->rlState = PR_LSGetProdToken; + } else if ((PR_TSE_MASK_OUT & wpset) != 0) { + with__0->rlState = PR_LSGetNextToken; + } else if (pr_hasToken(& wpset,& npset)) { + with__0->rlState = PR_LSGetToken; + } else { + with__0->rlState = PR_LSGetNextToken; + } + break; + case PR_LSGetProdToken: + with__0->rlState = PR_LSGetAltToken; + ldummy = pr_getProdToken(this, pr); + break; + case PR_LSGetProdContToken: + with__0->rlState = PR_LSGetAltToken; + ldummy = pr_getProdContToken(this, pr); + break; + case PR_LSGoBack: + pr->ractpath.rlen--; + break; + case PR_LSGetToken: + if (pr_getToken(this, pr)) { + with__0->rlState = PR_LSMatch; + } else if (pr->forceOutput) { + with__0->rlState = PR_LSGetAltToken; + } else { + with__0->rlState = PR_LSGetToken2; + pr->rgState = PR_GSNeedToken; + } + break; + case PR_LSGetToken2: + if (pr_getToken(this, pr)) { + with__0->rlState = PR_LSMatch; + } else { + with__0->rlState = PR_LSGoBack; + } + break; + case PR_LSMatch: + switch (pr_matchTokens(this, pr, & with__0->rcompare)) { + case PR_MSMatched: + with__0->rlState = PR_LSGetNextToken; + break; + case PR_MSMatchedContinue: + with__0->rlState = PR_LSGetAltToken; + ldummy = pr_getNextMultiToken(this, pr); + break; + case PR_MSMatchedMulti: + with__0->rlState = PR_LSGetNextToken; + ldummy = pr_getNextMultiToken(this, pr); + break; + default: + with__0->rlState = PR_LSGetAltToken; + break; + } + break; + case PR_LSGetNextToken: + with__0->rlState = PR_LSGetAltToken; + ldummy = pr_getNextToken(this, pr); + break; + case PR_LSGetAltToken: + with__0->rlState = PR_LSGoBack; + ldummy = pr_getAltToken(this, pr); + break; + default: + PICODBG_INFO(("unhandled local state")); + break; + } + } + pr->nrIterations--; + } while ((pr->rgState == PR_GSContinue) && (pr->nrIterations > 0)); +} + + +void pr_process (picodata_ProcessingUnit this, pr_subobj_t * pr) +{ + switch (pr->rgState) { + case PR_GS_START: + case PR_GSFound: + case PR_GSNotFound: + pr->ractpath.rlen = 0; + pr->ractpath.rcost = PR_COST_INIT; + pr->rbestpath.rlen = 0; + pr->rbestpath.rcost = PR_COST_INIT; + if (pr_getTopLevelToken(this, pr, TRUE)) { + pr->rgState = PR_GSContinue; + } else { + pr->rgState = PR_GSNotFound; + } + break; + case PR_GSContinue: + pr_processToken(this, pr); + break; + case PR_GSNeedToken: + pr->rgState = PR_GSContinue; + break; + default: + pr->rgState = PR_GS_START; + break; + } +} + + +static void pr_prepareItem (picodata_ProcessingUnit this, pr_subobj_t * pr, pr_ioItemPtr item) +{ + pr->ritems[pr->rnritems + 1] = item; + pr->rnritems++; +} + + +static void pr_processItems (picodata_ProcessingUnit this, pr_subobj_t * pr) +{ + pr_ioItemPtr lit; + pr_MemState lmemState; + + pr_getMemState(this, pr_WorkMem,& lmemState); + + while ((pr->rinItemList != NULL) && (pr->rinItemList->head.type != PICODATA_ITEM_TOKEN)) { + lit = pr->rinItemList; + PICODBG_INFO(("pp in (0)")); + PICODBG_INFO(("pp out(0)")); + pr->rinItemList = pr->rinItemList->next; + lit->next = NULL; + if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PHONEME) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_START)) { + pr->insidePhoneme = TRUE; + } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PHONEME) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_END)) { + pr->insidePhoneme = FALSE; + } + if (pr->insidePhoneme && (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PLAY) || pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_IGNSIG))) { + pr_disposeItem(this, & lit); + } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_CONTEXT)) { + pr_setContext(this, pr, lit->data); + pr_disposeItem(this, & lit); + } else if (pr->rignore <= 0) { + pr_appendItemToOutItemList(this, pr, & pr->routItemList,& pr->rlastOutItem,lit); + if (pr->outOfMemory) return; + } else { + pr_disposeItem(this, & lit); + } + pr->rgState = PR_GS_START; + } + if (pr->rinItemList != NULL) { + pr_process(this, pr); + if (pr->rgState == PR_GSNotFound) { + lit = pr->rinItemList; + pr->rinItemList = pr->rinItemList->next; + lit->next = NULL; + PICODBG_INFO(("pp in (2): '%s'", lit->data)); + if (pr->rignore <= 0) { + PICODBG_INFO(("pp out(2): '%s'", lit->data)); + } + + if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PHONEME) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_START)) { + pr->insidePhoneme = TRUE; + } else if (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PHONEME) && pr_isCmdInfo2(lit, PICODATA_ITEMINFO2_CMD_END)) { + pr->insidePhoneme = FALSE; + } + if (((pr->rignore <= 0) && !((pr->insidePhoneme && (pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_PLAY) || pr_isCmdType(lit,PICODATA_ITEMINFO1_CMD_IGNSIG)))))) { + pr_appendItemToOutItemList(this, pr, & pr->routItemList,& pr->rlastOutItem,lit); + if (pr->outOfMemory) return; + } else { + pr_disposeItem(this, & lit); + } + pr->rgState = PR_GS_START; + pr->rnritems = 0; + } else if (pr->rgState == PR_GSFound) { + pr_outputPath(this, pr); + if (pr->outOfMemory) return; + pr->rgState = PR_GS_START; + pr->rnritems = 0; + } + } + if (pr->rinItemList == NULL) { + pr->rlastInItem = NULL; + } else if (pr->rnritems == 0) { + lit = pr->rinItemList; + while (lit != NULL) { + if (lit->head.type == PICODATA_ITEM_TOKEN) { + pr_prepareItem(this, pr, lit); + } + lit = lit->next; + } + } + pr_resetMemState(this, pr_WorkMem,lmemState); +} + + + +extern void pr_treatItem (picodata_ProcessingUnit this, pr_subobj_t * pr, pr_ioItemPtr item) +{ + pr_ioItemPtr lit; + + pr_startItemList(& pr->routItemList,& pr->rlastOutItem); + + if (!PR_ENABLED || (pr->rgState == PR_GSNoPreproc)) { + /* preprocessing disabled or no preproc networks available: + append items directly to output item list */ + PICODBG_INFO(("pp in (3): '%s'", item->data)); + PICODBG_INFO(("pp out(3): '%s'", item->data)); + pr_appendItemToOutItemList(this, pr, & pr->routItemList,& pr->rlastOutItem,item); + } else { + + if (pr->actCtxChanged) { + pr->rgState = PR_GS_START; + pr->ractpath.rcost = PR_COST_INIT; + pr->ractpath.rlen = 0; + pr->rbestpath.rcost = PR_COST_INIT; + pr->rbestpath.rlen = 0; + pr->prodList = NULL; + pr->rnritems = 0; + pr->actCtxChanged = FALSE; + } + if (pr_isCmdType(item , PICODATA_ITEMINFO1_CMD_CONTEXT) || pr_isCmdType(item, PICODATA_ITEMINFO1_CMD_FLUSH)) { + /* context switch or flush: force processing and empty input item list */ + pr->forceOutput = TRUE; + } + pr_appendItem(this, & pr->rinItemList,& pr->rlastInItem, item); + if (pr->rnritems == 0) { + lit = pr->rinItemList; + while (lit != NULL) { + if (lit->head.type == PICODATA_ITEM_TOKEN) { + pr_prepareItem(this, pr, lit); + } + lit = lit->next; + } + } else if (item->head.type == PICODATA_ITEM_TOKEN) { + pr_prepareItem(this, pr, item); + } + } +} + +/* *****************************************************************************/ +/* *****************************************************************************/ +/* *****************************************************************************/ + + +pico_status_t prReset(register picodata_ProcessingUnit this) +{ + picoos_int32 i; + pr_subobj_t * pr; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pr = (pr_subobj_t *) this->subObj; + + pr->rinItemList = NULL; + pr->rlastInItem = NULL; + pr->routItemList = NULL; + pr->rlastOutItem = NULL; + pr->ractpath.rcost = PR_COST_INIT; + pr->ractpath.rlen = 0; + pr->rbestpath.rcost = PR_COST_INIT; + pr->rbestpath.rlen = 0; + pr->rnritems = 0; + pr->ritems[0] = NULL; + pr->rignore = 0; + pr->spellMode = 0; + pr->maxPathLen = 0; + pr->insidePhoneme = FALSE; + pr->saveFile[0] = 0; + + pr->outReadPos = 0; + pr->outWritePos = 0; + pr->inBufLen = 0; + + pr->rgState = PR_GSNoPreproc; + for (i=0; ipreproc[i] != NULL) { + pr->rgState = PR_GS_START; + } + } + pr->actCtx = pr_findContext(pr->ctxList, (picoos_uchar*)PICO_CONTEXT_DEFAULT); + pr->actCtxChanged = FALSE; + pr->prodList = NULL; + + if (((picoos_uint32)pr->pr_WorkMem % PICOOS_ALIGN_SIZE) == 0) { + pr->workMemTop = 0; + } + else { + pr->workMemTop = PICOOS_ALIGN_SIZE - ((picoos_uint32)pr->pr_WorkMem % PICOOS_ALIGN_SIZE); + } + pr->maxWorkMemTop=0; + pr->dynMemSize=0; + pr->maxDynMemSize=0; + /* this is ok to be in 'initialize' because it is a private memory within pr. Creating a new mm + * here amounts to resetting this internal memory + */ + pr->dynMemMM = picoos_newMemoryManager((void *)pr->pr_DynMem, PR_DYN_MEM_SIZE, + /*enableMemProt*/ FALSE); + pr->outOfMemory = FALSE; + + pr->forceOutput = FALSE; + + + pr->xsampa_parser = picokfst_getFST(this->voice->kbArray[PICOKNOW_KBID_FST_XSAMPA_PARSE]); + + pr->svoxpa_parser = picokfst_getFST(this->voice->kbArray[PICOKNOW_KBID_FST_SVOXPA_PARSE]); + + pr->xsampa2svoxpa_mapper = picokfst_getFST(this->voice->kbArray[PICOKNOW_KBID_FST_XSAMPA2SVOXPA]); + + + + return PICO_OK; +} + + +pico_status_t prInitialize(register picodata_ProcessingUnit this) +{ +/* + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } +*/ + return prReset(this); +} + + +pico_status_t prTerminate(register picodata_ProcessingUnit this) +{ + return PICO_OK; +} + +picodata_step_result_t prStep(register picodata_ProcessingUnit this, picoos_int16 mode, picoos_uint16 * numBytesOutput); + +pico_status_t prSubObjDeallocate(register picodata_ProcessingUnit this, + picoos_MemoryManager mm) +{ + pr_subobj_t * pr; + + if (NULL != this) { + pr = (pr_subobj_t *) this->subObj; + mm = mm; /* avoid warning "var not used in this function"*/ + PICODBG_INFO(("max pr_WorkMem: %i of %i", pr->maxWorkMemTop, PR_WORK_MEM_SIZE)); + PICODBG_INFO(("max pr_DynMem: %i of %i", pr->maxDynMemSize, PR_DYN_MEM_SIZE)); + + pr_disposeContextList(this); + picoos_deallocate(this->common->mm, (void *) &this->subObj); + } + return PICO_OK; +} + +picodata_ProcessingUnit picopr_newPreprocUnit(picoos_MemoryManager mm, picoos_Common common, + picodata_CharBuffer cbIn, picodata_CharBuffer cbOut, + picorsrc_Voice voice) +{ + picoos_int32 i; + pr_subobj_t * pr; + + + picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, cbOut, voice); + if (this == NULL) { + return NULL; + } + + this->initialize = prInitialize; + PICODBG_DEBUG(("set this->step to prStep")); + this->step = prStep; + this->terminate = prTerminate; + this->subDeallocate = prSubObjDeallocate; + this->subObj = picoos_allocate(mm, sizeof(pr_subobj_t)); +#if PR_TRACE_MEM || PR_TRACE_MAX_MEM + PICODBG_INFO(("preproc alloc: %i", sizeof(pr_subobj_t))); + PICODBG_INFO(("max dyn size: %i", PR_MAX_PATH_LEN*((((PR_IOITEM_MIN_SIZE+2) + PICOOS_ALIGN_SIZE - 1) / PICOOS_ALIGN_SIZE) * PICOOS_ALIGN_SIZE + 16))); +#endif + if (this->subObj == NULL) { + picoos_deallocate(mm, (void *)&this); + return NULL; + } + pr = (pr_subobj_t *) this->subObj; + + pr->graphs = picoktab_getGraphs(this->voice->kbArray[PICOKNOW_KBID_TAB_GRAPHS]); + pr->preproc[0] = picokpr_getPreproc(this->voice->kbArray[PICOKNOW_KBID_TPP_MAIN]); + for (i=0; ipreproc[1+i] = picokpr_getPreproc(this->voice->kbArray[PICOKNOW_KBID_TPP_USER_1+i]); + } + + if (pr_createContextList(this) != PICO_OK) { + pr_disposeContextList(this); + picoos_deallocate(mm, (void *)&this); + return NULL; + } + prInitialize(this); + return this; +} + +/** + * fill up internal buffer + */ +picodata_step_result_t prStep(register picodata_ProcessingUnit this, + picoos_int16 mode, picoos_uint16 * numBytesOutput) +{ + register pr_subobj_t * pr; + pr_ioItemPtr it; + picoos_int32 len, i; + pico_status_t rv; + picoos_int32 id; + picoos_uint8 info1; + picoos_uint8 info2; + picoos_int32 nrUtfChars; + picoos_uint32 pos; + picobase_utf8char inUtf8char, outUtf8char; + picoos_int32 inUtf8charlen, outUtf8charlen; + picoos_int32 lenpos; + picoos_bool ldone; + picoos_bool split; + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pr = (pr_subobj_t *) this->subObj; + + if (pr->outOfMemory) return PICODATA_PU_ERROR; + + mode = mode; /* avoid warning "var not used in this function"*/ + pr->nrIterations = PR_MAX_NR_ITERATIONS; + + *numBytesOutput = 0; + while (1) { /* exit via return */ + if ((pr->outWritePos - pr->outReadPos) > 0) { + /* deliver the data in the output buffer */ + if (picodata_cbPutItem(this->cbOut, &pr->outBuf[pr->outReadPos], pr->outWritePos - pr->outReadPos, numBytesOutput) == PICO_OK) { + pr->outReadPos += *numBytesOutput; + if (pr->outWritePos == pr->outReadPos) { + pr->outWritePos = 0; + pr->outReadPos = 0; + } + } + else { + return PICODATA_PU_OUT_FULL; + } + } + else if (pr->routItemList != NULL) { + /* there are item(s) in the output item list, move them to the output buffer */ + it = pr->routItemList; + pr->routItemList = pr->routItemList->next; + if (pr->routItemList == NULL) { + pr->rlastOutItem = NULL; + } + if (it->head.type == PICODATA_ITEM_TOKEN) { + if ((it->head.info1 != PICODATA_ITEMINFO1_TOKTYPE_SPACE) && (it->head.len > 0)) { + nrUtfChars = picobase_utf8_length(it->data, PR_MAX_DATA_LEN); + if ((nrUtfChars == 1) + && (((id = picoktab_graphOffset(pr->graphs, it->data)) > 0)) + && picoktab_getIntPropPunct(pr->graphs, id, &info1, &info2)) { + /* single punctuation chars have to be delivered as PICODATA_ITEM_PUNC items + instead as PICODATA_ITEM_WORDGRAPH items */ + pr->outBuf[pr->outWritePos++] = PICODATA_ITEM_PUNC; + pr->outBuf[pr->outWritePos++] = info1; + pr->outBuf[pr->outWritePos++] = info2; + pr->outBuf[pr->outWritePos++] = 0; + PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], + (picoos_uint8 *)"pr: ", pr->outBuf, pr->outWritePos); + } + else { + /* do subgraphs substitutions and deliver token items as PICODATA_ITEM_WORDGRAPH + items to the output buffer */ + split = FALSE; + pr->outBuf[pr->outWritePos++] = PICODATA_ITEM_WORDGRAPH; + pr->outBuf[pr->outWritePos++] = PICODATA_ITEMINFO1_NA; + pr->outBuf[pr->outWritePos++] = PICODATA_ITEMINFO2_NA; + lenpos=pr->outWritePos; + pr->outBuf[pr->outWritePos++] = 0; + pos = 0; + len = pr_strlen(it->data); + while (pos < (picoos_uint32)len) { + if (picobase_get_next_utf8char(it->data, it->head.len, &pos, inUtf8char)) { + if (inUtf8char[0] <= 32) { + /* do not add whitespace characters to the output buffer, + but initiate token splitting instead + + */ + split = TRUE; + } + else if (((id = picoktab_graphOffset(pr->graphs, inUtf8char)) > 0) && picoktab_getStrPropGraphsubs1(pr->graphs, id, outUtf8char)) { + if (split) { + /* split the token, eg. start a new item */ + pr->outBuf[pr->outWritePos++] = PICODATA_ITEM_WORDGRAPH; + pr->outBuf[pr->outWritePos++] = PICODATA_ITEMINFO1_NA; + pr->outBuf[pr->outWritePos++] = PICODATA_ITEMINFO2_NA; + lenpos=pr->outWritePos; + pr->outBuf[pr->outWritePos++] = 0; + } + outUtf8charlen = picobase_det_utf8_length(outUtf8char[0]); + for (i=0; ioutBuf[pr->outWritePos++] = outUtf8char[i]; + pr->outBuf[lenpos]++; + } + if (picoktab_getStrPropGraphsubs2(pr->graphs, id, outUtf8char)) { + outUtf8charlen = picobase_det_utf8_length(outUtf8char[0]); + for (i=0; ioutBuf[pr->outWritePos++] = outUtf8char[i]; + pr->outBuf[lenpos]++; + } + } + split = FALSE; + } + else { + if (split) { + /* split the token, eg. start a new item */ + pr->outBuf[pr->outWritePos++] = PICODATA_ITEM_WORDGRAPH; + pr->outBuf[pr->outWritePos++] = PICODATA_ITEMINFO1_NA; + pr->outBuf[pr->outWritePos++] = PICODATA_ITEMINFO2_NA; + lenpos=pr->outWritePos; + pr->outBuf[pr->outWritePos++] = 0; + } + inUtf8charlen = picobase_det_utf8_length(inUtf8char[0]); + for (i=0; ioutBuf[pr->outWritePos++] = inUtf8char[i]; + pr->outBuf[lenpos]++; + } + split = FALSE; + } + } + } + PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], + (picoos_uint8 *)"pr: ", pr->outBuf, pr->outWritePos); + } + } + } + else { + /* handle all other item types and put them to the output buffer */ + pr->outBuf[pr->outWritePos++] = it->head.type; + pr->outBuf[pr->outWritePos++] = it->head.info1; + pr->outBuf[pr->outWritePos++] = it->head.info2; + pr->outBuf[pr->outWritePos++] = it->head.len; + for (i=0; ihead.len; i++) { + pr->outBuf[pr->outWritePos++] = it->data[i]; + } + PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], + (picoos_uint8 *)"pr: ", pr->outBuf, pr->outWritePos); + } + pr_disposeItem(this, &it); + } + else if (pr->forceOutput) { + pr_processItems(this, pr); + if (pr->rinItemList == NULL) { + pr->forceOutput = FALSE; + } + } + else if ((pr->rgState != PR_GSNeedToken) && (pr->rinItemList != NULL)) { + pr_processItems(this, pr); + } + else if (pr->inBufLen > 0) { + /* input data is available in the input buffer, copy it to an input item + and treat it */ + if (pr->dynMemSize < (45*PR_DYN_MEM_SIZE / 100)) { + pr_newItem(this, pr_DynMem, &it, pr->inBuf[0], pr->inBuf[3], /*inItem*/TRUE); + if (pr->outOfMemory) return PICODATA_PU_ERROR; + it->head.type = pr->inBuf[0]; + it->head.info1 = pr->inBuf[1]; + it->head.info2 = pr->inBuf[2]; + it->head.len = pr->inBuf[3]; + for (i=0; iinBuf[3]; i++) { + it->data[i] = pr->inBuf[4+i]; + } + it->data[pr->inBuf[3]] = 0; + if ((pr->inBuf[0] == PICODATA_ITEM_TOKEN) && ((pr->inBuf[1] == PICODATA_ITEMINFO1_TOKTYPE_DIGIT))) { + it->val = tok_tokenDigitStrToInt(this, pr, it->data); + } else { + it->val = 0; + } + if (pr->inBuf[0] == PICODATA_ITEM_TOKEN) { + picobase_lowercase_utf8_str(it->data,it->strci,PR_MAX_DATA_LEN, &ldone); + pr_firstLetterToLowerCase(it->data,it->strcis); + it->alc = picobase_is_utf8_lowercase(it->data,PR_MAX_DATA_LEN); + it->auc = picobase_is_utf8_uppercase(it->data,PR_MAX_DATA_LEN); + it->suc = pr_isSUC(it->data); + } + + pr_treatItem(this, pr, it); + if (pr->outOfMemory) return PICODATA_PU_ERROR; + pr_processItems(this, pr); + pr->inBufLen = 0; + } + else { + pr->forceOutput = TRUE; + } + } + else { + /* there is not data in the output buffer and there is no data in the output item list, so + check whether input data is available */ + rv = picodata_cbGetItem(this->cbIn, pr->inBuf, IN_BUF_SIZE+PICODATA_ITEM_HEADSIZE, &pr->inBufLen); + if (PICO_OK == rv) { + } else if (PICO_EOF == rv) { + /* there was no item in the char buffer */ + return PICODATA_PU_IDLE; + } else if ((PICO_EXC_BUF_UNDERFLOW == rv) || (PICO_EXC_BUF_OVERFLOW == rv)) { + pr->inBufLen = 0; + PICODBG_ERROR(("problem getting item")); + picoos_emRaiseException(this->common->em, rv, NULL, NULL); + return PICODATA_PU_ERROR; + } else { + pr->inBufLen = 0; + PICODBG_ERROR(("problem getting item, unhandled")); + picoos_emRaiseException(this->common->em, rv, NULL, NULL); + return PICODATA_PU_ERROR; + } + } +#if PR_TRACE_MEM + PICODBG_INFO(("memory: dyn=%u, work=%u", pr->dynMemSize, pr->workMemTop)); +#endif + if (pr->nrIterations <= 0) { + return PICODATA_PU_BUSY; + } + } /* while */ + return PICODATA_PU_ERROR; +} + +#ifdef __cplusplus +} +#endif + + + +/* end */ diff --git a/pico/lib/picopr.h b/pico/lib/picopr.h new file mode 100644 index 0000000..3ade5c9 --- /dev/null +++ b/pico/lib/picopr.h @@ -0,0 +1,63 @@ +/* + * 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 picopr.h + * + * text preprocessor PU - include file + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +/** + * @addtogroup picopr + * + * Text Pre Processing module \n + * +*/ +#ifndef PICOPR_H_ +#define PICOPR_H_ + +#include "picoos.h" +#include "picodata.h" +#include "picorsrc.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +picodata_ProcessingUnit picopr_newPreprocUnit( + picoos_MemoryManager mm, + picoos_Common common, + picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, + picorsrc_Voice voice); + +#define PICOPR_OUTBUF_SIZE 256 + +#ifdef __cplusplus +} +#endif + + +#endif /*PICOPR_H_*/ diff --git a/pico/lib/picorsrc.c b/pico/lib/picorsrc.c new file mode 100644 index 0000000..d6e1e51 --- /dev/null +++ b/pico/lib/picorsrc.c @@ -0,0 +1,1028 @@ +/* + * 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 picorsrc.c + * + * 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" + +/* knowledge layer */ +#include "picoknow.h" + +#include "picokdt.h" +#include "picoklex.h" +#include "picokfst.h" +#include "picokpdf.h" +#include "picoktab.h" +#include "picokpr.h" + +#include "picorsrc.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +#if defined(PICO_DEBUG) +#include "picokdbg.h" +#endif + + +/** object : Resource + * shortcut : rsrc + * + */ +typedef struct picorsrc_resource { + picoos_uint32 magic; /* magic number used to validate handles */ + /* next connects all active resources of a resource manager and the garbaged resources of the manager's free list */ + picorsrc_Resource next; + picorsrc_resource_type_t type; + picorsrc_resource_name_t name; + picoos_int8 lockCount; /* count of current subscribers of this resource */ + picoos_File file; + picoos_uint8 * raw_mem; /* pointer to allocated memory. NULL if preallocated. */ + /* picoos_uint32 size; */ + picoos_uint8 * start; /* start of content (after header) */ + picoknow_KnowledgeBase kbList; +} picorsrc_resource_t; + + +#define MAGIC_MASK 0x7049634F /* pIcO */ + +#define SET_MAGIC_NUMBER(res) \ + (res)->magic = ((picoos_uint32) (res)) ^ MAGIC_MASK + +#define CHECK_MAGIC_NUMBER(res) \ + ((res)->magic == (((picoos_uint32) (res)) ^ MAGIC_MASK)) + + + +/** + * Returns non-zero if 'this' is a valid resource handle, zero otherwise. + */ +picoos_int16 picoctrl_isValidResourceHandle(picorsrc_Resource this) +{ + return (this != NULL) && CHECK_MAGIC_NUMBER(this); +} + + +static picorsrc_Resource picorsrc_newResource(picoos_MemoryManager mm) +{ + picorsrc_Resource this = picoos_allocate(mm, sizeof(*this)); + if (NULL != this) { + SET_MAGIC_NUMBER(this); + /* initialize */ + this->name[0] = NULLC; + /* picoos_strlcpy(this->name, name,PICORSRC_MAX_RSRC_NAME_SIZ); */ + this->next = NULL; + this->type = PICORSRC_TYPE_NULL; + this->lockCount = 0; + this->file = NULL; + this->raw_mem = NULL; + this->start = NULL; + this->kbList = NULL; + /* this->size=0; */ + } + return this; +} + +static void picorsrc_disposeResource(picoos_MemoryManager mm, picorsrc_Resource * this) +{ + if (NULL != (*this)) { + (*this)->magic ^= 0xFFFEFDFC; + /* we have to explicitly free 'raw_mem' here because in testing + scenarios (where memory protection functionality is enabled) + it might be allocated aside from normal memory */ + if ((*this)->raw_mem != NULL) { + picoos_deallocProtMem(mm, (void *) &(*this)->raw_mem); + } + picoos_deallocate(mm,(void * *)this); + } +} + + + + +static void picorsrc_initializeVoice(picorsrc_Voice this) +{ + picoos_uint16 i; + if (NULL != this) { + /* initialize */ + for (i=0; ikbArray[i] = NULL; + } + this->numResources = 0; + this->next = NULL; + } +} + +static picorsrc_Voice picorsrc_newVoice(picoos_MemoryManager mm) +{ + picorsrc_Voice this = (picorsrc_Voice) picoos_allocate(mm,sizeof(*this)); + picorsrc_initializeVoice(this); + return this; +} + +/* +static void picorsrc_disposeVoice(picoos_MemoryManager mm, picorsrc_Voice * this) +{ + if (NULL != (*this)) { + + picoos_deallocate(mm,(void *)this); + } +} +*/ + + +/** object : VoiceDefinition + * shortcut : vdef + * + */ + +typedef struct picorsrc_voice_definition * picorsrc_VoiceDefinition; + +typedef struct picorsrc_voice_definition { + picoos_char voiceName[PICO_MAX_VOICE_NAME_SIZE]; + picoos_uint8 numResources; + picorsrc_resource_name_t resourceName[PICO_MAX_NUM_RSRC_PER_VOICE]; + picorsrc_VoiceDefinition next; +} picorsrc_voice_definition_t; + + +static picorsrc_VoiceDefinition picorsrc_newVoiceDefinition(picoos_MemoryManager mm) +{ + /* picoos_uint8 i; */ + picorsrc_VoiceDefinition this = (picorsrc_VoiceDefinition) picoos_allocate(mm,sizeof(*this)); + if (NULL != this) { + /* initialize */ + this->voiceName[0] = NULLC; + this->numResources = 0; + /* + for (i=0; i < PICO_MAX_NUM_RSRC_PER_VOICE; i++) { + this->resourceName[i][0] = NULLC; + } + */ + this->next = NULL; + } + return this; +} + +/* +static void picorsrc_disposeVoiceDefinition(picoos_MemoryManager mm, picorsrc_VoiceDefinition * this) +{ + if (NULL != (*this)) { + + picoos_deallocate(mm,(void *)this); + } +} +*/ + + + +/** object : ResourceManager + * shortcut : rm + * + */ +typedef struct picorsrc_resource_manager { + picoos_Common common; + picoos_uint16 numResources; + picorsrc_Resource resources, freeResources; + picoos_uint16 numVoices; + picorsrc_Voice voices, freeVoices; + picoos_uint16 numVdefs; + picorsrc_VoiceDefinition vdefs, freeVdefs; + picoos_uint16 numKbs; + picoknow_KnowledgeBase freeKbs; + picoos_header_string_t tmpHeader; +} picorsrc_resource_manager_t; + +pico_status_t picorsrc_createDefaultResource(picorsrc_ResourceManager this /*, + picorsrc_Resource * resource */); + + +picorsrc_ResourceManager picorsrc_newResourceManager(picoos_MemoryManager mm, picoos_Common common /* , picoos_char * configFile */) +{ + picorsrc_ResourceManager this = picoos_allocate(mm,sizeof(*this)); + if (NULL != this) { + /* initialize */ + this->common = common; + this->numResources = 0; + this->resources = NULL; + this->freeResources = NULL; + this->numVoices = 0; + this->voices = NULL; + this->freeVoices = NULL; + this->numVdefs = 0; + this->vdefs = NULL; + this->freeVdefs = NULL; + } + return this; +} + +void picorsrc_disposeResourceManager(picoos_MemoryManager mm, picorsrc_ResourceManager * this) +{ + if (NULL != (*this)) { + /* terminate */ + picoos_deallocate(mm,(void *)this); + } +} + + +/* ******* accessing resources **************************************/ + + +static pico_status_t findResource(picorsrc_ResourceManager this, picoos_char * resourceName, picorsrc_Resource * rsrc) { + picorsrc_Resource r; + if (NULL == this) { + return PICO_ERR_NULLPTR_ACCESS; + } + r = this->resources; + while (NULL != r && (0 != picoos_strcmp(r->name,resourceName))) { + r = r->next; + } + *rsrc = r; + return PICO_OK; +} + +static picoos_uint8 isResourceLoaded(picorsrc_ResourceManager this, picoos_char * resourceName) { + picorsrc_Resource res; + + if (PICO_OK == findResource(this, resourceName,&res)){ + return (NULL != res); + } else { + return FALSE; + } + } + +static pico_status_t parse_resource_name(picoos_char * fileName) +{ + PICODBG_DEBUG(("analysing file name %s",fileName)); + if (picoos_has_extension(fileName, + (picoos_char *)PICO_BIN_EXTENSION)) { + return PICO_OK; + } else { + return PICO_EXC_UNEXPECTED_FILE_TYPE; + } +} + + + +static pico_status_t readHeader(picorsrc_ResourceManager this, + picoos_FileHeader header, picoos_uint32 * headerlen, picoos_File file) +{ + + picoos_uint16 hdrlen1; + picoos_uint32 n; + pico_status_t status; + + + /* read PICO header */ + status = picoos_readPicoHeader(file, headerlen); + if (PICO_OK == status) { + + } else { + return picoos_emRaiseException(this->common->em,status,NULL,(picoos_char *)"problem reading file header"); + } + /* read header length (excluding length itself) */ + status = picoos_read_pi_uint16(file,&hdrlen1); + PICODBG_DEBUG(("got header size %d",hdrlen1)); + + if (PICO_OK == status) { + *headerlen += 2; + status = (hdrlen1 <= PICOOS_MAX_HEADER_STRING_LEN-1) ? PICO_OK : PICO_ERR_OTHER; + if (PICO_OK == status) { + n = hdrlen1; + if (picoos_ReadBytes(file, (picoos_uint8 *) this->tmpHeader, &n) && hdrlen1 == n) { + this->tmpHeader[hdrlen1] = NULLC; + *headerlen += hdrlen1; + PICODBG_DEBUG(("got header <%s>",this->tmpHeader)); + + status = PICO_OK; + } else { + status = PICO_ERR_OTHER; + } + } + if (PICO_OK == status) { + status = picoos_hdrParseHeader(header, this->tmpHeader); + } + } + return status; +} + +static pico_status_t picorsrc_createKnowledgeBase( + picorsrc_ResourceManager this, + picoos_uint8 * data, + picoos_uint32 size, + picoknow_kb_id_t kbid, + picoknow_KnowledgeBase * kb) +{ + (*kb) = picoknow_newKnowledgeBase(this->common->mm); + if (NULL == (*kb)) { + return PICO_EXC_OUT_OF_MEM; + } + (*kb)->base = data; + (*kb)->size = size; + (*kb)->id = kbid; + switch (kbid) { + case PICOKNOW_KBID_TPP_MAIN: + case PICOKNOW_KBID_TPP_USER_1: + case PICOKNOW_KBID_TPP_USER_2: + return picokpr_specializePreprocKnowledgeBase(*kb, this->common); + break; + case PICOKNOW_KBID_TAB_GRAPHS: + return picoktab_specializeGraphsKnowledgeBase(*kb, this->common); + break; + case PICOKNOW_KBID_TAB_PHONES: + return picoktab_specializePhonesKnowledgeBase(*kb, this->common); + break; + case PICOKNOW_KBID_TAB_POS: + return picoktab_specializePosKnowledgeBase(*kb, this->common); + break; + case PICOKNOW_KBID_FIXED_IDS: + return picoktab_specializeIdsKnowledgeBase(*kb, this->common); + break; + case PICOKNOW_KBID_LEX_MAIN: + case PICOKNOW_KBID_LEX_USER_1: + case PICOKNOW_KBID_LEX_USER_2: + return picoklex_specializeLexKnowledgeBase(*kb, this->common); + break; + case PICOKNOW_KBID_DT_POSP: + return picokdt_specializeDtKnowledgeBase(*kb, this->common, + PICOKDT_KDTTYPE_POSP); + break; + case PICOKNOW_KBID_DT_POSD: + return picokdt_specializeDtKnowledgeBase(*kb, this->common, + PICOKDT_KDTTYPE_POSD); + break; + case PICOKNOW_KBID_DT_G2P: + return picokdt_specializeDtKnowledgeBase(*kb, this->common, + PICOKDT_KDTTYPE_G2P); + break; + case PICOKNOW_KBID_DT_PHR: + return picokdt_specializeDtKnowledgeBase(*kb, this->common, + PICOKDT_KDTTYPE_PHR); + break; + case PICOKNOW_KBID_DT_ACC: + return picokdt_specializeDtKnowledgeBase(*kb, this->common, + PICOKDT_KDTTYPE_ACC); + break; + case PICOKNOW_KBID_FST_SPHO_1: + case PICOKNOW_KBID_FST_SPHO_2: + case PICOKNOW_KBID_FST_SPHO_3: + case PICOKNOW_KBID_FST_SPHO_4: + case PICOKNOW_KBID_FST_SPHO_5: + case PICOKNOW_KBID_FST_SPHO_6: + case PICOKNOW_KBID_FST_SPHO_7: + case PICOKNOW_KBID_FST_SPHO_8: + case PICOKNOW_KBID_FST_SPHO_9: + case PICOKNOW_KBID_FST_SPHO_10: + case PICOKNOW_KBID_FST_WPHO_1: + case PICOKNOW_KBID_FST_WPHO_2: + case PICOKNOW_KBID_FST_WPHO_3: + case PICOKNOW_KBID_FST_WPHO_4: + case PICOKNOW_KBID_FST_WPHO_5: + case PICOKNOW_KBID_FST_SVOXPA_PARSE: + case PICOKNOW_KBID_FST_XSAMPA_PARSE: + case PICOKNOW_KBID_FST_XSAMPA2SVOXPA: + + return picokfst_specializeFSTKnowledgeBase(*kb, this->common); + break; + + case PICOKNOW_KBID_DT_DUR: + case PICOKNOW_KBID_DT_LFZ1: + case PICOKNOW_KBID_DT_LFZ2: + case PICOKNOW_KBID_DT_LFZ3: + case PICOKNOW_KBID_DT_LFZ4: + case PICOKNOW_KBID_DT_LFZ5: + case PICOKNOW_KBID_DT_MGC1: + case PICOKNOW_KBID_DT_MGC2: + case PICOKNOW_KBID_DT_MGC3: + case PICOKNOW_KBID_DT_MGC4: + case PICOKNOW_KBID_DT_MGC5: + return picokdt_specializeDtKnowledgeBase(*kb, this->common, + PICOKDT_KDTTYPE_PAM); + break; + case PICOKNOW_KBID_PDF_DUR: + return picokpdf_specializePdfKnowledgeBase(*kb, this->common, + PICOKPDF_KPDFTYPE_DUR); + + break; + case PICOKNOW_KBID_PDF_LFZ: + return picokpdf_specializePdfKnowledgeBase(*kb, this->common, + PICOKPDF_KPDFTYPE_MUL); + break; + case PICOKNOW_KBID_PDF_MGC: + return picokpdf_specializePdfKnowledgeBase(*kb, this->common, + PICOKPDF_KPDFTYPE_MUL); + break; + case PICOKNOW_KBID_PDF_PHS: + return picokpdf_specializePdfKnowledgeBase(*kb, this->common, + PICOKPDF_KPDFTYPE_PHS); + break; + + + +#if defined(PICO_DEBUG) + case PICOKNOW_KBID_DBG: + return picokdbg_specializeDbgKnowledgeBase(*kb, this->common); + break; +#endif + + default: + break; + } + return PICO_OK; +} + + +static pico_status_t picorsrc_releaseKnowledgeBase( + picorsrc_ResourceManager this, + picoknow_KnowledgeBase * kb) +{ + (*kb) = NULL; + return PICO_OK; +} + +static pico_status_t picorsrc_getKbList(picorsrc_ResourceManager this, + picoos_uint8 * data, + picoos_uint32 datalen, + picoknow_KnowledgeBase * kbList) +{ + + pico_status_t status = PICO_OK; + picoos_uint32 curpos = 0, offset, size; + picoos_uint8 i, numKbs, kbid; + picoos_char str[PICOKNOW_MAX_KB_NAME_SIZ]; + picoknow_KnowledgeBase kb; + + *kbList = NULL; + datalen = datalen; + /* read number of fields */ + numKbs = data[curpos++]; + PICODBG_DEBUG(("number of kbs (unrestricted) = %i",numKbs)); + status = (numKbs <= PICOKNOW_MAX_NUM_RESOURCE_KBS) ? PICO_OK : PICO_EXC_FILE_CORRUPT; + /* read in all kb names */ + PICODBG_DEBUG(("number of kbs = %i",numKbs)); + i = 0; + while ((PICO_OK == status) && (i++ < numKbs)) { + status = (picoos_get_str((picoos_char *)data,&curpos,str,PICOOS_MAX_FIELD_STRING_LEN)) ? PICO_OK : PICO_EXC_FILE_CORRUPT; + PICODBG_DEBUG(("contains knowledge base %s (status: %i)",str, status)); + } + /* consume termination of last str */ + curpos++; + i = 0; + while ((PICO_OK == status) && (i++ < numKbs)) { + kbid = data[curpos++]; + PICODBG_DEBUG(("got kb id %i, curpos now %i",kbid, curpos)); + status = picoos_read_mem_pi_uint32(data,&curpos,&offset); + PICODBG_DEBUG(("got kb offset %i, curpos now %i",offset, curpos)); + status = picoos_read_mem_pi_uint32(data,&curpos,&size); + PICODBG_DEBUG(("got kb size %i, curpos now %i",size, curpos)); + if (PICO_OK == status) { + if (0 == offset) { + /* currently we consider a kb mentioned in resource but with offset 0 (no knowledge) as + * different form a kb not mentioned at all. We might reconsider that later. */ + PICODBG_DEBUG((" kb (id %i) is mentioned but empty (base:%i, size:%i)",kb->id, kb->base, kb->size)); + status = picorsrc_createKnowledgeBase(this, NULL, size, (picoknow_kb_id_t)kbid, &kb); + } else { + status = picorsrc_createKnowledgeBase(this, data+offset, size, (picoknow_kb_id_t)kbid, &kb); + } + PICODBG_DEBUG(("found kb (id %i) starting at %i with size %i",kb->id, kb->base, kb->size)); + if (PICO_OK == status) { + kb->next = *kbList; + *kbList = kb; + } + } + } + if (PICO_OK != status) { + kb = *kbList; + while (NULL != kb) { + picorsrc_releaseKnowledgeBase(this,&kb); + } + } + + return status; + +} + +/* load resource file. the type of resource file etc. are in the header, + * then follows the directory, then the knowledge bases themselves (as byte streams) */ + +pico_status_t picorsrc_loadResource(picorsrc_ResourceManager this, + picoos_char * fileName, picorsrc_Resource * resource) +{ + picorsrc_Resource res; + picoos_uint32 headerlen, len,maxlen; + picoos_file_header_t header; + picoos_uint8 rem; + pico_status_t status = PICO_OK; + + if (resource == NULL) { + return PICO_ERR_NULLPTR_ACCESS; + } else { + *resource = NULL; + } + + res = picorsrc_newResource(this->common->mm); + + if (NULL == res) { + return picoos_emRaiseException(this->common->em,PICO_EXC_OUT_OF_MEM,NULL,NULL); + } + + if (PICO_MAX_NUM_RESOURCES <= this->numResources) { + picoos_deallocate(this->common->mm, (void *) &res); + return picoos_emRaiseException(this->common->em,PICO_EXC_MAX_NUM_EXCEED,NULL,(picoos_char *)"no more than %i resources",PICO_MAX_NUM_RESOURCES); + } + + /* ***************** parse file name for file type and parameters */ + + if (PICO_OK != parse_resource_name(fileName)) { + picoos_deallocate(this->common->mm, (void *) &res); + return PICO_EXC_UNEXPECTED_FILE_TYPE; + } + + /* ***************** get header info */ + + /* open binary file for reading (no key, nrOfBufs, bufSize) */ + PICODBG_DEBUG(("trying to open file %s",fileName)); + if (!picoos_OpenBinary(this->common, &res->file, fileName)) { + /* open didn't succeed */ + status = PICO_EXC_CANT_OPEN_FILE; + PICODBG_ERROR(("can't open file %s",fileName)); + picoos_emRaiseException(this->common->em, PICO_EXC_CANT_OPEN_FILE, + NULL, (picoos_char *) "%s", fileName); + } + if (PICO_OK == status) { + status = readHeader(this, &header, &headerlen, res->file); + /* res->file now positioned at first pos after header */ + } + + /* ***************** check header values */ + if (PICO_OK == status && isResourceLoaded(this, header.field[PICOOS_HEADER_NAME].value)) { + /* lingware is allready loaded, do nothing */ + PICODBG_WARN((">>> lingware '%s' allready loaded",header.field[PICOOS_HEADER_NAME].value)); + picoos_emRaiseWarning(this->common->em,PICO_WARN_RESOURCE_DOUBLE_LOAD,NULL,(picoos_char *)"%s",header.field[PICOOS_HEADER_NAME].value); + status = PICO_WARN_RESOURCE_DOUBLE_LOAD; + } + + if (PICO_OK == status) { + /* get data length */ + status = picoos_read_pi_uint32(res->file, &len); + PICODBG_DEBUG(("found net resource len of %i",len)); + /* allocate memory */ + if (PICO_OK == status) { + PICODBG_TRACE((">>> 2")); + maxlen = len + PICOOS_ALIGN_SIZE; /* once would be sufficient? */ + res->raw_mem = picoos_allocProtMem(this->common->mm, maxlen); + /* res->size = maxlen; */ + status = (NULL == res->raw_mem) ? PICO_EXC_OUT_OF_MEM : PICO_OK; + } + if (PICO_OK == status) { + rem = (picoos_uint32) res->raw_mem % PICOOS_ALIGN_SIZE; + if (rem > 0) { + res->start = res->raw_mem + (PICOOS_ALIGN_SIZE - rem); + } else { + res->start = res->raw_mem; + } + + /* read file contents into memory */ + status = (picoos_ReadBytes(res->file, res->start, &len)) ? PICO_OK + : PICO_ERR_OTHER; + /* resources are read-only; the following write protection + has an effect in test configurations only */ + picoos_protectMem(this->common->mm, res->start, len, /*enable*/TRUE); + } + /* note resource unique name */ + if (PICO_OK == status) { + if (picoos_strlcpy(res->name,header.field[PICOOS_HEADER_NAME].value,PICORSRC_MAX_RSRC_NAME_SIZ) < PICORSRC_MAX_RSRC_NAME_SIZ) { + PICODBG_DEBUG(("assigned name %s to resource",res->name)); + status = PICO_OK; + } else { + status = PICO_ERR_INDEX_OUT_OF_RANGE; + PICODBG_ERROR(("failed assigning name %s to resource", + res->name)); + picoos_emRaiseException(this->common->em, + PICO_ERR_INDEX_OUT_OF_RANGE, NULL, + (picoos_char *)"resource %s",res->name); + } + } + + /* get resource type */ + if (PICO_OK == status) { + if (!picoos_strcmp(header.field[PICOOS_HEADER_CONTENT_TYPE].value, PICORSRC_FIELD_VALUE_TEXTANA)) { + res->type = PICORSRC_TYPE_TEXTANA; + } else if (!picoos_strcmp(header.field[PICOOS_HEADER_CONTENT_TYPE].value, PICORSRC_FIELD_VALUE_SIGGEN)) { + res->type = PICORSRC_TYPE_SIGGEN; + } else if (!picoos_strcmp(header.field[PICOOS_HEADER_CONTENT_TYPE].value, PICORSRC_FIELD_VALUE_SIGGEN)) { + res->type = PICORSRC_TYPE_USER_LEX; + } else if (!picoos_strcmp(header.field[PICOOS_HEADER_CONTENT_TYPE].value, PICORSRC_FIELD_VALUE_SIGGEN)) { + res->type = PICORSRC_TYPE_USER_PREPROC; + } else { + res->type = PICORSRC_TYPE_OTHER; + } + } + + if (PICO_OK == status) { + /* create kb list from resource */ + status = picorsrc_getKbList(this, res->start, len, &res->kbList); + } + } + + if (status == PICO_OK) { + /* add resource to rm */ + res->next = this->resources; + this->resources = res; + this->numResources++; + *resource = res; + PICODBG_DEBUG(("done loading resource %s from %s", res->name, fileName)); + } else { + picorsrc_disposeResource(this->common->mm, &res); + PICODBG_ERROR(("failed to load resource")); + } + + if (status < 0) { + return status; + } else { + return PICO_OK; + } +} + +static pico_status_t picorsrc_releaseKbList(picorsrc_ResourceManager this, picoknow_KnowledgeBase * kbList) +{ + picoknow_KnowledgeBase kbprev, kb; + kb = *kbList; + while (NULL != kb) { + kbprev = kb; + kb = kb->next; + picoknow_disposeKnowledgeBase(this->common->mm,&kbprev); + } + *kbList = NULL; + return PICO_OK; +} + +/* unload resource file. (if resource file is busy, warn and don't unload) */ +pico_status_t picorsrc_unloadResource(picorsrc_ResourceManager this, picorsrc_Resource * resource) { + + picorsrc_Resource r1, r2, rsrc; + + if (resource == NULL) { + return PICO_ERR_NULLPTR_ACCESS; + } else { + rsrc = *resource; + } + + if (rsrc->lockCount > 0) { + return PICO_EXC_RESOURCE_BUSY; + } + /* terminate */ + if (rsrc->file != NULL) { + picoos_CloseBinary(this->common, &rsrc->file); + } + if (NULL != rsrc->raw_mem) { + picoos_deallocProtMem(this->common->mm, (void *) &rsrc->raw_mem); + PICODBG_DEBUG(("deallocated raw mem")); + } + + r1 = NULL; + r2 = this->resources; + while (r2 != NULL && r2 != rsrc) { + r1 = r2; + r2 = r2->next; + } + if (NULL == r1) { + this->resources = rsrc->next; + } else if (NULL == r2) { + /* didn't find resource in rm! */ + return PICO_ERR_OTHER; + } else { + r1->next = rsrc->next; + } + + if (NULL != rsrc->kbList) { + picorsrc_releaseKbList(this, &rsrc->kbList); + } + + picoos_deallocate(this->common->mm,(void **)resource); + this->numResources--; + + return PICO_OK; +} + + +pico_status_t picorsrc_createDefaultResource(picorsrc_ResourceManager this + /*, picorsrc_Resource * resource */) +{ + picorsrc_Resource res; + pico_status_t status = PICO_OK; + + + /* *resource = NULL; */ + + if (PICO_MAX_NUM_RESOURCES <= this->numResources) { + return picoos_emRaiseException(this->common->em,PICO_EXC_MAX_NUM_EXCEED,NULL,(picoos_char *)"no more than %i resources",PICO_MAX_NUM_RESOURCES); + } + + res = picorsrc_newResource(this->common->mm); + + if (NULL == res) { + return picoos_emRaiseException(this->common->em,PICO_EXC_OUT_OF_MEM,NULL,NULL); + } + + if (picoos_strlcpy(res->name,PICOKNOW_DEFAULT_RESOURCE_NAME,PICORSRC_MAX_RSRC_NAME_SIZ) < PICORSRC_MAX_RSRC_NAME_SIZ) { + PICODBG_DEBUG(("assigned name %s to default resource",res->name)); + status = PICO_OK; + } else { + PICODBG_ERROR(("failed assigning name %s to default resource",res->name)); + status = PICO_ERR_INDEX_OUT_OF_RANGE; + } + status = picorsrc_createKnowledgeBase(this, NULL, 0, (picoknow_kb_id_t)PICOKNOW_KBID_FIXED_IDS, &res->kbList); + + if (PICO_OK == status) { + res->next = this->resources; + this->resources = res; + this->numResources++; + /* *resource = res; */ + + } + + + return status; + +} + +pico_status_t picorsrc_rsrcGetName(picorsrc_Resource this, + picoos_char * name, picoos_uint32 maxlen) { + if (!picoctrl_isValidResourceHandle(this)) { + return PICO_ERR_INVALID_ARGUMENT; + } + picoos_strlcpy(name, this->name,maxlen); + return PICO_OK; +} + + +/* ******* accessing voice definitions **************************************/ + + +static pico_status_t findVoiceDefinition(picorsrc_ResourceManager this, + const picoos_char * voiceName, picorsrc_VoiceDefinition * vdef) +{ + picorsrc_VoiceDefinition v; + PICODBG_DEBUG(("finding voice name %s",voiceName)); + if (NULL == this) { + return PICO_ERR_NULLPTR_ACCESS; + } + v = this->vdefs; + while (NULL != v && (0 != picoos_strcmp(v->voiceName,voiceName))) { + PICODBG_DEBUG(("%s doesnt match",v->voiceName)); + v = v->next; + } + *vdef = v; + if (v == NULL) { + PICODBG_DEBUG(("didnt find voice name %s",voiceName)); + } else { + PICODBG_DEBUG(("found voice name %s",voiceName)); + } + return PICO_OK; +} + + +pico_status_t picorsrc_addResourceToVoiceDefinition(picorsrc_ResourceManager this, + picoos_char * voiceName, picoos_char * resourceName) +{ + picorsrc_VoiceDefinition vdef; + + if (NULL == this) { + PICODBG_ERROR(("this is NULL")); + return PICO_ERR_NULLPTR_ACCESS; + } + if ((PICO_OK == findVoiceDefinition(this,voiceName,&vdef)) && (NULL != vdef)) { + if (PICO_MAX_NUM_RSRC_PER_VOICE <= vdef->numResources) { + return picoos_emRaiseException(this->common->em,PICO_EXC_MAX_NUM_EXCEED,NULL,(picoos_char *)"no more than %i resources per voice",PICO_MAX_NUM_RSRC_PER_VOICE); + } + if (picoos_strlcpy(vdef->resourceName[vdef->numResources++], resourceName, + PICORSRC_MAX_RSRC_NAME_SIZ) < PICORSRC_MAX_RSRC_NAME_SIZ) { + PICODBG_DEBUG(("vdef added resource '%s' to voice '%s'",resourceName,voiceName)); + return PICO_OK; + } else { + PICODBG_ERROR(("illegal name (%s)",resourceName)); + return picoos_emRaiseException(this->common->em,PICO_EXC_NAME_ILLEGAL,NULL,(picoos_char *)"%s",resourceName); + } + + } else { + return picoos_emRaiseException(this->common->em,PICO_EXC_NAME_UNDEFINED,NULL,(picoos_char *)"%s",voiceName); + } +} + + +pico_status_t picorsrc_createVoiceDefinition(picorsrc_ResourceManager this, + picoos_char * voiceName) +{ + picorsrc_VoiceDefinition vdef; + + if (NULL == this) { + PICODBG_ERROR(("this is NULL")); + return PICO_ERR_NULLPTR_ACCESS; + } + if ((PICO_OK == findVoiceDefinition(this,voiceName,&vdef)) && (NULL != vdef)) { + PICODBG_ERROR(("voice %s allready defined",voiceName)); + return picoos_emRaiseException(this->common->em,PICO_EXC_NAME_CONFLICT,NULL,NULL); + } + if (PICO_MAX_NUM_VOICE_DEFINITIONS <= this->numVdefs) { + PICODBG_ERROR(("max number of vdefs exceeded (%i)",this->numVdefs)); + return picoos_emRaiseException(this->common->em,PICO_EXC_MAX_NUM_EXCEED,NULL,(picoos_char *)"no more than %i voice definitions",PICO_MAX_NUM_VOICE_DEFINITIONS); + } + if (NULL == this->freeVdefs) { + vdef = picorsrc_newVoiceDefinition(this->common->mm); + } else { + vdef = this->freeVdefs; + this->freeVdefs = vdef->next; + vdef->voiceName[0] = NULLC; + vdef->numResources = 0; + vdef->next = NULL; + } + if (NULL == vdef) { + return picoos_emRaiseException(this->common->em,PICO_EXC_OUT_OF_MEM,NULL,NULL); + } + if (picoos_strlcpy(vdef->voiceName, voiceName, + PICO_MAX_VOICE_NAME_SIZE) < PICO_MAX_VOICE_NAME_SIZE) { + vdef->next = this->vdefs; + this->vdefs = vdef; + this->numVdefs++; + if (PICO_OK != picorsrc_addResourceToVoiceDefinition(this,voiceName,PICOKNOW_DEFAULT_RESOURCE_NAME)) { + return picoos_emRaiseException(this->common->em,PICO_ERR_OTHER,NULL,(picoos_char *)"problem loading default resource %s",voiceName); + } + PICODBG_DEBUG(("vdef created (%s)",voiceName)); + return PICO_OK; + } else { + PICODBG_ERROR(("illegal name (%s)",voiceName)); + return picoos_emRaiseException(this->common->em,PICO_EXC_NAME_ILLEGAL,NULL,(picoos_char *)"%s",voiceName); + } +} + + +pico_status_t picorsrc_releaseVoiceDefinition(picorsrc_ResourceManager this, + picoos_char *voiceName) +{ + picorsrc_VoiceDefinition v, l; + + if (this == NULL) { + return PICO_ERR_NULLPTR_ACCESS; + } + + l = NULL; + v = this->vdefs; + while ((v != NULL) && (picoos_strcmp(v->voiceName, voiceName) != 0)) { + l = v; + v = v->next; + } + if (v != NULL) { + /* remove v from vdefs list */ + if (l != NULL) { + l->next = v->next; + } else { + this->vdefs = v->next; + } + /* insert v at head of freeVdefs list */ + v->next = this->freeVdefs; + this->freeVdefs = v; + this->numVdefs--; + return PICO_OK; + } else { + /* we should rather return a warning, here */ + /* return picoos_emRaiseException(this->common->em,PICO_EXC_NAME_UNDEFINED,"%s", NULL); */ + return PICO_OK; + } +} + + + +/* ******* accessing voices **************************************/ + + +/* create voice, given a voice name. the corresponding lock counts are incremented */ + +pico_status_t picorsrc_createVoice(picorsrc_ResourceManager this, const picoos_char * voiceName, picorsrc_Voice * voice) { + + picorsrc_VoiceDefinition vdef; + picorsrc_Resource rsrc; + picoos_uint8 i, required; + picoknow_KnowledgeBase kb; + /* pico_status_t status = PICO_OK; */ + + PICODBG_DEBUG(("creating voice %s",voiceName)); + + if (NULL == this) { + PICODBG_ERROR(("this is NULL")); + return PICO_ERR_NULLPTR_ACCESS; + + } + /* check number of voices */ + if (PICORSRC_MAX_NUM_VOICES <= this->numVoices) { + PICODBG_ERROR(("PICORSRC_MAX_NUM_VOICES exceeded")); + return picoos_emRaiseException(this->common->em,PICO_EXC_MAX_NUM_EXCEED,NULL,(picoos_char *)"no more than %i voices",PICORSRC_MAX_NUM_VOICES); + } + + /* find voice definition for that name */ + if (!(PICO_OK == findVoiceDefinition(this,voiceName,&vdef)) || (NULL == vdef)) { + PICODBG_ERROR(("no voice definition for %s",voiceName)); + return picoos_emRaiseException(this->common->em,PICO_EXC_NAME_UNDEFINED,NULL,(picoos_char *)"voice definition %s",voiceName); + + } + PICODBG_DEBUG(("found voice definition for %s",voiceName)); + + /* check that resources are loaded */ + for (i = 0; i < vdef->numResources; i++) { + required = (NULLC != vdef->resourceName[i][0]); + if (required && !isResourceLoaded(this,vdef->resourceName[i])) { + PICODBG_ERROR(("resource missing")); + return picoos_emRaiseException(this->common->em,PICO_EXC_RESOURCE_MISSING,NULL,(picoos_char *)"resource %s for voice %s",vdef->resourceName[i],voiceName); + } + } + + /* allocate new voice */ + if (NULL == this->freeVoices) { + *voice = picorsrc_newVoice(this->common->mm); + } else { + *voice = this->freeVoices; + this->freeVoices = (*voice)->next; + picorsrc_initializeVoice(*voice); + } + if (*voice == NULL) { + return picoos_emRaiseException(this->common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); + } + this->numVoices++; + + /* copy resource kb pointers into kb array of voice */ + for (i = 0; i < vdef->numResources; i++) { + required = (NULLC != vdef->resourceName[i][0]); + if (required) { + findResource(this,vdef->resourceName[i],&rsrc); + (*voice)->resourceArray[(*voice)->numResources++] = rsrc; + rsrc->lockCount++; + kb = rsrc->kbList; + while (NULL != kb) { + if (NULL != (*voice)->kbArray[kb->id]) { + picoos_emRaiseWarning(this->common->em,PICO_WARN_KB_OVERWRITE,NULL, (picoos_char *)"%i", kb->id); + PICODBG_WARN(("overwriting knowledge base of id %i", kb->id)); + + } + PICODBG_DEBUG(("setting knowledge base of id %i", kb->id)); + + (*voice)->kbArray[kb->id] = kb; + kb = kb->next; + } + } + } /* for */ + + return PICO_OK; +} + +/* dispose voice. the corresponding lock counts are decremented. */ + +pico_status_t picorsrc_releaseVoice(picorsrc_ResourceManager this, picorsrc_Voice * voice) +{ + picoos_uint16 i; + picorsrc_Voice v = *voice; + if (NULL == this || NULL == v) { + return PICO_ERR_NULLPTR_ACCESS; + } + for (i = 0; i < v->numResources; i++) { + v->resourceArray[i]->lockCount--; + } + v->next = this->freeVoices; + this->freeVoices = v; + this->numVoices--; + + return PICO_OK; +} + +#ifdef __cplusplus +} +#endif + +/* end picorsrc.c */ diff --git a/pico/lib/picorsrc.h b/pico/lib/picorsrc.h new file mode 100644 index 0000000..4dfb19e --- /dev/null +++ b/pico/lib/picorsrc.h @@ -0,0 +1,185 @@ +/* + * 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 picorsrc.h + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +/** + * @addtogroup picorsrc + * + * Pico Resource Management module \n + * +*/ + +#ifndef PICORSRC_H_ +#define PICORSRC_H_ + +#include "picodefs.h" +#include "picoos.h" +#include "picoknow.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +#define PICORSRC_MAX_RSRC_NAME_SIZ PICO_MAX_RESOURCE_NAME_SIZE /* including terminating NULLC */ + +#define PICORSRC_MAX_NUM_VOICES 64 + +/* size of kb array of a voice */ +#define PICORSRC_KB_ARRAY_SIZE 64 + +typedef picoos_char picorsrc_resource_name_t[PICORSRC_MAX_RSRC_NAME_SIZ]; + +typedef enum picorsrc_resource_type { + PICORSRC_TYPE_NULL, + PICORSRC_TYPE_TEXTANA, + PICORSRC_TYPE_SIGGEN, + PICORSRC_TYPE_USER_LEX, + PICORSRC_TYPE_USER_PREPROC, + PICORSRC_TYPE_OTHER +} picorsrc_resource_type_t; + + +#define PICORSRC_FIELD_VALUE_TEXTANA (picoos_char *) "TEXTANA" +#define PICORSRC_FIELD_VALUE_SIGGEN (picoos_char *) "SIGGEN" +#define PICORSRC_FIELD_VALUE_USERLEX (picoos_char *) "USERLEX" +#define PICORSRC_FIELD_VALUE_USERTPP (picoos_char *) "USERTPP" + + + +typedef struct picorsrc_resource_manager * picorsrc_ResourceManager; +typedef struct picorsrc_voice * picorsrc_Voice; +typedef struct picorsrc_resource * picorsrc_Resource; + + +/* ************************************************************************** + * + * file name extensions + * + ****************************************************************************/ + +#define PICO_BIN_EXTENSION ".bin" +#define PICO_INPLACE_EXTENSION ".inp" + + + +/* ************************************************************************** + * + * construct/destruct resource manager + * + ****************************************************************************/ + +/* create resource manager, given a config file name (or default name, if empty) */ + +picorsrc_ResourceManager picorsrc_newResourceManager(picoos_MemoryManager mm, picoos_Common common /* , picoos_char * configFile */); + +void picorsrc_disposeResourceManager(picoos_MemoryManager mm, picorsrc_ResourceManager * this); + + +/* ************************************************************************** + * + * resources + * + ****************************************************************************/ + +/** + * Returns non-zero if 'resource' is a valid resource handle, zero otherwise. + */ +picoos_int16 picoctrl_isValidResourceHandle(picorsrc_Resource resource); + +/* load resource file. the type of resource file, magic numbers, checksum etc. are in the header, then follows the directory + * (with fixed structure per resource type), then the knowledge bases themselves (as byte streams) */ +pico_status_t picorsrc_loadResource(picorsrc_ResourceManager this, + picoos_char * fileName, picorsrc_Resource * resource); + +/* unload resource file. (warn if resource file is busy) */ +pico_status_t picorsrc_unloadResource(picorsrc_ResourceManager this, picorsrc_Resource * rsrc); + + +pico_status_t picorsrc_createDefaultResource(picorsrc_ResourceManager this /*, + picorsrc_Resource * resource */); + + +pico_status_t picorsrc_rsrcGetName(picorsrc_Resource resource, + picoos_char * name, picoos_uint32 maxlen); + +/* ************************************************************************** + * + * voice definitions + * + ****************************************************************************/ + + +pico_status_t picorsrc_createVoiceDefinition(picorsrc_ResourceManager this, + picoos_char * voiceName); + + +pico_status_t picorsrc_releaseVoiceDefinition(picorsrc_ResourceManager this, + picoos_char * voiceName); + +pico_status_t picorsrc_addResourceToVoiceDefinition(picorsrc_ResourceManager this, + picoos_char * voiceName, picoos_char * resourceName); + +/* ************************************************************************** + * + * voices + * + ****************************************************************************/ + +/** object : Voice + * shortcut : voice + * + */ + +typedef struct picorsrc_voice { + + picorsrc_Voice next; + + picoknow_KnowledgeBase kbArray[PICORSRC_KB_ARRAY_SIZE]; + + picoos_uint8 numResources; + + picorsrc_Resource resourceArray[PICO_MAX_NUM_RSRC_PER_VOICE]; + + +} picorsrc_voice_t; + + + +/* create voice, given a voice name. the corresponding lock counts are incremented */ +pico_status_t picorsrc_createVoice(picorsrc_ResourceManager this, const picoos_char * voiceName, picorsrc_Voice * voice); + +/* dispose voice. the corresponding lock counts are decremented. */ +pico_status_t picorsrc_releaseVoice(picorsrc_ResourceManager this, picorsrc_Voice * voice); + +#ifdef __cplusplus +} +#endif + + + +#endif /*PICORSRC_H_*/ diff --git a/pico/lib/picosa.c b/pico/lib/picosa.c new file mode 100644 index 0000000..3147c76 --- /dev/null +++ b/pico/lib/picosa.c @@ -0,0 +1,1738 @@ +/* + * 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 picosa.c + * + * sentence analysis - POS disambiguation + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#include "picoos.h" +#include "picodbg.h" +#include "picobase.h" +#include "picokdt.h" +#include "picoklex.h" +#include "picoktab.h" +#include "picokfst.h" +#include "picotrns.h" +#include "picodata.h" +#include "picosa.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* PU saStep states */ +#define SA_STEPSTATE_COLLECT 0 +#define SA_STEPSTATE_PROCESS_POSD 10 +#define SA_STEPSTATE_PROCESS_WPHO 11 +#define SA_STEPSTATE_PROCESS_TRNS_PARSE 12 +#define SA_STEPSTATE_PROCESS_TRNS_FST 13 +#define SA_STEPSTATE_FEED 2 + +#define SA_MAX_ALTDESC_SIZE (30*(PICOTRNS_MAX_NUM_POSSYM + 2)) + +#define SA_MSGSTR_SIZE 32 + +/* subobject : SentAnaUnit + * shortcut : sa + * context size : one phrase, max. 30 non-PUNC items, for non-processed items + * one item if internal input empty + */ + +/** @addtogroup picosa + + internal buffers: + + - headx: array for extended item heads of fixed size (head plus + index for content, plus two fields for boundary strength/type) + + - cbuf1, cbuf2: buffers for item contents (referenced by index in + headx). Future: replace these two buffers by a single double-sided + buffer (double shrink-grow type) + + 0. bottom up filling of items in headx and cbuf1 + + 1. POS disambiguation (right-to-left, top-to-bottom): + - number and sequence of items unchanged + - item content can only get smaller (reducing nr of results in WORDINDEX) + -> info stays in "headx, cbuf1" and changed in place \n + WORDGRAPH(POSes,NA)graph -> WORDGRAPH(POS,NA)graph \n + WORDINDEX(POSes,NA)POS1ind1...POSNindN -> WORDINDEX(POS,NA)POS|ind \n + + 2. lex-index lookup and G2P (both directions possible, left-to-right done): + - number and sequence of items unchanged, item head info and content + changes + -> headx changed in place; cbuf1 to cbuf2 \n + WORDGRAPH(POS,NA)graph -> WORDPHON(POS,NA)phon \n + WORDINDEX(POS,NA)POS|ind -> WORDPHON(POS,NA)phon \n + + 3. phrasing (right-to-left): + + Previous (before introducing SBEG)\n + ---------------------------------- + 1| 2| 3| 4| \n + e.g. from WP WP WP WP WP PUNC WP WP PUNC WP WP WP PUNC FLUSH \n + e.g. to BINIT WP WP WP BPHR3 WP WP BPHR1 WP WP BSEND WP WP WP BSEND BTERM \n + |1 |2 |3 |4 \n + + 3-level bound state: to keep track of bound strength from end of + previous punc-phrase, then BOUND item output as first item + (strength from prev punc-phrase and type from current + punc-phrase). + + trailing PUNC item bound states + INIT SEND PHR1 + PUNC(SENTEND, T) B(I,T)>SEND B(S,T)>SEND B(P1,T)>SEND + PUNC(SENTEND, Q) B(I,Q)>SEND B(S,Q)>SEND B(P1,Q)>SEND + PUNC(SENTEND, E) B(I,E)>SEND B(S,E)>SEND B(P1,E)>SEND + PUNC(PHRASEEND, P) B(I,P)>PHR1 B(S,P)>PHR1 B(P1,P)>PHR1 + PUNC(PHRASEEND, FORC) B(I,P)>PHR1 B(S,P)>PHR1 B(P1,P)>PHR1 + PUNC(FLUSH, T) B(I,T).. B(S,T).. B(P1,T).. + B(T,NA) B(T,NA) B(T,NA) + >INIT >INIT >INIT + + PHR2/3 case: + trailing PUNC item bound states + INIT SEND PHR1 + PUNC(SENTEND, T) B(I,P)B(P,T)>SEND B(S,P)B(P,T)>SEND B(P1,P)B(P,T)>SEND + PUNC(SENTEND, Q) B(I,P)B(P,Q)>SEND B(S,P)B(P,Q)>SEND B(P1,P)B(P,Q)>SEND + PUNC(SENTEND, E) B(I,P)B(P,E)>SEND B(S,P)B(P,E)>SEND B(P1,P)B(P,E)>SEND + PUNC(PHRASEEND, P) B(I,P)B(P,P)>PHR1 B(S,P)B(P,P)>PHR1 B(P1,P)B(P,P)>PHR1 + PUNC(PHREND, FORC) B(I,P)B(P,P)>PHR1 B(S,P)B(P,P)>PHR1 B(P1,P)B(P,P)>PHR1 + PUNC(FLUSH, T) B(I,P)B(P,T).. B(S,T)B(P,T).. B(P1,T)B(P,T).. + B(T,NA) B(T,NA) B(T,NA) + >INIT >INIT >INIT + + Current + -------- + e.g. from WP WP WP WP WP PUNC WP WP PUNC WP WP WP PUNC FLUSH + e.g. to BSBEG WP WP WP BPHR3 WP WP BPHR1 WP WP BSEND BSBEG WP WP WP BSEND BTERM + |1 |2 |3 |4 + + 2-level bound state: The internal buffer contains one primary phrase (sometimes forced, if buffer + allmost full), with the trailing PUNCT item included (last item). + If the trailing PUNC is a a primary phrase separator, the + item is not output, but instead, the bound state is set to PPHR, so that the correct BOUND can + be output at the start of the next primary phrase. + Otherwise, + the item is converted to the corresponding BOUND and output. the bound state is set to SSEP, + so that a BOUND of type SBEG is output at the start of the next primary phrase. + + trailing PUNC item bound states + SSEP PPHR + PUNC(SENTEND, X) B(B,X)>SSEP B(P1,X)>SSEP (X = T | Q | E) + PUNC(FLUSH, T) B(B,T)>SSEP* B(P1,T)>SSEP + PUNC(PHRASEEND, P) B(B,P)>PPHR B(P1,P)>PPHR + PUNC(PHRASEEND, FORC) B(B,P)>PPHR B(P1,P)>PPHR + +* If more than one sentence separators follow each other (e.g. SEND-FLUSH, SEND-SEND) then + all but the first will be treated as an (empty) phrase containing just this item. + If this (single) item is a flush, creation of SBEG is suppressed. + + + - dtphr phrasing tree (rather subphrasing tree it should be called) + determines + BOUND_PHR2 + BOUND_PHR3 + - boundary strenghts are determined for every word (except the + first one) from right-to-left. The boundary types mark the phrase + type of the phrase following the boundary. + - number of items actually changed (new BOUND items added): because + of fixed size without content, two fields are contained in headx + to indicate if a BOUND needs to be added to the LEFT of the item. + -> headx further extended with boundary strength and type info to + indicate that to the left of the headx ele a BOUND needs to be + inserted when outputting. + + 4. accentuation: + - number of items unchanged, content unchanged, only head info changes + -> changed in place in headx +*/ + + +typedef struct { + picodata_itemhead_t head; + picoos_uint16 cind; +} picosa_headx_t; + + +typedef struct sa_subobj { + picoos_uint8 procState; /* for next processing step decision */ + + picoos_uint8 inspaceok; /* flag: headx/cbuf1 has space for an item */ + picoos_uint8 needsmoreitems; /* flag: need more items */ + picoos_uint8 phonesTransduced; /* flag: */ + + picoos_uint8 tmpbuf[PICODATA_MAX_ITEMSIZE]; /* tmp. location for an item */ + + picosa_headx_t headx[PICOSA_MAXNR_HEADX]; + picoos_uint16 headxBottom; /* bottom */ + picoos_uint16 headxLen; /* length, 0 if empty */ + + picoos_uint8 cbuf1[PICOSA_MAXSIZE_CBUF]; + picoos_uint16 cbuf1BufSize; /* actually allocated size */ + picoos_uint16 cbuf1Len; /* length, 0 if empty */ + + picoos_uint8 cbuf2[PICOSA_MAXSIZE_CBUF]; + picoos_uint16 cbuf2BufSize; /* actually allocated size */ + picoos_uint16 cbuf2Len; /* length, 0 if empty */ + + picotrns_possym_t phonBufA[PICOTRNS_MAX_NUM_POSSYM+1]; + picotrns_possym_t phonBufB[PICOTRNS_MAX_NUM_POSSYM+1]; + picotrns_possym_t * phonBuf; + picotrns_possym_t * phonBufOut; + picoos_uint16 phonReadPos, phonWritePos; /* next pos to read from phonBufIn, next pos to write to phonBufIn */ + picoos_uint16 nextReadPos; /* position of (potential) next item to read from */ + + + /* buffer for internal calculation of transducer */ + picotrns_AltDesc altDescBuf; + /* the number of AltDesc in the buffer */ + picoos_uint16 maxAltDescLen; + + /* tab knowledge base */ + picoktab_Graphs tabgraphs; + picoktab_Phones tabphones; + picoktab_Pos tabpos; + picoktab_FixedIds fixedIds; + + /* dtposd knowledge base */ + picokdt_DtPosD dtposd; + + /* dtg2p knowledge base */ + picokdt_DtG2P dtg2p; + + /* lex knowledge base */ + picoklex_Lex lex; + + /* ulex knowledge bases */ + picoos_uint8 numUlex; + picoklex_Lex ulex[PICOKNOW_MAX_NUM_ULEX]; + + /* fst knowledge bases */ + picoos_uint8 numFsts; + picokfst_FST fst[PICOKNOW_MAX_NUM_WPHO_FSTS]; + picoos_uint8 curFst; /* the fst to be applied next */ + + +} sa_subobj_t; + + +static pico_status_t saInitialize(register picodata_ProcessingUnit this) { + sa_subobj_t * sa; + picoos_uint16 i; + picokfst_FST fst; + picoknow_kb_id_t fstKbIds[PICOKNOW_MAX_NUM_WPHO_FSTS] = PICOKNOW_KBID_WPHO_ARRAY; + picoklex_Lex ulex; + picoknow_kb_id_t ulexKbIds[PICOKNOW_MAX_NUM_ULEX] = PICOKNOW_KBID_ULEX_ARRAY; + + PICODBG_DEBUG(("calling")); + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(this->common->em, + PICO_ERR_NULLPTR_ACCESS, NULL, NULL); + } + sa = (sa_subobj_t *) this->subObj; + + /* sa->common = this->common; */ + + sa->procState = SA_STEPSTATE_COLLECT; + + sa->inspaceok = TRUE; + sa->needsmoreitems = TRUE; + + sa->headxBottom = 0; + sa->headxLen = 0; + sa->cbuf1BufSize = PICOSA_MAXSIZE_CBUF; + sa->cbuf2BufSize = PICOSA_MAXSIZE_CBUF; + sa->cbuf1Len = 0; + sa->cbuf2Len = 0; + + /* init headx, cbuf1, cbuf2 */ + for (i = 0; i < PICOSA_MAXNR_HEADX; i++){ + sa->headx[i].head.type = 0; + sa->headx[i].head.info1 = PICODATA_ITEMINFO1_NA; + sa->headx[i].head.info2 = PICODATA_ITEMINFO2_NA; + sa->headx[i].head.len = 0; + sa->headx[i].cind = 0; + } + for (i = 0; i < PICOSA_MAXSIZE_CBUF; i++) { + sa->cbuf1[i] = 0; + sa->cbuf2[i] = 0; + } + + + /* possym buffer */ + sa->phonesTransduced = FALSE; + sa->phonBuf = sa->phonBufA; + sa->phonBufOut = sa->phonBufB; + sa->phonReadPos = 0; + sa->phonWritePos = 0; + sa->nextReadPos = 0; + + /* kb fst[] */ + sa->numFsts = 0; + for (i = 0; ivoice->kbArray[fstKbIds[i]]); + if (NULL != fst) { + sa->fst[sa->numFsts++] = fst; + } + } + sa->curFst = 0; + PICODBG_DEBUG(("got %i fsts", sa->numFsts)); + /* kb fixedIds */ + sa->fixedIds = picoktab_getFixedIds(this->voice->kbArray[PICOKNOW_KBID_FIXED_IDS]); + + /* kb tabgraphs */ + sa->tabgraphs = + picoktab_getGraphs(this->voice->kbArray[PICOKNOW_KBID_TAB_GRAPHS]); + if (sa->tabgraphs == NULL) { + return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + PICODBG_DEBUG(("got tabgraphs")); + + /* kb tabphones */ + sa->tabphones = + picoktab_getPhones(this->voice->kbArray[PICOKNOW_KBID_TAB_PHONES]); + if (sa->tabphones == NULL) { + return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + PICODBG_DEBUG(("got tabphones")); + +#ifdef PICO_DEBU + { + picoos_uint16 itmp; + for (itmp = 0; itmp < 256; itmp++) { + if (picoktab_hasVowelProp(sa->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones hasVowel: %d", itmp)); + } + if (picoktab_hasDiphthProp(sa->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones hasDiphth: %d", itmp)); + } + if (picoktab_hasGlottProp(sa->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones hasGlott: %d", itmp)); + } + if (picoktab_hasNonsyllvowelProp(sa->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones hasNonsyllvowel: %d", itmp)); + } + if (picoktab_hasSyllconsProp(sa->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones hasSyllcons: %d", itmp)); + } + if (picoktab_isPrimstress(sa->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones isPrimstress: %d", itmp)); + } + if (picoktab_isSecstress(sa->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones isSecstress: %d", itmp)); + } + if (picoktab_isSyllbound(sa->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones isSyllbound: %d", itmp)); + } + if (picoktab_isPause(sa->tabphones, itmp)) { + PICODBG_DEBUG(("tabphones isPause: %d", itmp)); + } + } + + PICODBG_DEBUG(("tabphones primstressID: %d", + picoktab_getPrimstressID(sa->tabphones))); + PICODBG_DEBUG(("tabphones secstressID: %d", + picoktab_getSecstressID(sa->tabphones))); + PICODBG_DEBUG(("tabphones syllboundID: %d", + picoktab_getSyllboundID(sa->tabphones))); + PICODBG_DEBUG(("tabphones pauseID: %d", + picoktab_getPauseID(sa->tabphones))); + } +#endif + + /* kb tabpos */ + sa->tabpos = + picoktab_getPos(this->voice->kbArray[PICOKNOW_KBID_TAB_POS]); + if (sa->tabpos == NULL) { + return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + PICODBG_DEBUG(("got tabpos")); + + /* kb dtposd */ + sa->dtposd = picokdt_getDtPosD(this->voice->kbArray[PICOKNOW_KBID_DT_POSD]); + if (sa->dtposd == NULL) { + return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + PICODBG_DEBUG(("got dtposd")); + + /* kb dtg2p */ + sa->dtg2p = picokdt_getDtG2P(this->voice->kbArray[PICOKNOW_KBID_DT_G2P]); + if (sa->dtg2p == NULL) { + return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + PICODBG_DEBUG(("got dtg2p")); + + /* kb lex */ + sa->lex = picoklex_getLex(this->voice->kbArray[PICOKNOW_KBID_LEX_MAIN]); + if (sa->lex == NULL) { + return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + PICODBG_DEBUG(("got lex")); + + /* kb ulex[] */ + sa->numUlex = 0; + for (i = 0; ivoice->kbArray[ulexKbIds[i]]); + if (NULL != ulex) { + sa->ulex[sa->numUlex++] = ulex; + } + } + PICODBG_DEBUG(("got %i user lexica", sa->numUlex)); + + return PICO_OK; +} + +static picodata_step_result_t saStep(register picodata_ProcessingUnit this, + picoos_int16 mode, + picoos_uint16 *numBytesOutput); + +static pico_status_t saTerminate(register picodata_ProcessingUnit this) { + return PICO_OK; +} + +static pico_status_t saSubObjDeallocate(register picodata_ProcessingUnit this, + picoos_MemoryManager mm) { + sa_subobj_t * sa; + if (NULL != this) { + sa = (sa_subobj_t *) this->subObj; + picotrns_deallocate_alt_desc_buf(mm,&sa->altDescBuf); + picoos_deallocate(mm, (void *) &this->subObj); + } + return PICO_OK; +} + + +picodata_ProcessingUnit picosa_newSentAnaUnit(picoos_MemoryManager mm, + picoos_Common common, + picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, + picorsrc_Voice voice) { + picodata_ProcessingUnit this; + sa_subobj_t * sa; + this = picodata_newProcessingUnit(mm, common, cbIn, cbOut, voice); + if (this == NULL) { + return NULL; + } + + this->initialize = saInitialize; + PICODBG_DEBUG(("set this->step to saStep")); + this->step = saStep; + this->terminate = saTerminate; + this->subDeallocate = saSubObjDeallocate; + + this->subObj = picoos_allocate(mm, sizeof(sa_subobj_t)); + if (this->subObj == NULL) { + picoos_deallocate(mm, (void *)&this); + picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); + return NULL; + } + + sa = (sa_subobj_t *) this->subObj; + + sa->altDescBuf = picotrns_allocate_alt_desc_buf(mm, SA_MAX_ALTDESC_SIZE, &sa->maxAltDescLen); + if (NULL == sa->altDescBuf) { + picotrns_deallocate_alt_desc_buf(mm,&sa->altDescBuf); + picoos_deallocate(mm, (void *)&sa); + picoos_deallocate(mm, (void *)&this); + picoos_emRaiseException(common->em,PICO_EXC_OUT_OF_MEM, NULL, NULL); + } + + + saInitialize(this); + return this; +} + + +/* ***********************************************************************/ +/* PROCESS_POSD disambiguation functions */ +/* ***********************************************************************/ + +/* find next POS to the right of 'ind' and return its POS and index */ +static picoos_uint8 saPosDItemSeqGetPosRight(register picodata_ProcessingUnit this, + register sa_subobj_t *sa, + const picoos_uint16 ind, + const picoos_uint16 top, + picoos_uint16 *rightind) { + picoos_uint8 val; + picoos_int32 i; + + val = PICOKDT_EPSILON; + for (i = ind + 1; ((val == PICOKDT_EPSILON) && (i < top)); i++) { + if ((sa->headx[i].head.type == PICODATA_ITEM_WORDGRAPH) || + (sa->headx[i].head.type == PICODATA_ITEM_WORDINDEX) || + (sa->headx[i].head.type == PICODATA_ITEM_WORDPHON) ) { + val = sa->headx[i].head.info1; + } + } + *rightind = i - 1; + return val; +} + + +/* left-to-right, for each WORDGRAPH/WORDINDEX/WORDPHON do posd */ +static pico_status_t saDisambPos(register picodata_ProcessingUnit this, + register sa_subobj_t *sa) { + picokdt_classify_result_t dtres; + picoos_uint8 half_nratt_posd = PICOKDT_NRATT_POSD >> 1; + picoos_uint16 valbuf[PICOKDT_NRATT_POSD]; /* only [0..half_nratt_posd] can be >2^8 */ + picoos_uint16 prevout; /* direct dt output (hist.) or POS of prev word */ + picoos_uint16 lastprev3; /* last index of POS(es) found to the left */ + picoos_uint16 curPOS; /* POS(es) of current word */ + picoos_int32 first; /* index of first item with POS(es) */ + picoos_int32 ci; + picoos_uint8 okay; /* two uses: processing okay and lexind resovled */ + picoos_uint8 i; + picoos_uint16 inval; + picoos_uint16 fallback; + + /* set initial values */ + okay = TRUE; + prevout = PICOKDT_HISTORY_ZERO; + curPOS = PICODATA_ITEMINFO1_ERR; + first = 0; + + while ((first < sa->headxLen) && + (sa->headx[first].head.type != PICODATA_ITEM_WORDGRAPH) && + (sa->headx[first].head.type != PICODATA_ITEM_WORDINDEX) && + (sa->headx[first].head.type != PICODATA_ITEM_WORDPHON)) { + first++; + } + if (first >= sa->headxLen) { + /* phrase not containing an item with POSes info, e.g. single flush */ + PICODBG_DEBUG(("no item with POSes found")); + return PICO_OK; + } + + lastprev3 = first; + + for (i = 0; i <= half_nratt_posd; i++) { + valbuf[i] = PICOKDT_HISTORY_ZERO; + } + /* set POS(es) of current word, will be shifted afterwards */ + valbuf[half_nratt_posd+1] = sa->headx[first].head.info1; + for (i = half_nratt_posd+2; i < PICOKDT_NRATT_POSD; i++) { + /* find next POS to the right and set valbuf[i] */ + valbuf[i] = saPosDItemSeqGetPosRight(this, sa, lastprev3, sa->headxLen, &lastprev3); + } + + PICODBG_TRACE(("headxLen: %d", sa->headxLen)); + + /* process from left to right all items in headx */ + for (ci = first; ci < sa->headxLen; ci++) { + okay = TRUE; + + PICODBG_TRACE(("iter: %d, type: %c", ci, sa->headx[ci].head.type)); + + /* if not (WORDGRAPH or WORDINDEX) */ + if ((sa->headx[ci].head.type != PICODATA_ITEM_WORDGRAPH) && + (sa->headx[ci].head.type != PICODATA_ITEM_WORDINDEX) && + (sa->headx[ci].head.type != PICODATA_ITEM_WORDPHON)) { + continue; + } + + PICODBG_TRACE(("iter: %d, curPOS: %d", ci, sa->headx[ci].head.info1)); + + /* no continue so far => at [ci] we have a WORDGRAPH / WORDINDEX item */ + /* shift all elements one position to the left */ + /* shift predicted values (history) */ + for (i=1; iheadxLen, &lastprev3); + + /* just to be on the safe side; the following should never happen */ + if (sa->headx[ci].head.info1 != valbuf[half_nratt_posd]) { + PICODBG_WARN(("syncing POS")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, + NULL, NULL); + valbuf[half_nratt_posd] = sa->headx[ci].head.info1; + } + + curPOS = valbuf[half_nratt_posd]; + + /* Check if POS disambiguation not needed */ + if (picoktab_isUniquePos(sa->tabpos, (picoos_uint8) curPOS)) { + /* not needed */ + inval = 0; + fallback = 0; + if (!picokdt_dtPosDreverseMapOutFixed(sa->dtposd, curPOS, + &prevout, &fallback)) { + if (fallback) { + prevout = fallback; + + } else { + PICODBG_ERROR(("problem doing reverse output mapping")); + prevout = curPOS; + } + } + PICODBG_DEBUG(("keeping: %d", sa->headx[ci].head.info1)); + continue; + } + + /* assuming PICOKDT_NRATT_POSD == 7 */ + PICODBG_DEBUG(("%d: [%d %d %d %d %d %d %d]", + ci, valbuf[0], valbuf[1], valbuf[2], + valbuf[3], valbuf[4], valbuf[5], valbuf[6])); + + /* no continue so far => POS disambiguation needed */ + /* construct input vector, which is set in dtposd */ + if (!picokdt_dtPosDconstructInVec(sa->dtposd, valbuf)) { + /* error constructing invec */ + PICODBG_WARN(("problem with invec")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, + NULL, NULL); + okay = FALSE; + } + /* classify */ + if (okay && (!picokdt_dtPosDclassify(sa->dtposd, &prevout))) { + /* error doing classification */ + PICODBG_WARN(("problem classifying")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, + NULL, NULL); + okay = FALSE; + } + /* decompose */ + if (okay && (!picokdt_dtPosDdecomposeOutClass(sa->dtposd, &dtres))) { + /* error decomposing */ + PICODBG_WARN(("problem decomposing")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_OUTVECTOR, + NULL, NULL); + okay = FALSE; + } + if (okay && dtres.set) { + PICODBG_DEBUG(("in: %d, out: %d", valbuf[3], dtres.class)); + } else { + PICODBG_WARN(("problem disambiguating POS")); + dtres.class = PICODATA_ITEMINFO1_ERR; + } + + if (dtres.class > 255) { + PICODBG_WARN(("dt result outside valid range, setting pos to ERR")); + dtres.class = PICODATA_ITEMINFO1_ERR; + } + + sa->headx[ci].head.info1 = (picoos_uint8)dtres.class; + if (sa->headx[ci].head.type == PICODATA_ITEM_WORDINDEX) { + /* find pos/ind entry in cbuf matching unique, + disambiguated POS, adapt current headx cind/len + accordingly */ + PICODBG_DEBUG(("select phon based on POS disambiguation")); + okay = FALSE; + for (i = 0; i < sa->headx[ci].head.len; i += PICOKLEX_POSIND_SIZE) { + PICODBG_DEBUG(("comparing POS at cind + %d", i)); + if (picoktab_isPartOfPosGroup(sa->tabpos, + (picoos_uint8)dtres.class, + sa->cbuf1[sa->headx[ci].cind + i])) { + PICODBG_DEBUG(("found match for entry %d", + i/PICOKLEX_POSIND_SIZE + 1)); + sa->headx[ci].cind += i; + okay = TRUE; + break; + } + } + /* not finding a match is possible if posd predicts a POS that + is not part of any of the input POSes -> no warning */ +#if defined(PICO_DEBUG) + if (!okay) { + PICODBG_DEBUG(("no match found, selecting 1st entry")); + } +#endif + sa->headx[ci].head.len = PICOKLEX_POSIND_SIZE; + } + } + return PICO_OK; +} + + +/* ***********************************************************************/ +/* PROCESS_WPHO functions, copy, lexindex, and g2p */ +/* ***********************************************************************/ + +/* ************** copy ***************/ + +static pico_status_t saCopyItemContent1to2(register picodata_ProcessingUnit this, + register sa_subobj_t *sa, + picoos_uint16 ind) { + picoos_uint16 i; + picoos_uint16 cind1; + + /* set headx.cind, and copy content, head unchanged */ + cind1 = sa->headx[ind].cind; + sa->headx[ind].cind = sa->cbuf2Len; + + /* check cbufLen */ + if (sa->headx[ind].head.len > (sa->cbuf2BufSize - sa->cbuf2Len)) { + sa->headx[ind].head.len = sa->cbuf2BufSize - sa->cbuf2Len; + PICODBG_WARN(("phones skipped")); + picoos_emRaiseWarning(this->common->em, + PICO_WARN_INCOMPLETE, NULL, NULL); + if (sa->headx[ind].head.len == 0) { + sa->headx[ind].cind = 0; + } + } + + for (i = 0; i < sa->headx[ind].head.len; i++) { + sa->cbuf2[sa->cbuf2Len] = sa->cbuf1[cind1 + i]; + sa->cbuf2Len++; + } + + PICODBG_DEBUG(("%c item, len: %d", + sa->headx[ind].head.type, sa->headx[ind].head.len)); + + return PICO_OK; +} + + +/* ************** lexindex ***************/ + +static pico_status_t saLexIndLookup(register picodata_ProcessingUnit this, + register sa_subobj_t *sa, + picoklex_Lex lex, + picoos_uint16 ind) { + picoos_uint8 pos; + picoos_uint8 *phones; + picoos_uint8 plen; + picoos_uint16 i; + + if (picoklex_lexIndLookup(lex, &(sa->cbuf1[sa->headx[ind].cind + 1]), + PICOKLEX_IND_SIZE, &pos, &phones, &plen)) { + sa->headx[ind].cind = sa->cbuf2Len; + + /* check cbufLen */ + if (plen > (sa->cbuf2BufSize - sa->cbuf2Len)) { + plen = sa->cbuf2BufSize - sa->cbuf2Len; + PICODBG_WARN(("phones skipped")); + picoos_emRaiseWarning(this->common->em, + PICO_WARN_INCOMPLETE, NULL, NULL); + if (plen == 0) { + sa->headx[ind].cind = 0; + } + } + + /* set item head, info1, info2 unchanged */ + sa->headx[ind].head.type = PICODATA_ITEM_WORDPHON; + sa->headx[ind].head.len = plen; + + for (i = 0; i < plen; i++) { + sa->cbuf2[sa->cbuf2Len] = phones[i]; + sa->cbuf2Len++; + } + + PICODBG_DEBUG(("%c item, pos: %d, plen: %d", + PICODATA_ITEM_WORDPHON, pos, plen)); + + } else { + PICODBG_WARN(("lexIndLookup problem")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_PU_IRREG_ITEM, + NULL, NULL); + } + return PICO_OK; +} + + + +/* ************** g2p ***************/ + + +/* Name : saGetNvowel + Function: returns vowel info in a word or word seq + Input : sInChar the grapheme string to be converted in phoneme + inLen number of bytes in grapheme buffer + inPos start position of current grapheme (0..inLen-1) + Output : nVow number of vowels in the word + nVord vowel order in the word + Returns : TRUE: processing successful; FALSE: errors +*/ +static picoos_uint8 saGetNrVowel(register picodata_ProcessingUnit this, + register sa_subobj_t *sa, + const picoos_uint8 *sInChar, + const picoos_uint16 inLen, + const picoos_uint8 inPos, + picoos_uint8 *nVow, + picoos_uint8 *nVord) { + picoos_uint32 nCount; + picoos_uint32 pos; + picoos_uint8 cstr[PICOBASE_UTF8_MAXLEN + 1]; + + /*defaults*/ + *nVow = 0; + *nVord = 0; + /*1:check wether the current char is a vowel*/ + pos = inPos; + if (!picobase_get_next_utf8char(sInChar, inLen, &pos, cstr) || + !picoktab_hasVowellikeProp(sa->tabgraphs, cstr, PICOBASE_UTF8_MAXLEN)) { + return FALSE; + } + /*2:count number of vowels in current word and find vowel order*/ + for (nCount = 0; nCount < inLen; ) { + if (!picobase_get_next_utf8char(sInChar, inLen, &nCount, cstr)) { + return FALSE; + } + if (picoktab_hasVowellikeProp(sa->tabgraphs, cstr, + PICOBASE_UTF8_MAXLEN)) { + (*nVow)++; + if (nCount == pos) { + (*nVord) = (*nVow); + } + } + } + return TRUE; +} + + +/* do g2p for a full word, right-to-left */ +static picoos_uint8 saDoG2P(register picodata_ProcessingUnit this, + register sa_subobj_t *sa, + const picoos_uint8 *graph, + const picoos_uint8 graphlen, + const picoos_uint8 pos, + picoos_uint8 *phones, + const picoos_uint16 phonesmaxlen, + picoos_uint16 *plen) { + picoos_uint16 outNp1Ch; /*last 3 outputs produced*/ + picoos_uint16 outNp2Ch; + picoos_uint16 outNp3Ch; + picoos_uint8 nPrimary; + picoos_uint8 nCount; + picoos_uint32 utfpos; + picoos_uint16 nOutVal; + picoos_uint8 okay; + picoos_uint16 phonesind; + picoos_uint8 nrvow; + picoos_uint8 ordvow; + picokdt_classify_vecresult_t dtresv; + picoos_uint16 i; + + *plen = 0; + okay = TRUE; + + /* use sa->tmpbuf[PICOSA_MAXITEMSIZE] to temporarly store the + phones which are predicted in reverse order. Once all are + available put them in phones in usuable order. phonesind is + used to fille item in reverse order starting at the end of + tmpbuf. */ + phonesind = PICOSA_MAXITEMSIZE - 1; + + /* prepare the data for loop operations */ + outNp1Ch = PICOKDT_HISTORY_ZERO; + outNp2Ch = PICOKDT_HISTORY_ZERO; + outNp3Ch = PICOKDT_HISTORY_ZERO; + + /* inner loop */ + nPrimary = 0; + + /* ************************************************/ + /* go backward grapheme by grapheme, it's utf8... */ + /* ************************************************/ + + /* set start nCount to position of start of last utfchar */ + /* ! watch out! somethimes starting at 1, sometimes at 0, + ! sometimes counting per byte, sometimes per UTF8 char */ + /* nCount is (start position + 1) of utf8 char */ + utfpos = graphlen; + if (picobase_get_prev_utf8charpos(graph, 0, &utfpos)) { + nCount = utfpos + 1; + } else { + /* should not occurr */ + PICODBG_ERROR(("invalid utf8 string, graphlen: %d", graphlen)); + return FALSE; + } + + while (nCount > 0) { + PICODBG_TRACE(("right-to-left g2p, count: %d", nCount)); + okay = TRUE; + + if (!saGetNrVowel(this, sa, graph, graphlen, nCount-1, &nrvow, + &ordvow)) { + nrvow = 0; + ordvow = 0; + } + + /* prepare input vector, set inside tree object invec, + * g2pBuildVector will call the constructInVec tree method */ + if (!picokdt_dtG2PconstructInVec(sa->dtg2p, + graph, /*grapheme start*/ + graphlen, /*grapheme length*/ + nCount-1, /*grapheme current position*/ + pos, /*Word POS*/ + nrvow, /*nr vowels if vowel, 0 else */ + ordvow, /*ord of vowel if vowel, 0 el*/ + &nPrimary, /*primary stress flag*/ + outNp1Ch, /*Right phoneme context +1*/ + outNp2Ch, /*Right phoneme context +2*/ + outNp3Ch)) { /*Right phon context +3*/ + /*Errors in preparing the input vector : skip processing*/ + PICODBG_WARN(("problem with invec")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, + NULL, NULL); + okay = FALSE; + } + + /* classify using the invec in the tree object and save the direct + tree output also in the tree object */ + if (okay && (!picokdt_dtG2Pclassify(sa->dtg2p, &nOutVal))) { + /* error doing classification */ + PICODBG_WARN(("problem classifying")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, + NULL, NULL); + okay = FALSE; + } + + /* decompose the invec in the tree object and return result in dtresv */ + if (okay && (!picokdt_dtG2PdecomposeOutClass(sa->dtg2p, &dtresv))) { + /* error decomposing */ + PICODBG_WARN(("problem decomposing")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_OUTVECTOR, + NULL, NULL); + okay = FALSE; + } + + if (okay) { + if ((dtresv.nr == 0) || (dtresv.classvec[0] == PICOKDT_EPSILON)) { + /* no phones to be added */ + PICODBG_TRACE(("epsilon, no phone added %c", graph[nCount-1])); + ; + } else { + /* add decomposed output to tmpbuf, reverse order */ + for (i = dtresv.nr; ((((PICOSA_MAXITEMSIZE - 1) - + phonesind) 0)); ) { + i--; + PICODBG_TRACE(("%c %d",graph[nCount-1],dtresv.classvec[i])); + if (dtresv.classvec[i] > 255) { + PICODBG_WARN(("dt result outside valid range, " + "skipping phone")); + continue; + } + sa->tmpbuf[phonesind--] = (picoos_uint8)dtresv.classvec[i]; + if (!nPrimary) { + if (picoktab_isPrimstress(sa->tabphones, + (picoos_uint8)dtresv.classvec[i])) { + nPrimary = 1; + } + } + (*plen)++; + } + if (i > 0) { + PICODBG_WARN(("phones skipped")); + picoos_emRaiseWarning(this->common->em, + PICO_WARN_INCOMPLETE, NULL, NULL); + } + } + } + + /*shift tree output history and update*/ + outNp3Ch = outNp2Ch; + outNp2Ch = outNp1Ch; + outNp1Ch = nOutVal; + + /* go backward one utf8 char */ + /* nCount is in +1 domain */ + if (nCount <= 1) { + /* end of str */ + nCount = 0; + } else { + utfpos = nCount - 1; + if (!picobase_get_prev_utf8charpos(graph, 0, &utfpos)) { + /* should not occur */ + PICODBG_ERROR(("invalid utf8 string, utfpos: %d", utfpos)); + return FALSE; + } else { + nCount = utfpos + 1; + } + } + } + + /* a must be: (PICOSA_MAXITEMSIZE-1) - phonesind == *plen */ + /* now that we have all phone IDs, copy in correct order to phones */ + /* phonesind point to next free slot in the reverse domainn, + ie. inc first */ + phonesind++; + for (i = 0; i < *plen; i++, phonesind++) { + phones[i] = sa->tmpbuf[phonesind]; + } + return TRUE; +} + + +/* item in headx[ind]/cbuf1, out: modified headx and cbuf2 */ + +static pico_status_t saGraphemeToPhoneme(register picodata_ProcessingUnit this, + register sa_subobj_t *sa, + picoos_uint16 ind) { + picoos_uint16 plen; + + PICODBG_TRACE(("starting g2p")); + + if (saDoG2P(this, sa, &(sa->cbuf1[sa->headx[ind].cind]), + sa->headx[ind].head.len, sa->headx[ind].head.info1, + &(sa->cbuf2[sa->cbuf2Len]), (sa->cbuf2BufSize - sa->cbuf2Len), + &plen)) { + + /* check of cbuf2Len done in saDoG2P, phones skipped if needed */ + if (plen > 255) { + PICODBG_WARN(("maximum number of phones exceeded (%d), skipping", + plen)); + plen = 255; + } + + /* set item head, info1, info2 unchanged */ + sa->headx[ind].head.type = PICODATA_ITEM_WORDPHON; + sa->headx[ind].head.len = (picoos_uint8)plen; + sa->headx[ind].cind = sa->cbuf2Len; + sa->cbuf2Len += plen; + PICODBG_DEBUG(("%c item, plen: %d", + PICODATA_ITEM_WORDPHON, plen)); + } else { + PICODBG_WARN(("problem doing g2p")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_PU_IRREG_ITEM, + NULL, NULL); + } + return PICO_OK; +} + + +/* ***********************************************************************/ +/* extract phonemes of an item into a phonBuf */ +/* ***********************************************************************/ + +static pico_status_t saAddPhoneme(register sa_subobj_t *sa, picoos_uint16 pos, picoos_uint16 sym) { + /* picoos_uint8 plane, unshifted; */ + + /* just for debuging */ + /* + unshifted = picotrns_unplane(sym,&plane); + PICODBG_DEBUG(("adding %i/%i (%c on plane %i) at phonBuf[%i]",pos,sym,unshifted,plane,sa->phonWritePos)); + */ + if (PICOTRNS_MAX_NUM_POSSYM <= sa->phonWritePos) { + /* not an error! */ + PICODBG_DEBUG(("couldn't add because phon buffer full")); + return PICO_EXC_BUF_OVERFLOW; + } else { + sa->phonBuf[sa->phonWritePos].pos = pos; + sa->phonBuf[sa->phonWritePos].sym = sym; + sa->phonWritePos++; + return PICO_OK; + } +} + +/* +static pico_status_t saAddStartPhoneme(register sa_subobj_t *sa) { + return saAddPhoneme(sa, PICOTRNS_POS_IGNORE, + (PICOKFST_PLANE_INTERN << 8) + sa->fixedIds->phonStartId); +} + + +static pico_status_t saAddTermPhoneme(register sa_subobj_t *sa) { + return saAddPhoneme(sa, PICOTRNS_POS_IGNORE, + (PICOKFST_PLANE_INTERN << 8) + sa->fixedIds->phonTermId); +} + +*/ + +static pico_status_t saExtractPhonemes(register picodata_ProcessingUnit this, + register sa_subobj_t *sa, picoos_uint16 pos, + picodata_itemhead_t* head, const picoos_uint8* content) +{ + pico_status_t rv= PICO_OK; + picoos_uint8 i; + picoos_int16 fstSymbol; +#if defined(PICO_DEBUG) + picoos_char msgstr[SA_MSGSTR_SIZE]; +#endif + + PICODBG_TRACE(("doing item %s", + picodata_head_to_string(head,msgstr,SA_MSGSTR_SIZE))); + /* + Items considered in a transduction are WORDPHON item. its starting offset within the inBuf is given as + 'pos'. + Elements that go into the transduction receive "their" position in the buffer. + */ + sa->phonWritePos = 0; + /* WORDPHON(POS,WACC)phon */ + rv = saAddPhoneme(sa, PICOTRNS_POS_IGNORE, + (PICOKFST_PLANE_INTERN << 8) + sa->fixedIds->phonStartId); + for (i = 0; i < head->len; i++) { + fstSymbol = /* (PICOKFST_PLANE_PHONEMES << 8) + */content[i]; + /* */ + PICODBG_TRACE(("adding phoneme %c",fstSymbol)); + rv = saAddPhoneme(sa, pos+PICODATA_ITEM_HEADSIZE+i, fstSymbol); + } + rv = saAddPhoneme(sa, PICOTRNS_POS_IGNORE, + (PICOKFST_PLANE_INTERN << 8) + sa->fixedIds->phonTermId); + sa->nextReadPos = pos + PICODATA_ITEM_HEADSIZE + head->len; + return rv; +} + + +#define SA_POSSYM_OK 0 +#define SA_POSSYM_OUT_OF_RANGE 1 +#define SA_POSSYM_END 2 +#define SA_POSSYM_INVALID -3 +/* *readPos is the next position in phonBuf to be read, and *writePos is the first position not to be read (may be outside + * buf). + * 'rangeEnd' is the first possym position outside the desired range. + * Possible return values: + * SA_POSSYM_OK : 'pos' and 'sym' are set to the read possym, *readPos is advanced + * SA_POSSYM_OUT_OF_RANGE : pos is out of range. 'pos' is set to that of the read possym, 'sym' is undefined + * SA_POSSYM_UNDERFLOW : no more data in buf. 'pos' is set to PICOTRNS_POS_INVALID, 'sym' is undefined + * SA_POSSYM_INVALID : "strange" pos. 'pos' is set to PICOTRNS_POS_INVALID, 'sym' is undefined + */ +static pico_status_t getNextPosSym(sa_subobj_t * sa, picoos_int16 * pos, picoos_int16 * sym, + picoos_int16 rangeEnd) { + /* skip POS_IGNORE */ + while ((sa->phonReadPos < sa->phonWritePos) && (PICOTRNS_POS_IGNORE == sa->phonBuf[sa->phonReadPos].pos)) { + PICODBG_DEBUG(("ignoring phone at sa->phonBuf[%i] because it has pos==IGNORE",sa->phonReadPos)); + sa->phonReadPos++; + } + if ((sa->phonReadPos < sa->phonWritePos)) { + *pos = sa->phonBuf[sa->phonReadPos].pos; + if ((PICOTRNS_POS_INSERT == *pos) || ((0 <= *pos) && (*pos < rangeEnd))) { + *sym = sa->phonBuf[sa->phonReadPos++].sym; + return SA_POSSYM_OK; + } else if (*pos < 0){ /* *pos is "strange" (e.g. POS_INVALID) */ + return SA_POSSYM_INVALID; + } else { + return SA_POSSYM_OUT_OF_RANGE; + } + } else { + /* no more possyms to read */ + *pos = PICOTRNS_POS_INVALID; + return SA_POSSYM_END; + } +} + + + + +/* ***********************************************************************/ +/* saStep function */ +/* ***********************************************************************/ + +/* +complete phrase processed in one step, if not fast enough -> rework + +init, collect into internal buffer, process, and then feed to +output buffer + +init state: INIT ext ext +state trans: in hc1 hc2 out + +INIT | putItem = 0 0 +1 | BUSY -> COLL (put B-SBEG item, + set do-init to false) + + inspace-ok-hc1 + needs-more-items-(phrase-or-flush) +COLL1 |getItems -n +n 0 1 | ATOMIC -> PPOSD (got items, + if flush set do-init) +COLL2 |getItems -n +n 1 0 | ATOMIC -> PPOSD (got items, forced) +COLL3 |getItems -n +n 1 1 | IDLE (got items, need more) +COLL4 |getItems = = 1 1 | IDLE (got no items) + +PPOSD | posd = ~n~n | BUSY -> PWP (posd done) +PWP | lex/g2p = ~n-n 0+n | BUSY -> PPHR (lex/g2p done) +PPHR | phr = -n 0 +m=n | BUSY -> PACC (phr done, m>=n) +PACC | acc = 0 0 ~m=n | BUSY -> FEED (acc done) + + doinit-flag +FEED | putItems 0 0 0 -m-n +m 0 | BUSY -> COLL (put items) +FEED | putItems 0 0 0 -m-n +m 1 | BUSY -> INIT (put items) +FEED | putItems 0 0 0 -d-d +d | OUT_FULL (put some items) +*/ + +static picodata_step_result_t saStep(register picodata_ProcessingUnit this, + picoos_int16 mode, + picoos_uint16 *numBytesOutput) { + register sa_subobj_t *sa; + pico_status_t rv = PICO_OK; + pico_status_t rvP = PICO_OK; + picoos_uint16 blen = 0; + picoos_uint16 clen = 0; + picoos_uint16 i; + picoklex_Lex lex; + + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + sa = (sa_subobj_t *) this->subObj; + mode = mode; /* avoid warning "var not used in this function"*/ + *numBytesOutput = 0; + while (1) { /* exit via return */ + PICODBG_DEBUG(("doing state %i, hLen|c1Len|c2Len: %d|%d|%d", + sa->procState, sa->headxLen, sa->cbuf1Len, + sa->cbuf2Len)); + + switch (sa->procState) { + + /* *********************************************************/ + /* collect state: get item(s) from charBuf and store in + * internal buffers, need a complete punctuation-phrase + */ + case SA_STEPSTATE_COLLECT: + + while (sa->inspaceok && sa->needsmoreitems + && (PICO_OK == + (rv = picodata_cbGetItem(this->cbIn, sa->tmpbuf, + PICOSA_MAXITEMSIZE, &blen)))) { + rvP = picodata_get_itemparts(sa->tmpbuf, + PICOSA_MAXITEMSIZE, + &(sa->headx[sa->headxLen].head), + &(sa->cbuf1[sa->cbuf1Len]), + sa->cbuf1BufSize-sa->cbuf1Len, + &clen); + if (rvP != PICO_OK) { + PICODBG_ERROR(("problem getting item parts")); + picoos_emRaiseException(this->common->em, rvP, + NULL, NULL); + return PICODATA_PU_ERROR; + } + + /* if CMD(...FLUSH...) -> PUNC(...FLUSH...), + construct PUNC-FLUSH item in headx */ + if ((sa->headx[sa->headxLen].head.type == + PICODATA_ITEM_CMD) && + (sa->headx[sa->headxLen].head.info1 == + PICODATA_ITEMINFO1_CMD_FLUSH)) { + sa->headx[sa->headxLen].head.type = + PICODATA_ITEM_PUNC; + sa->headx[sa->headxLen].head.info1 = + PICODATA_ITEMINFO1_PUNC_FLUSH; + sa->headx[sa->headxLen].head.info2 = + PICODATA_ITEMINFO2_PUNC_SENT_T; + sa->headx[sa->headxLen].head.len = 0; + } + + /* convert opening phoneme command to WORDPHON + * and assign user-POS XX to it (Bug 432) */ + sa->headx[sa->headxLen].cind = sa->cbuf1Len; + /* maybe overwritten later */ + if ((sa->headx[sa->headxLen].head.type == + PICODATA_ITEM_CMD) && + (sa->headx[sa->headxLen].head.info1 == + PICODATA_ITEMINFO1_CMD_PHONEME)&& + (sa->headx[sa->headxLen].head.info2 == + PICODATA_ITEMINFO2_CMD_START)) { + picoos_uint8 i; + picoos_uint8 wordsep = picoktab_getWordboundID(sa->tabphones); + PICODBG_INFO(("wordsep id is %i",wordsep)); + sa->headx[sa->headxLen].head.type = PICODATA_ITEM_WORDPHON; + sa->headx[sa->headxLen].head.info1 = PICODATA_POS_XX; + sa->headx[sa->headxLen].head.info2 = PICODATA_ITEMINFO2_NA; + /* cut off additional words */ + i = 0; + while ((i < sa->headx[sa->headxLen].head.len) && (wordsep != sa->cbuf1[sa->headx[sa->headxLen].cind+i])) { + PICODBG_INFO(("accepting phoneme %i",sa->cbuf1[sa->headx[sa->headxLen].cind+i])); + + i++; + } + if (i < sa->headx[sa->headxLen].head.len) { + PICODBG_INFO(("cutting off superfluous phonetic words at %i",i)); + sa->headx[sa->headxLen].head.len = i; + } + } + + /* check/set needsmoreitems */ + if (sa->headx[sa->headxLen].head.type == + PICODATA_ITEM_PUNC) { + sa->needsmoreitems = FALSE; + } + + /* check/set inspaceok, keep spare slot for forcing */ + if ((sa->headxLen >= (PICOSA_MAXNR_HEADX - 2)) || + ((sa->cbuf1BufSize - sa->cbuf1Len) < + PICOSA_MAXITEMSIZE)) { + sa->inspaceok = FALSE; + } + + if (clen > 0) { + sa->headx[sa->headxLen].cind = sa->cbuf1Len; + sa->cbuf1Len += clen; + } else { + sa->headx[sa->headxLen].cind = 0; + } + sa->headxLen++; + } + + if (!sa->needsmoreitems) { + /* 1, phrase buffered */ + sa->procState = SA_STEPSTATE_PROCESS_POSD; + return PICODATA_PU_ATOMIC; + } else if (!sa->inspaceok) { + /* 2, forced phrase end */ + /* at least one slot is still free, use it to + force a trailing PUNC item */ + sa->headx[sa->headxLen].head.type = PICODATA_ITEM_PUNC; + sa->headx[sa->headxLen].head.info1 = + PICODATA_ITEMINFO1_PUNC_PHRASEEND; + sa->headx[sa->headxLen].head.info2 = + PICODATA_ITEMINFO2_PUNC_PHRASE_FORCED; + sa->headx[sa->headxLen].head.len = 0; + sa->needsmoreitems = FALSE; /* not really needed for now */ + sa->headxLen++; + PICODBG_WARN(("forcing phrase end, added PUNC_PHRASEEND")); + picoos_emRaiseWarning(this->common->em, + PICO_WARN_FALLBACK, NULL, + (picoos_char *)"forced phrase end"); + sa->procState = SA_STEPSTATE_PROCESS_POSD; + return PICODATA_PU_ATOMIC; + } else if (rv == PICO_EOF) { + /* 3, 4 */ + return PICODATA_PU_IDLE; + } else if ((rv == PICO_EXC_BUF_UNDERFLOW) || + (rv == PICO_EXC_BUF_OVERFLOW)) { + /* error, no valid item in cb (UNDER) */ + /* or tmpbuf not large enough, not possible (OVER) */ + /* no exception raised, left for ctrl to handle */ + PICODBG_ERROR(("buffer under/overflow, rv: %d", rv)); + return PICODATA_PU_ERROR; + } else { + /* error, only possible if cbGetItem implementation + changes without this function being adapted*/ + PICODBG_ERROR(("untreated return value, rv: %d", rv)); + return PICODATA_PU_ERROR; + } + break; + + + /* *********************************************************/ + /* process posd state: process items in headx/cbuf1 + * and change in place + */ + case SA_STEPSTATE_PROCESS_POSD: + /* ensure there is an item in inBuf */ + if (sa->headxLen > 0) { + /* we have a phrase in headx, cbuf1 (can be + single PUNC item without POS), do pos disamb */ + if (PICO_OK != saDisambPos(this, sa)) { + picoos_emRaiseException(this->common->em, + PICO_ERR_OTHER, NULL, NULL); + return PICODATA_PU_ERROR; + } + sa->procState = SA_STEPSTATE_PROCESS_WPHO; + + } else if (sa->headxLen == 0) { /* no items in inBuf */ + PICODBG_WARN(("no items in inBuf")); + sa->procState = SA_STEPSTATE_COLLECT; + return PICODATA_PU_BUSY; + } + +#if defined (PICO_DEBUG) + if (1) { + picoos_uint8 i, j, ittype; + for (i = 0; i < sa->headxLen; i++) { + ittype = sa->headx[i].head.type; + PICODBG_INFO_CTX(); + PICODBG_INFO_MSG(("sa-d: (")); + PICODBG_INFO_MSG(("'%c',", ittype)); + if ((32 <= sa->headx[i].head.info1) && + (sa->headx[i].head.info1 < 127) && + (ittype != PICODATA_ITEM_WORDGRAPH) && + (ittype != PICODATA_ITEM_WORDINDEX)) { + PICODBG_INFO_MSG(("'%c',",sa->headx[i].head.info1)); + } else { + PICODBG_INFO_MSG(("%3d,", sa->headx[i].head.info1)); + } + if ((32 <= sa->headx[i].head.info2) && + (sa->headx[i].head.info2 < 127)) { + PICODBG_INFO_MSG(("'%c',",sa->headx[i].head.info2)); + } else { + PICODBG_INFO_MSG(("%3d,", sa->headx[i].head.info2)); + } + PICODBG_INFO_MSG(("%3d)", sa->headx[i].head.len)); + + for (j = 0; j < sa->headx[i].head.len; j++) { + if ((ittype == PICODATA_ITEM_WORDGRAPH) || + (ittype == PICODATA_ITEM_CMD)) { + PICODBG_INFO_MSG(("%c", + sa->cbuf1[sa->headx[i].cind+j])); + } else { + PICODBG_INFO_MSG(("%4d", + sa->cbuf1[sa->headx[i].cind+j])); + } + } + PICODBG_INFO_MSG(("\n")); + } + } +#endif + + break; + + + /* *********************************************************/ + /* process wpho state: process items in headx/cbuf1 and modify + * headx in place and fill cbuf2 + */ + case SA_STEPSTATE_PROCESS_WPHO: + /* ensure there is an item in inBuf */ + if (sa->headxLen > 0) { + /* we have a phrase in headx, cbuf1 (can be single + PUNC item), do lex lookup, g2p, or copy */ + + /* check if cbuf2 is empty as it should be */ + if (sa->cbuf2Len > 0) { + /* enforce emptyness */ + PICODBG_WARN(("forcing empty cbuf2, discarding buf")); + picoos_emRaiseWarning(this->common->em, + PICO_WARN_PU_DISCARD_BUF, + NULL, NULL); + } + + /* cbuf2 overflow avoided in saGrapheme*, saLexInd*, + saCopyItem*, phones skipped if needed */ + for (i = 0; i < sa->headxLen; i++) { + switch (sa->headx[i].head.type) { + case PICODATA_ITEM_WORDGRAPH: + if (PICO_OK != saGraphemeToPhoneme(this, sa, + i)) { + /* not possible, phones skipped if needed */ + picoos_emRaiseException(this->common->em, + PICO_ERR_OTHER, + NULL, NULL); + return PICODATA_PU_ERROR; + } + break; + case PICODATA_ITEM_WORDINDEX: + if (0 == sa->headx[i].head.info2) { + lex = sa->lex; + } else { + lex = sa->ulex[sa->headx[i].head.info2-1]; + } + if (PICO_OK != saLexIndLookup(this, sa, lex, i)) { + /* not possible, phones skipped if needed */ + picoos_emRaiseException(this->common->em, + PICO_ERR_OTHER, + NULL, NULL); + return PICODATA_PU_ERROR; + } + break; + default: + /* copy item unmodified, ie. headx untouched, + content from cbuf1 to cbuf2 */ + if (PICO_OK != saCopyItemContent1to2(this, sa, + i)) { + /* not possible, phones skipped if needed */ + picoos_emRaiseException(this->common->em, + PICO_ERR_OTHER, + NULL, NULL); + return PICODATA_PU_ERROR; + } + break; + } + } + /* set cbuf1 to empty */ + sa->cbuf1Len = 0; + sa->procState = SA_STEPSTATE_PROCESS_TRNS_PARSE; + + } else if (sa->headxLen == 0) { /* no items in inBuf */ + PICODBG_WARN(("no items in inBuf")); + sa->procState = SA_STEPSTATE_COLLECT; + return PICODATA_PU_BUSY; + } + +#if defined (PICO_DEBUG) + if (1) { + picoos_uint8 i, j, ittype; + for (i = 0; i < sa->headxLen; i++) { + ittype = sa->headx[i].head.type; + PICODBG_INFO_CTX(); + PICODBG_INFO_MSG(("sa-g: (")); + PICODBG_INFO_MSG(("'%c',", ittype)); + if ((32 <= sa->headx[i].head.info1) && + (sa->headx[i].head.info1 < 127) && + (ittype != PICODATA_ITEM_WORDPHON)) { + PICODBG_INFO_MSG(("'%c',",sa->headx[i].head.info1)); + } else { + PICODBG_INFO_MSG(("%3d,", sa->headx[i].head.info1)); + } + if ((32 <= sa->headx[i].head.info2) && + (sa->headx[i].head.info2 < 127)) { + PICODBG_INFO_MSG(("'%c',",sa->headx[i].head.info2)); + } else { + PICODBG_INFO_MSG(("%3d,", sa->headx[i].head.info2)); + } + PICODBG_INFO_MSG(("%3d)", sa->headx[i].head.len)); + + for (j = 0; j < sa->headx[i].head.len; j++) { + if ((ittype == PICODATA_ITEM_CMD)) { + PICODBG_INFO_MSG(("%c", + sa->cbuf2[sa->headx[i].cind+j])); + } else { + PICODBG_INFO_MSG(("%4d", + sa->cbuf2[sa->headx[i].cind+j])); + } + } + PICODBG_INFO_MSG(("\n")); + } + } +#endif + + break; + + + /* *********************************************************/ + /* transduction parse state: extract phonemes of item in internal outBuf */ + case SA_STEPSTATE_PROCESS_TRNS_PARSE: + + PICODBG_DEBUG(("transduce item (bot, remain): (%d, %d)", + sa->headxBottom, sa->headxLen)); + + /* check for termination condition first */ + if (0 == sa->headxLen) { + /* reset headx, cbuf2 */ + sa->headxBottom = 0; + sa->cbuf2Len = 0; + /* reset collect state support variables */ + sa->inspaceok = TRUE; + sa->needsmoreitems = TRUE; + + sa->procState = SA_STEPSTATE_COLLECT; + return PICODATA_PU_BUSY; + } + + sa->procState = SA_STEPSTATE_FEED; + /* copy item unmodified */ + rv = picodata_put_itemparts( + &(sa->headx[sa->headxBottom].head), + &(sa->cbuf2[sa->headx[sa->headxBottom].cind]), + sa->headx[sa->headxBottom].head.len, sa->tmpbuf, + PICOSA_MAXITEMSIZE, &blen); + + if (PICODATA_ITEM_WORDPHON == sa->headx[sa->headxBottom].head.type) { + PICODBG_DEBUG(("PARSE found WORDPHON")); + rv = saExtractPhonemes(this, sa, 0, &(sa->headx[sa->headxBottom].head), + &(sa->cbuf2[sa->headx[sa->headxBottom].cind])); + if (PICO_OK == rv) { + PICODBG_DEBUG(("PARSE successfully returned from phoneme extraction")); + sa->procState = SA_STEPSTATE_PROCESS_TRNS_FST; + } else { + PICODBG_WARN(("PARSE phone extraction returned exception %i, output WORDPHON untransduced",rv)); + } + } else { + PICODBG_DEBUG(("PARSE found other item, just copying")); + } + if (SA_STEPSTATE_FEED == sa->procState) { + PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], + (picoos_uint8 *)"sa-p: ", + sa->tmpbuf, PICOSA_MAXITEMSIZE); + + } + + /* consume item */ + sa->headxBottom++; + sa->headxLen--; + + break; + + /* *********************************************************/ + /* transduce state: copy item in internal outBuf to tmpBuf and transduce */ + case SA_STEPSTATE_PROCESS_TRNS_FST: + + + + + + /* if no word-level FSTs: doing trivial syllabification instead */ + if (0 == sa->numFsts) { + PICODBG_DEBUG(("doing trivial sylabification with %i phones", sa->phonWritePos)); +#if defined(PICO_DEBUG) + { + PICODBG_INFO_CTX(); + PICODBG_INFO_MSG(("sa trying to trivially syllabify: ")); + PICOTRNS_PRINTSYMSEQ(this->voice->kbArray[PICOKNOW_KBID_DBG], sa->phonBuf, sa->phonWritePos); + PICODBG_INFO_MSG(("\n")); + } +#endif + + picotrns_trivial_syllabify(sa->tabphones, sa->phonBuf, + sa->phonWritePos, sa->phonBufOut, + &sa->phonWritePos,PICOTRNS_MAX_NUM_POSSYM); + PICODBG_DEBUG(("returned from trivial sylabification with %i phones", sa->phonWritePos)); +#if defined(PICO_DEBUG) + { + PICODBG_INFO_CTX(); + PICODBG_INFO_MSG(("sa returned from syllabification: ")); + PICOTRNS_PRINTSYMSEQ(this->voice->kbArray[PICOKNOW_KBID_DBG], sa->phonBufOut, sa->phonWritePos); + PICODBG_INFO_MSG(("\n")); + } +#endif + + /* eliminate deep epsilons */ + PICODBG_DEBUG(("doing epsilon elimination with %i phones", sa->phonWritePos)); + picotrns_eliminate_epsilons(sa->phonBufOut, + sa->phonWritePos, sa->phonBuf, + &sa->phonWritePos,PICOTRNS_MAX_NUM_POSSYM); + PICODBG_DEBUG(("returning from epsilon elimination with %i phones", sa->phonWritePos)); + sa->phonReadPos = 0; + sa->phonesTransduced = 1; + sa->procState = SA_STEPSTATE_FEED; + break; + } + + /* there are word-level FSTs */ + /* termination condition first */ + if (sa->curFst >= sa->numFsts) { + /* reset for next transduction */ + sa->curFst = 0; + sa->phonReadPos = 0; + sa->phonesTransduced = 1; + sa->procState = SA_STEPSTATE_FEED; + break; + } + + /* transduce from phonBufIn to PhonBufOut */ + { + + picoos_uint32 nrSteps; +#if defined(PICO_DEBUG) + { + PICODBG_INFO_CTX(); + PICODBG_INFO_MSG(("sa trying to transduce: ")); + PICOTRNS_PRINTSYMSEQ(this->voice->kbArray[PICOKNOW_KBID_DBG], sa->phonBuf, sa->phonWritePos); + PICODBG_INFO_MSG(("\n")); + } +#endif + picotrns_transduce(sa->fst[sa->curFst], FALSE, + picotrns_printSolution, sa->phonBuf, sa->phonWritePos, sa->phonBufOut, + &sa->phonWritePos, + PICOTRNS_MAX_NUM_POSSYM, sa->altDescBuf, + sa->maxAltDescLen, &nrSteps); +#if defined(PICO_DEBUG) + { + PICODBG_INFO_CTX(); + PICODBG_INFO_MSG(("sa returned from transduction: ")); + PICOTRNS_PRINTSYMSEQ(this->voice->kbArray[PICOKNOW_KBID_DBG], sa->phonBufOut, sa->phonWritePos); + PICODBG_INFO_MSG(("\n")); + } +#endif + } + + + + /* + The trasduction output will contain equivalent items i.e. (x,y') for each (x,y) plus inserted deep symbols (-1,d). + In case of deletions, (x,0) might also be omitted... + */ + /* eliminate deep epsilons */ + picotrns_eliminate_epsilons(sa->phonBufOut, + sa->phonWritePos, sa->phonBuf, &sa->phonWritePos,PICOTRNS_MAX_NUM_POSSYM); + sa->phonesTransduced = 1; + + sa->curFst++; + + return PICODATA_PU_ATOMIC; + /* break; */ + + /* *********************************************************/ + /* feed state: copy item in internal outBuf to output charBuf */ + + case SA_STEPSTATE_FEED: + + PICODBG_DEBUG(("FEED")); + + if (sa->phonesTransduced) { + /* replace original phones by transduced */ + picoos_uint16 phonWritePos = PICODATA_ITEM_HEADSIZE; + picoos_uint8 plane; + picoos_int16 sym, pos; + while (SA_POSSYM_OK == (rv = getNextPosSym(sa,&pos,&sym,sa->nextReadPos))) { + PICODBG_TRACE(("FEED inserting phoneme %c into inBuf[%i]",sym,phonWritePos)); + sym = picotrns_unplane(sym, &plane); + PICODBG_ASSERT((PICOKFST_PLANE_PHONEMES == plane)); + sa->tmpbuf[phonWritePos++] = (picoos_uint8) sym; + } + PICODBG_DEBUG(("FEED setting item length to %i",phonWritePos - PICODATA_ITEM_HEADSIZE)); + picodata_set_itemlen(sa->tmpbuf,PICODATA_ITEM_HEADSIZE,phonWritePos - PICODATA_ITEM_HEADSIZE); + if (SA_POSSYM_INVALID == rv) { + PICODBG_ERROR(("FEED unexpected symbol or unexpected end of phoneme list")); + return (picodata_step_result_t)picoos_emRaiseException(this->common->em, PICO_WARN_INCOMPLETE, NULL, NULL); + } + sa->phonesTransduced = 0; + + } /* if (sa->phonesTransduced) */ + + + rvP = picodata_cbPutItem(this->cbOut, sa->tmpbuf, + PICOSA_MAXITEMSIZE, &clen); + + *numBytesOutput += clen; + + PICODBG_DEBUG(("put item, status: %d", rvP)); + + if (rvP == PICO_OK) { + } else if (rvP == PICO_EXC_BUF_OVERFLOW) { + /* try again next time */ + PICODBG_DEBUG(("feeding overflow")); + return PICODATA_PU_OUT_FULL; + } else { + /* error, should never happen */ + PICODBG_ERROR(("untreated return value, rvP: %d", rvP)); + return PICODATA_PU_ERROR; + } + + PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], + (picoos_uint8 *)"sana: ", + sa->tmpbuf, PICOSA_MAXITEMSIZE); + + sa->procState = SA_STEPSTATE_PROCESS_TRNS_PARSE; + /* return PICODATA_PU_BUSY; */ + break; + + default: + break; + } /* switch */ + + } /* while */ + + /* should be never reached */ + PICODBG_ERROR(("reached end of function")); + picoos_emRaiseException(this->common->em, PICO_ERR_OTHER, NULL, NULL); + return PICODATA_PU_ERROR; +} + +#ifdef __cplusplus +} +#endif + + +/* end */ diff --git a/pico/lib/picosa.h b/pico/lib/picosa.h new file mode 100644 index 0000000..c35da2e --- /dev/null +++ b/pico/lib/picosa.h @@ -0,0 +1,216 @@ +/* + * 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 picosa.h + * + * sentence analysis - POS disambiguation - Include file + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + + +/** @addtogroup picosa + * ---------------------------------------------------\n + * Pico Sentence analysis \n + * ---------------------------------------------------\n + * +itemtype, iteminfo1, iteminfo2, content -> TYPE(INFO1,INFO2)content +in the following + +items input +=========== + +processed by sa (POS disambiguation): +- WORDGRAPH(POSes,NA)graph +- WORDINDEX(POSes,NA)POS|1ind1...POSN|indN +- CMD(PICODATA_ITEMINFO1_CMD_FLUSH,PICODATA_ITEMINFO2_NA) + +processed by sa (Phrasing, Accentuation): +- PUNC(PUNCtype,PUNCsubtype) + +unprocessed: +- all other item types are forwarded through the PU without modification: + CMD + + +minimal input size (before processing starts) +================== + +processing (POS disambiguation, g2p, lexind, phrasing, accentuation) +is possible with + +- one punctuation-phrase, consisting of a sequence (see below for + limits) of items terminated by a PUNC item. + +(possible but not implemented: as long as the internal buffer is +empty, non-processed item types can be processed immediately) + +Ensuring terminal PUNC item: +- when reading items from the external buffer a CMD(...FLUSH...) is + converted to a PUNC(...FLUSH...) item +- If needed, a PUNC(PHRASE) is artificially added to ensure a phrase + fits in the PUs memory and processing can start. + + +items processed and output +========================== + +precondition: +CMD(...FLUSH...) already converted to PUNC(...FLUSH...) and trailing +PUNC item enforced if necessary. + +---- +1. PROCESS_POSD: processing input WORDGRAPH or WORDINDEX items, after +POS disambiguation (POSes -> POS), results in a sequence of: + +-> WORDGRAPH(POS,NA)graph +-> WORDINDEX(POS,NA)POS|ind + +---- +2. PROCESS_WPHO: then, after lex-index lookup and G2P in a +sequence of: + +-> WORDPHON(POS,NA)phon + +(phon containing primary and secondary word-level stress) + +---- +3. PROCESS_PHR: then, after processing these WORDPHON items, +together with the trailing PUNC item results in: + +-> BOUND(BOUNDstrength,BOUNDtype) + +being added in the sequence of WORDPHON (respectively inserted instead +of the PUNC). All PUNC, incl PUNC(...FLUSH...) now gone. + +---- +4. PROCESS_ACC: then, after processing the WORDPHON and BOUND items +results in: + +-> WORDPHON(POS,ACC)phon + +A postprocessing step of accentuation is hard-coded in the +accentuation module: In case the whole word does not have any stress +at all (primary or secondary or both) then do the following mapping: + + ACC0 nostress -> ACC0 + ACC1 nostress -> ACC3 + ACC2 nostress -> ACC3 + ACC3 nostress -> ACC3 + +---- +- POS + a single, unambiguous POS + +cf. picodata.h for +- ACC (sentence-level accent (aka prominence)) %d + PICODATA_ACC0 + PICODATA_ACC1 + PICODATA_ACC2 (<- maybe mapped to ACC1, ie. no ACC2 in output) + PICODATA_ACC3 + +- BOUNDstrength %d + PICODATA_ITEMINFO1_BOUND_SBEG (at sentence start) + PICODATA_ITEMINFO1_BOUND_SEND (at sentence end) + PICODATA_ITEMINFO1_BOUND_TERM (replaces a flush) + PICODATA_ITEMINFO1_BOUND_PHR1 (primary boundary) + PICODATA_ITEMINFO1_BOUND_PHR2 (short break) + PICODATA_ITEMINFO1_BOUND_PHR3 (secondary phrase boundary, no break) + PICODATA_ITEMINFO1_BOUND_PHR0 (no break, not produced by sa, not existing + BOUND in item sequence equals PHR0 bound strength) + +- BOUNDtype (created in sa base on punctuation, indicates type of phrase + following the boundary) %d + PICODATA_ITEMINFO2_BOUNDTYPE_P + PICODATA_ITEMINFO2_BOUNDTYPE_T + PICODATA_ITEMINFO2_BOUNDTYPE_Q + PICODATA_ITEMINFO2_BOUNDTYPE_E + + +output sequence (without CMDs): + + = { BOUND(BOUND_SBEG,PHRASEtype) BOUND(BOUND_SEND,..)} BOUND(BOUND_TERM,..) + + + = { BOUND(BOUND_PHR1|2|3,BOUNDtype) } + + = WORDPHON(POS,ACC)phon { WORDPHON(POS,ACC)phon } + + +Done in later PU: mapping ACC & word-level stress to syllable accent value + ACC0 prim -> 0 + ACC1 prim -> 1 + ACC2 prim -> 2 + ACC3 prim -> 3 + ACC0 sec -> 0 + ACC1 sec -> 4 + ACC2 sec -> 4 + ACC3 sec -> 4 + + +other limitations +================= + +- item size: header plus len=256 (valid for Pico in general) +- see defines below for max nr of items. Item heads plus ref. to contents + buffer are stored in array with fixed size elements. Two restrictions: + - MAXNR_HEADX (max nr elements==items in headx array) + - CONTENTSSIZE (max size of all contents together + */ + + +#ifndef PICOSA_H_ +#define PICOSA_H_ + +#include "picoos.h" +#include "picodata.h" +#include "picorsrc.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* nr item restriction: maximum number of extended item heads in headx */ +#define PICOSA_MAXNR_HEADX 60 +/* nr item restriction: maximum size of all item contents together in cont */ +#define PICOSA_MAXSIZE_CBUF 7680 + +/* maximum length of an item incl. head for input GetItem buffer */ +#define PICOSA_MAXITEMSIZE 260 + + +picodata_ProcessingUnit picosa_newSentAnaUnit( + picoos_MemoryManager mm, + picoos_Common common, + picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, + picorsrc_Voice voice); + +#ifdef __cplusplus +} +#endif + + +#endif /*PICOSA_H_*/ diff --git a/pico/lib/picosig.c b/pico/lib/picosig.c new file mode 100644 index 0000000..be44b3c --- /dev/null +++ b/pico/lib/picosig.c @@ -0,0 +1,1280 @@ +/* + * 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 picosig.c + * + * Signal Generation PU - Implementation + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#include "picoos.h" +#include "picodsp.h" +#include "picosig2.h" +#include "picodata.h" +#include "picosig.h" +#include "picodbg.h" +#include "picokpdf.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +#define PICOSIG_IN_BUFF_SIZE PICODATA_BUFSIZE_SIG /*input buffer size for SIG */ +#define PICOSIG_OUT_BUFF_SIZE PICODATA_BUFSIZE_SIG /*output buffer size for SIG*/ + +#define PICOSIG_COLLECT 0 +#define PICOSIG_SCHEDULE 1 +#define PICOSIG_PLAY 2 +#define PICOSIG_PROCESS 3 +#define PICOSIG_FEED 4 + +/*---------------------------------------------------------- + // Internal function declarations + //---------------------------------------------------------*/ + +static picodata_step_result_t sigStep(register picodata_ProcessingUnit this, + picoos_int16 mode, picoos_uint16 * numBytesOutput); + +/*---------------------------------------------------------- + // Name : sig_subobj + // Function: subobject definition for the sig processing + // Shortcut: sig + //---------------------------------------------------------*/ +typedef struct sig_subobj +{ + /*----------------------PU voice management------------------------------*/ + /* picorsrc_Voice voice; */ + /*----------------------PU state management------------------------------*/ + picoos_uint8 procState; /* where to take up work at next processing step */ + picoos_uint8 retState; /* where to return after next processing step */ + picoos_uint8 needMoreInput; /* more data necessary to start processing */ + /*----------------------PU input management------------------------------*/ + picoos_uint8 inBuf[PICOSIG_IN_BUFF_SIZE]; /* internal input buffer */ + picoos_uint16 inBufSize;/* actually allocated size */ + picoos_uint16 inReadPos, inWritePos; /* next pos to read/write from/to inBuf*/ + /*Input audio file management*/ + picoos_char sInSDFileName[255]; + picoos_SDFile sInSDFile; + picoos_uint32 sInSDFilePos; + /*----------------------PU output management-----------------------------*/ + picoos_uint8 outBuf[PICOSIG_OUT_BUFF_SIZE]; /* internal output buffer */ + picoos_uint16 outBufSize; /* actually allocated size */ + picoos_uint16 outReadPos, outWritePos; /* next pos to read/write from/to outBuf*/ + picoos_bool outSwitch; /* output destination switch 0:buffer, 1:file*/ + picoos_char sOutSDFileName[255]; /* output file name */ + picoos_SDFile sOutSDFile; /* output file handle */ + picoos_single fSampNorm; /* running normalization factor */ + picoos_uint32 nNumFrame; /* running count for frame number in output items */ + /*---------------------- other working variables ---------------------------*/ + picoos_uint8 innerProcState; /*where to take up work at next processing step*/ + /*-----------------------Definition of the local storage for this PU--------*/ + sig_innerobj_t sig_inner; + picoos_single pMod; /*pitch modifier*/ + picoos_single vMod; /*Volume modifier*/ + picoos_single sMod; /*speaker modifier*/ + /*knowledge bases */ + picokpdf_PdfMUL pdflfz, pdfmgc; + picoos_uint32 scmeanpowLFZ, scmeanpowMGC; + picoos_uint32 scmeanLFZ, scmeanMGC; + picokpdf_PdfPHS pdfphs; + +} sig_subobj_t; + +/* ****************************************************************************** + * generic PU management + ********************************************************************************/ + +/** + * initialization of the PU (processing unit) + * @param this : sig PU object + * @return PICO_OK : init ok + * @return PICO_ERR_OTHER : init failed + * @callgraph + * @callergraph + */ +static pico_status_t sigInitialize(register picodata_ProcessingUnit this) +{ + sig_subobj_t *sig_subObj; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + sig_subObj = (sig_subobj_t *) this->subObj; + sig_subObj->inBufSize = PICOSIG_IN_BUFF_SIZE; + sig_subObj->outBufSize = PICOSIG_OUT_BUFF_SIZE; + sig_subObj->inReadPos = 0; + sig_subObj->inWritePos = 0; + sig_subObj->outReadPos = 0; + sig_subObj->outWritePos = 0; + sig_subObj->needMoreInput = 0; + sig_subObj->procState = PICOSIG_COLLECT; + sig_subObj->retState = PICOSIG_COLLECT; + sig_subObj->innerProcState = 0; + sig_subObj->nNumFrame = 0; + + /*----------------------------------------------------------------- + * MANAGE Item I/O control management + ------------------------------------------------------------------*/ + sig_subObj->sInSDFile = NULL; + sig_subObj->sInSDFilePos = 0; + sig_subObj->sInSDFileName[0] = '\0'; + sig_subObj->outSwitch = 0; /*PU sends output to buffer (nextPU)*/ + sig_subObj->sOutSDFile = NULL; + sig_subObj->sOutSDFileName[0] = '\0'; + sig_subObj->nNumFrame = 0; + + /*----------------------------------------------------------------- + * MANAGE LINGWARE INITIALIZATION IF NEEDED + ------------------------------------------------------------------*/ + sig_subObj->pdfmgc = picokpdf_getPdfMUL( + this->voice->kbArray[PICOKNOW_KBID_PDF_MGC]); + sig_subObj->pdflfz = picokpdf_getPdfMUL( + this->voice->kbArray[PICOKNOW_KBID_PDF_LFZ]); + sig_subObj->pdfphs = picokpdf_getPdfPHS( + this->voice->kbArray[PICOKNOW_KBID_PDF_PHS]); + + sig_subObj->scmeanpowLFZ = sig_subObj->pdflfz->bigpow + - sig_subObj->pdflfz->meanpow; + sig_subObj->scmeanpowMGC = sig_subObj->pdfmgc->bigpow + - sig_subObj->pdfmgc->meanpow; + sig_subObj->scmeanLFZ = (1 << (picoos_uint32) sig_subObj->scmeanpowLFZ); + sig_subObj->scmeanMGC = (1 << (picoos_uint32) sig_subObj->scmeanpowMGC); + sig_subObj->fSampNorm = PICOSIG_NORM1 * sig_subObj->pdfmgc->amplif; + + /*----------------------------------------------------------------- + * Initialize memory for DSP + * ------------------------------------------------------------------*/ + sigDspInitialize(&(sig_subObj->sig_inner)); + + /*----------------------------------------------------------------- + * Initialize modifiers + * ------------------------------------------------------------------*/ + /*pitch , volume , speaker modifiers*/ + sig_subObj->pMod = 1.0f; + sig_subObj->vMod = 1.0f; + sig_subObj->sMod = 1.0f; + + return PICO_OK; +}/*sigInitialize*/ + +/** + * terminates the PU (processing unit) + * @param this : sig PU object + * @return PICO_OK : termination ok + * @return PICO_ERR_OTHER : termination failed + * @callgraph + * @callergraph + */ +static pico_status_t sigTerminate(register picodata_ProcessingUnit this) +{ + + sig_subobj_t *sig_subObj; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + sig_subObj = (sig_subobj_t *) this->subObj; + + return PICO_OK; +}/*sigTerminate*/ + +/** + * deallocates the PU (processing unit) sub object + * @param this : sig PU object + * @param mm : the engine memory manager + * @return PICO_OK : deallocation ok + * @return PICO_ERR_OTHER : deallocation failed + * @callgraph + * @callergraph + */ +static pico_status_t sigSubObjDeallocate(register picodata_ProcessingUnit this, + picoos_MemoryManager mm) +{ + sig_subobj_t *sig_subObj; + if ((NULL == this) || ((this)->subObj == NULL)) { + return PICO_ERR_OTHER; + } + sig_subObj = (sig_subobj_t *) (this)->subObj; + + if (sig_subObj->sInSDFile != NULL) { + picoos_sdfCloseIn(this->common, &(sig_subObj->sInSDFile)); + sig_subObj->sInSDFile = NULL; + sig_subObj->sInSDFileName[0] = '\0'; + } + + if (sig_subObj->sOutSDFile != NULL) { + picoos_sdfCloseOut(this->common, &(sig_subObj->sOutSDFile)); + sig_subObj->sOutSDFile = NULL; + sig_subObj->sOutSDFileName[0] = '\0'; + } + + sigDeallocate(mm, &(sig_subObj->sig_inner)); + + picoos_deallocate(this->common->mm, (void *) &this->subObj); + + return PICO_OK; +}/*sigSubObjDeallocate*/ + +/** + * creates a new sig processing unit + * @param mm : the engine memory manager + * @param common : the engine common object + * @param cbIn : the PU input buffer + * @param cbOut : the PU output buffer + * @param voice : the voice descriptor object + * @return a valid PU handle if creation is OK + * @return NULL if creation is !=OK + * @callgraph + * @callergraph + */ +picodata_ProcessingUnit picosig_newSigUnit(picoos_MemoryManager mm, + picoos_Common common, picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, picorsrc_Voice voice) +{ + sig_subobj_t *sig_subObj; + + picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, + cbOut, voice); + if (NULL == this) { + return NULL; + } + this->initialize = sigInitialize; + + PICODBG_DEBUG(("picosig_newSigUnit -- creating SIG PU")); + /*Init function pointers*/ + this->step = sigStep; + this->terminate = sigTerminate; + this->subDeallocate = sigSubObjDeallocate; + /*sub obj allocation*/ + this->subObj = picoos_allocate(mm, sizeof(sig_subobj_t)); + + if (NULL == this->subObj) { + PICODBG_ERROR(("Error in Sig Object allocation")); + picoos_deallocate(mm, (void *) &this); + return NULL; + } + sig_subObj = (sig_subobj_t *) this->subObj; + + /*----------------------------------------------------------------- + * Allocate memory for DSP inner algorithms + * ------------------------------------------------------------------*/ + if (sigAllocate(mm, &(sig_subObj->sig_inner)) != 0) { + PICODBG_ERROR(("Error in Sig Sub Object Allocation")); + picoos_deallocate(mm, (void *) &this); + return NULL; + } + + /*----------------------------------------------------------------- + * Initialize memory for DSP (this may be re-used elsewhere, e.g.Reset) + * ------------------------------------------------------------------*/ + if (PICO_OK != sigInitialize(this)) { + PICODBG_ERROR(("Error in iSig Sub Object initialization")); + sigDeallocate(mm, &(sig_subObj->sig_inner)); + picoos_deallocate(mm, (void *) &this); + return NULL; + }PICODBG_DEBUG(("SIG PU creation succeded!!")); + return this; +}/*picosig_newSigUnit*/ + +/** + * pdf access for phase + * @param this : sig object pointer + * @param phsIndex : index of phase vectot in the pdf + * @param phsVect : pointer to base of array where to store the phase values + * @param numComponents : pointer to the variable to store the number of components + * @return PICO_OK : pdf retrieved + * @return PICO_ERR_OTHER : pdf not retrieved + * @callgraph + * @callergraph + */ +static pico_status_t getPhsFromPdf(register picodata_ProcessingUnit this, + picoos_uint16 phsIndex, picoos_int32 *phsVect, + picoos_int16 *numComponents) +{ + sig_subobj_t *sig_subObj; + picokpdf_PdfPHS pdf; + static int nFrame = 0; + + picoos_uint32 nIndexValue; + picoos_uint8 *nCurrIndexOffset, *nContent; + picoos_uint16 nI; + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + sig_subObj = (sig_subobj_t *) this->subObj; + pdf = sig_subObj->pdfphs; + /*check incoming index*/ + if (phsIndex >= pdf->numvectors) { + return PICODATA_PU_ERROR; + } + nCurrIndexOffset = ((picoos_uint8*) pdf->indexBase) + phsIndex * sizeof(picoos_uint32); + nIndexValue = (0xFF000000 & ((*(nCurrIndexOffset+3)) << 24)) | (0x00FF0000 & ((*(nCurrIndexOffset+2)) << 16)) | + (0x0000FF00 & ((*(nCurrIndexOffset+1)) << 8)) | (0x000000FF & ((*nCurrIndexOffset))); + nContent = pdf->contentBase; + nContent += nIndexValue; + *numComponents = (picoos_int16) *nContent++; + if (*numComponents>PICODSP_PHASEORDER) { + PICODBG_DEBUG(("WARNING : Frame %d -- Phase vector[%d] Components = %d --> too big\n", nFrame, phsIndex, *numComponents)); + *numComponents = PICODSP_PHASEORDER; + } + for (nI=0; nI<*numComponents; nI++) { + phsVect[nI] = (picoos_int32) *nContent++; + } + for (nI=*numComponents; nIsubObj; + + numinb = numinb; /* avoid warning "var not used in this function"*/ + + /*defaults to 0 for output bytes*/ + *numoutb = 0; + + /*Input buffer contains an item FRAME_PAR*/ + switch (sig_subObj->innerProcState) { + + case 0: + /*--------------------------------------------- + Shifting old values + ---------------------------------------------*/ + for (n_count = 0; n_count < CEPST_BUFF_SIZE-1; n_count++) { + sig_subObj->sig_inner.F0Buff[n_count]=sig_subObj->sig_inner.F0Buff[n_count+1]; + sig_subObj->sig_inner.PhIdBuff[n_count]=sig_subObj->sig_inner.PhIdBuff[n_count+1]; + sig_subObj->sig_inner.VoicingBuff[n_count]=sig_subObj->sig_inner.VoicingBuff[n_count+1]; + sig_subObj->sig_inner.FuVBuff[n_count]=sig_subObj->sig_inner.FuVBuff[n_count+1]; + } + for (n_count = 0; n_count < PHASE_BUFF_SIZE-1; n_count++) { + sig_subObj->sig_inner.VoxBndBuff[n_count]=sig_subObj->sig_inner.VoxBndBuff[n_count+1]; + } + + tmp1 = sig_subObj->sig_inner.CepBuff[0]; + for (n_count = 0; n_count < CEPST_BUFF_SIZE-1; n_count++) { + sig_subObj->sig_inner.CepBuff[n_count]=sig_subObj->sig_inner.CepBuff[n_count+1]; + } + sig_subObj->sig_inner.CepBuff[CEPST_BUFF_SIZE-1]=tmp1; + + tmp1 = sig_subObj->sig_inner.PhsBuff[0]; + for (n_count = 0; n_count < PHASE_BUFF_SIZE-1; n_count++) { + sig_subObj->sig_inner.PhsBuff[n_count]=sig_subObj->sig_inner.PhsBuff[n_count+1]; + } + sig_subObj->sig_inner.PhsBuff[PHASE_BUFF_SIZE-1]=tmp1; + + /*--------------------------------------------- + Frame related initializations + ---------------------------------------------*/ + sig_subObj->sig_inner.prevVoiced_p = sig_subObj->sig_inner.voiced_p; + /*--------------------------------------------- + Get input data from PU buffer in internal buffers + -------------------------------------------------*/ + /*load the phonetic id code*/ + picoos_mem_copy((void *) &sig_subObj->inBuf[inReadPos + + sizeof(picodata_itemhead_t)], /*src*/ + (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ + sig_subObj->sig_inner.PhIdBuff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16; /*store into newest*/ + tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.PhIdBuff[0]; /*assign oldest*/ + sig_subObj->sig_inner.phId_p = (picoos_int16) tmp_uint16; /*assign oldest*/ + + /*load pitch values*/ + for (i = 0; i < sig_subObj->pdflfz->ceporder; i++) { + picoos_mem_copy((void *) &(sig_subObj->inBuf[inReadPos + + sizeof(picodata_itemhead_t) + sizeof(tmp_uint16) + 3 + * i * sizeof(tmp_uint16)]), /*src*/ + (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ + + sig_subObj->sig_inner.F0Buff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16;/*store into newest*/ + tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.F0Buff[0]; /*assign oldest*/ + + /*convert in float*/ + sig_subObj->sig_inner.F0_p + = (tmp_uint16 ? ((picoos_single) tmp_uint16 + / sig_subObj->scmeanLFZ) : (picoos_single) 0.0); + + if (sig_subObj->sig_inner.F0_p != (picoos_single) 0.0f) { + sig_subObj->sig_inner.F0_p = (picoos_single) exp( + (picoos_single) sig_subObj->sig_inner.F0_p); + + } + /* voicing */ + picoos_mem_copy((void *) &(sig_subObj->inBuf[inReadPos + + sizeof(picodata_itemhead_t) + sizeof(tmp_uint16) + 3 + * i * sizeof(tmp_uint16) + sizeof(tmp_uint16)]),/*src*/ + (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ + + sig_subObj->sig_inner.VoicingBuff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16;/*store into newest*/ + tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.VoicingBuff[0]; /*assign oldest*/ + + sig_subObj->sig_inner.voicing = (picoos_single) ((tmp_uint16 + & 0x01) * 8 + (tmp_uint16 & 0x0e) / 2) + / (picoos_single) 15.0f; + + /* unrectified f0 */ + picoos_mem_copy((void *) &(sig_subObj->inBuf[inReadPos + + sizeof(picodata_itemhead_t) + sizeof(tmp_uint16) + 3 + * i * sizeof(tmp_uint16) + 2 * sizeof(tmp_uint16)]),/*src*/ + (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ + + sig_subObj->sig_inner.FuVBuff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16;/*store into newest*/ + tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.FuVBuff[0]; /*assign oldest*/ + + sig_subObj->sig_inner.Fuv_p = (picoos_single) tmp_uint16 + / sig_subObj->scmeanLFZ; + sig_subObj->sig_inner.Fuv_p = (picoos_single) EXP((double)sig_subObj->sig_inner.Fuv_p); + } + /*load cep values*/ + offset = inReadPos + sizeof(picodata_itemhead_t) + + sizeof(tmp_uint16) + + 3 * sig_subObj->pdflfz->ceporder * sizeof(tmp_int16); + + tmp1 = sig_subObj->sig_inner.CepBuff[CEPST_BUFF_SIZE-1]; /*store into CURR */ + tmp2 = sig_subObj->sig_inner.CepBuff[0]; /*assign oldest*/ + + for (i = 0; i < sig_subObj->pdfmgc->ceporder; i++) { + picoos_mem_copy((void *) &(sig_subObj->inBuf[offset + i + * sizeof(tmp_int16)]), /*src*/ + (void *) &tmp_int16, sizeof(tmp_int16)); /*dest+size*/ + + tmp1 [i] = (picoos_int32) tmp_int16; + sig_subObj->sig_inner.wcep_pI[i] = (picoos_int32) tmp2[i]; + } + + if (sig_subObj->inBuf[inReadPos+ 3] > sig_subObj->inBuf[inReadPos+ 2]*2 + 8) { + /*load phase values*/ + /*get the index*/ + picoos_mem_copy((void *) &(sig_subObj->inBuf[offset + sig_subObj->pdfmgc->ceporder + * sizeof(tmp_int16)]), /*src*/ + (void *) &tmp_int16, sizeof(tmp_int16)); /*dest+size*/ + + /*store into buffers*/ + tmp1 = sig_subObj->sig_inner.PhsBuff[PHASE_BUFF_SIZE-1]; + /*retrieve values from pdf*/ + getPhsFromPdf(this, tmp_int16, tmp1, &(sig_subObj->sig_inner.VoxBndBuff[PHASE_BUFF_SIZE-1])); + } else { + /* no support for phase found */ + sig_subObj->sig_inner.VoxBndBuff[PHASE_BUFF_SIZE-1] = 0; + } + + /*pitch modifier*/ + sig_subObj->sig_inner.F0_p *= sig_subObj->pMod; + sig_subObj->sig_inner.Fuv_p *= sig_subObj->pMod; + if (sig_subObj->sig_inner.F0_p > 0.0f) { + sig_subObj->sig_inner.voiced_p = 1; + } else { + sig_subObj->sig_inner.voiced_p = 0; + } + sig_subObj->sig_inner.n_available++; + if (sig_subObj->sig_inner.n_available>3) sig_subObj->sig_inner.n_available = 3; + + if (sig_subObj->sig_inner.n_available < 3) { + return PICO_STEP_BUSY; + } + + sig_subObj->innerProcState = 3; + return PICO_STEP_BUSY; + + case 3: + /*Convert from mfcc to power spectrum*/ + save_transition_frame(&(sig_subObj->sig_inner)); + mel_2_lin_lookup(&(sig_subObj->sig_inner), sig_subObj->scmeanpowMGC); + sig_subObj->innerProcState += 1; + return PICO_STEP_BUSY; + + case 4: + /*Reconstruct PHASE SPECTRUM */ + phase_spec2(&(sig_subObj->sig_inner)); + sig_subObj->innerProcState += 1; + return PICO_STEP_BUSY; + + case 5: + /*Prepare Envelope spectrum for inverse FFT*/ + env_spec(&(sig_subObj->sig_inner)); + sig_subObj->innerProcState += 1; + return PICO_STEP_BUSY; + + case 6: + /*Generate the impulse response of the vocal tract */ + impulse_response(&(sig_subObj->sig_inner)); + sig_subObj->innerProcState += 1; + return PICO_STEP_BUSY; + + case 7: + /*Sum up N impulse responses according to excitation */ + td_psola2(&(sig_subObj->sig_inner)); + sig_subObj->innerProcState += 1; + return PICO_STEP_BUSY; + + case 8: + /*Ovladd */ + overlap_add(&(sig_subObj->sig_inner)); + sig_subObj->innerProcState += 1; + return PICO_STEP_BUSY; + + case 9: + /*----------------------------------------- + Save the output FRAME item (0:hop-1) + swap remaining buffer + ---------------------------------------------*/ + n_frames = 2; + *numoutb = 0; + hop_p_half = (sig_subObj->sig_inner.hop_p) / 2; + for (n_count = 0; n_count < n_frames; n_count++) { + sig_subObj->outBuf[outWritePos] + = (picoos_uint8) PICODATA_ITEM_FRAME; + sig_subObj->outBuf[outWritePos + 1] + = (picoos_uint8) (hop_p_half); + sig_subObj->outBuf[outWritePos + 2] + = (picoos_uint8) (sig_subObj->nNumFrame % ((hop_p_half))); + sig_subObj->outBuf[outWritePos + 3] + = (picoos_uint8) sig_subObj->sig_inner.hop_p; + s_data = (picoos_int16 *) &(sig_subObj->outBuf[outWritePos + 4]); + + /*range control and clipping*/ + mlt = (picoos_int32) ((sig_subObj->fSampNorm * sig_subObj->vMod) + * PICODSP_END_FLOAT_NORM); + t1 = &(sig_subObj->sig_inner.WavBuff_p[n_count * (hop_p_half)]); + for (n_i = 0; n_i < hop_p_half; n_i++) { /*Normalization*/ + f_data = *t1++ * mlt; + if (f_data >= 0) + f_data >>= 14; + else + f_data = -(-f_data >> 14); + if (f_data > PICOSIG_MAXAMP) + f_data = PICOSIG_MAXAMP; + if (f_data < PICOSIG_MINAMP) + f_data = PICOSIG_MINAMP; + *s_data = (picoos_int16) (f_data); + s_data++; + } + sig_subObj->nNumFrame = sig_subObj->nNumFrame + 1; + *numoutb += ((picoos_int16) n_i * sizeof(picoos_int16)) + 4; + outWritePos += *numoutb; + }/*end for n_count*/ + /*Swap remaining buffer*/ + cnt = sig_subObj->sig_inner.m2_p - sig_subObj->sig_inner.hop_p; + tmp1 = sig_subObj->sig_inner.WavBuff_p; + tmp2 + = &(sig_subObj->sig_inner.WavBuff_p[sig_subObj->sig_inner.hop_p]); + FAST_DEVICE(cnt,*(tmp1++)=*(tmp2++);) + ; + cnt = sig_subObj->sig_inner.m2_p - (sig_subObj->sig_inner.m2_p + - sig_subObj->sig_inner.hop_p); + FAST_DEVICE(cnt,*(tmp1++)=0;) + ; + sig_subObj->innerProcState = 0; /*reset to step 0*/ + sig_subObj->nNumFrame += 2; + return PICO_OK; + default: + return PICO_ERR_OTHER; + } + return PICO_ERR_OTHER; +}/*sigProcess*/ + +/** + * selects items to be dealth with by this PU + * @param item : pointer to current item head + * @return TRUE : item should be managed + * @return FALSE : item should be passed on next PU + * @remarks item pointed to by *item should be already valid + * @callgraph + * @callergraph + */ +static pico_status_t sig_deal_with(const picoos_uint8 *item) +{ + picodata_itemhead_t head; + pico_status_t s_result; + s_result = FALSE; + head.type = item[0]; + head.info1 = item[1]; + head.info2 = item[2]; + head.len = item[3]; + switch (head.type) { + case PICODATA_ITEM_FRAME_PAR: + /*the only item that is managed by sig, so far, is "FRAME_PAR"*/ + s_result = TRUE; + break; + case PICODATA_ITEM_CMD: + if ((head.info1 == PICODATA_ITEMINFO1_CMD_PLAY) || (head.info1 + == PICODATA_ITEMINFO1_CMD_SAVE) || (head.info1 + == PICODATA_ITEMINFO1_CMD_UNSAVE)) { + if (head.info2 == PICODATA_ITEMINFO2_CMD_TO_SIG) { + return TRUE; + } + } + if ((head.info1 == PICODATA_ITEMINFO1_CMD_PITCH) || (head.info1 + == PICODATA_ITEMINFO1_CMD_VOLUME) || (head.info1 + == PICODATA_ITEMINFO1_CMD_SPEAKER)) { + return TRUE; + } + break; + default: + break; + } + return s_result; +} /*sig_deal_with*/ + +/** + * selects items to be managed as commands by this PU + * @param item : pointer to current item head + * @return TRUE : item should be managed as a command + * @return FALSE : item is not a PU command + * @remarks item pointed to by *item should be already valid + * @callgraph + * @callergraph + */ +static pico_status_t sig_is_command(const picoos_uint8 *item) +{ + picodata_itemhead_t head; + head.type = item[0]; + head.info1 = item[1]; + head.info2 = item[2]; + head.len = item[3]; + switch (head.type) { + case PICODATA_ITEM_CMD: + if ((head.info1 == PICODATA_ITEMINFO1_CMD_PLAY) || (head.info1 + == PICODATA_ITEMINFO1_CMD_SAVE) || (head.info1 + == PICODATA_ITEMINFO1_CMD_UNSAVE)) { + if (head.info2 == PICODATA_ITEMINFO2_CMD_TO_SIG) { + return TRUE; + } + } + if ((head.info1 == PICODATA_ITEMINFO1_CMD_PITCH) || (head.info1 + == PICODATA_ITEMINFO1_CMD_VOLUME) || (head.info1 + == PICODATA_ITEMINFO1_CMD_SPEAKER)) { + return TRUE; + } + break; + default: + break; + } + return FALSE; +} /*sig_is_command*/ + +/** + * performs a step of the sig processing + * @param this : pointer to current PU (Control Unit) + * @param mode : mode for the PU + * @param numBytesOutput : pointer to number of bytes produced (output) + * @param this : pointer to current PU (Control Unit) + * @return one of the "picodata_step_result_t" values + * @callgraph + * @callergraph + */ +static picodata_step_result_t sigStep(register picodata_ProcessingUnit this, + picoos_int16 mode, picoos_uint16 * numBytesOutput) +{ + register sig_subobj_t * sig_subObj; + pico_status_t s_result; + picoos_bool b_res; + pico_status_t s_deal_with; + picoos_uint16 blen; + picoos_uint16 numinb, numoutb; + pico_status_t rv; + picoos_int16 *s_data; + picoos_int16 hop_p_half; + picoos_uint32 n_samp, n_i; + picoos_char s_temp_file_name[255]; + picoos_uint32 n_start, n_fram, n_bytes; + picoos_single f_value; + picoos_uint16 n_value; + picoos_uint32 n_pos; + /*wav file play volume control*/ + picoos_int16 *s_t1; + picoos_int32 sf_data, sf_mlt; + picoos_uint32 sf; + picoos_encoding_t enc; + picoos_uint32 numSamples; + + numinb = 0; + numoutb = 0; + rv = PICO_OK; + s_result = PICO_OK; + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + sig_subObj = (sig_subobj_t *) this->subObj; + + /*Init number of output bytes*/ + *numBytesOutput = 0; + + mode = mode; /* avoid warning "var not used in this function" */ + + while (1) { /* exit via return */ + + PICODBG_DEBUG(("picosig.sigStep -- doing state %i",sig_subObj->procState)); + + switch (sig_subObj->procState) { + + case PICOSIG_COLLECT: + /* ************** item collector ***********************************/ + /*collecting items from the PU input buffer*/ + s_result = picodata_cbGetItem(this->cbIn, + &(sig_subObj->inBuf[sig_subObj->inWritePos]), + sig_subObj->inBufSize - sig_subObj->inWritePos, &blen); + + PICODBG_DEBUG(("picosig.sigStep -- got item, status: %d",rv)); + + if (s_result == PICO_EOF) { + /*no items available : remain in state 0 and return idle*/ + return PICODATA_PU_IDLE; + } + if ((PICO_OK == s_result) && (blen > 0)) { + /* we now have one item : CHECK IT */ + s_result = picodata_is_valid_item( + &(sig_subObj->inBuf[sig_subObj->inWritePos]), blen); + if (s_result != TRUE) { + PICODBG_DEBUG(("picosig.sigStep -- item is not valid: discard")); + /*Item not valid : remain in state PICOSIG_COLLECT*/ + return PICODATA_PU_BUSY; + } + /*item ok: it could be sent to schedule state*/ + sig_subObj->inWritePos += blen; + sig_subObj->needMoreInput = FALSE; + sig_subObj->procState = PICOSIG_SCHEDULE; + /* uncomment next to split into two steps */ + return PICODATA_PU_ATOMIC; + } + /*no EOF, no OK --> errors : remain in state PICOSIG_COLLECT and return error*/ + return PICODATA_PU_ERROR; + break; + + case PICOSIG_SCHEDULE: + /* *************** item processing ***********************************/ + numinb = PICODATA_ITEM_HEADSIZE + + sig_subObj->inBuf[sig_subObj->inReadPos + 3]; + + /*verify that current item has to be dealth with by this PU*/ + s_deal_with = sig_deal_with( + &(sig_subObj->inBuf[sig_subObj->inReadPos])); + + switch (s_deal_with) { + + case TRUE: + /* we have to manage this item */ + if (FALSE == sig_is_command( + &(sig_subObj->inBuf[sig_subObj->inReadPos]))) + { + /*no commands, item to deal with : switch to process state*/ + sig_subObj->procState = PICOSIG_PROCESS; + sig_subObj->retState = PICOSIG_COLLECT; + return PICODATA_PU_BUSY; /*data still to process or to feed*/ + + } else { + + /*we need to manage this item as a SIG command-item*/ + + switch (sig_subObj->inBuf[sig_subObj->inReadPos + 1]) { + + case PICODATA_ITEMINFO1_CMD_PLAY: + /*CMD recognized : consume the command */ + sig_subObj->inReadPos += numinb; + if (sig_subObj->inReadPos + >= sig_subObj->inWritePos) { + sig_subObj->inReadPos = 0; + sig_subObj->inWritePos = 0; + } + /*default next state setting*/ + sig_subObj->procState = + sig_subObj->retState = PICOSIG_COLLECT; + + /*--------- wav file play management --------------*/ + if (sig_subObj->sInSDFile != NULL) { + /*input wav file is already open : return*/ + return PICODATA_PU_BUSY; + } + /*get temp file name*/ + picoos_strlcpy( + (picoos_char*) s_temp_file_name, + (picoos_char*) &(sig_subObj->inBuf[sig_subObj->inReadPos + + 4]), + sig_subObj->inBuf[sig_subObj->inReadPos + + 3] + 1); + /*avoid input/output file name clashes*/ + if (sig_subObj->sOutSDFile != NULL) { + if (picoos_strncmp( + (picoos_char*) s_temp_file_name, + (picoos_char*) sig_subObj->sOutSDFileName, + picoos_strlen( + (picoos_char*) s_temp_file_name)) + == 0) { + PICODBG_WARN(("input and output files has the same name!\n")); + return PICODATA_PU_BUSY; + } + } + /*actual sampled data file open*/ + b_res = picoos_sdfOpenIn(this->common, + &(sig_subObj->sInSDFile), + s_temp_file_name, &sf, + &enc, &numSamples); + if (b_res != TRUE) { + PICODBG_DEBUG(("Error on opening file %s\n", s_temp_file_name)); + sig_subObj->sInSDFile = NULL; + sig_subObj->sInSDFileName[0] = '\0'; + return PICODATA_PU_BUSY; + } + /*input file handle is now valid : store filename*/ + picoos_strlcpy( + (picoos_char*) sig_subObj->sInSDFileName, + (picoos_char*) s_temp_file_name, + sig_subObj->inBuf[sig_subObj->inReadPos + + 3] + 1); + sig_subObj->sInSDFilePos = 0; + /*switch to state PLAY and return*/ + sig_subObj->procState = + sig_subObj->retState = PICOSIG_PLAY; + return PICODATA_PU_BUSY; + break; + + case PICODATA_ITEMINFO1_CMD_SAVE: + /*CMD recognized : consume the command */ + sig_subObj->inReadPos += numinb; + if (sig_subObj->inReadPos + >= sig_subObj->inWritePos) { + sig_subObj->inReadPos = 0; + sig_subObj->inWritePos = 0; + } + /*prepare return state*/ + sig_subObj->procState = PICOSIG_COLLECT; + sig_subObj->retState = PICOSIG_COLLECT; + /*check about output file*/ + if ((sig_subObj->sOutSDFile != NULL) + || (sig_subObj->outSwitch == 1)) { + /*output sig file is already active : return*/ + return PICODATA_PU_BUSY; + } + /*get temp file name*/ + picoos_strlcpy( + (picoos_char*) s_temp_file_name, + (picoos_char*) &(sig_subObj->inBuf[sig_subObj->inReadPos + + 4]), + sig_subObj->inBuf[sig_subObj->inReadPos + + 3] + 1); + /*check extension*/ + if (picoos_has_extension(s_temp_file_name, + PICODATA_PUTYPE_WAV_OUTPUT_EXTENSION) + == FALSE){ + /*extension unsupported : return*/ + return PICODATA_PU_BUSY; + } + /*avoid input/output file name clashes*/ + if (sig_subObj->sInSDFile != NULL) { + if (picoos_strncmp( + (picoos_char*) sig_subObj->sInSDFileName, + (picoos_char*) s_temp_file_name, + picoos_strlen( + (picoos_char*) sig_subObj->sInSDFileName)) + == 0) { + /*input and output files has the same name : do not allow opening for writing*/ + PICODBG_WARN(("input and output files has the same name!\n")); + return PICODATA_PU_BUSY; + } + } + /*try to open*/ + picoos_sdfOpenOut(this->common, + &(sig_subObj->sOutSDFile), + s_temp_file_name, + SAMPLE_FREQ_16KHZ, PICOOS_ENC_LIN); + if (sig_subObj->sOutSDFile == NULL) { + PICODBG_DEBUG(("Error on opening file %s\n", sig_subObj->sOutSDFileName)); + sig_subObj->outSwitch = 0; + sig_subObj->sOutSDFileName[0] = '\0'; + } else { + /*open OK*/ + sig_subObj->outSwitch = 1; + /*store output filename*/ + picoos_strlcpy( + (picoos_char*) sig_subObj->sOutSDFileName, + (picoos_char*) s_temp_file_name, + sig_subObj->inBuf[sig_subObj->inReadPos + 3] + 1); + } + return PICODATA_PU_BUSY; + break; + + case PICODATA_ITEMINFO1_CMD_UNSAVE: + /*CMD recognized : consume the command */ + sig_subObj->inReadPos += numinb; + if (sig_subObj->inReadPos + >= sig_subObj->inWritePos) { + sig_subObj->inReadPos = 0; + sig_subObj->inWritePos = 0; + } + /*prepare return state*/ + sig_subObj->procState = PICOSIG_COLLECT; + sig_subObj->retState = PICOSIG_COLLECT; + /*close the output file if any*/ + if ((sig_subObj->sOutSDFile == NULL) + || (sig_subObj->outSwitch == 0)) { + /*output sig file is not active : return*/ + PICODBG_DEBUG(("Error on requesting a binary samples file output closing : no file output handle exist\n")); + return PICODATA_PU_BUSY; + } + picoos_sdfCloseOut(this->common, + &(sig_subObj->sOutSDFile)); + sig_subObj->outSwitch = 0; + sig_subObj->sOutSDFile = NULL; + sig_subObj->sOutSDFileName[0] = '\0'; + return PICODATA_PU_BUSY; + break; + + case PICODATA_ITEMINFO1_CMD_PITCH: + case PICODATA_ITEMINFO1_CMD_VOLUME: + case PICODATA_ITEMINFO1_CMD_SPEAKER: + n_pos = 4; + picoos_read_mem_pi_uint16( + &(sig_subObj->inBuf[sig_subObj->inReadPos]), + &n_pos, &n_value); + b_res = FALSE; + switch (sig_subObj->inBuf[sig_subObj->inReadPos + 2]) { + case 'a' : + /*absloute modifier*/ + f_value = (picoos_single) n_value + / (picoos_single) 100.0f; + b_res = TRUE; + break; + case 'r' : + /*relative modifier*/ + f_value = (picoos_single) n_value + / (picoos_single) 1000.0f; + b_res = TRUE; + break; + default : + f_value = (picoos_single)0; /*avoid warnings*/ + break; + } + if (b_res) { + switch (sig_subObj->inBuf[sig_subObj->inReadPos + 1]) { + case PICODATA_ITEMINFO1_CMD_PITCH : + sig_subObj->pMod = f_value; + break; + case PICODATA_ITEMINFO1_CMD_VOLUME : + sig_subObj->vMod = f_value; + break; + case PICODATA_ITEMINFO1_CMD_SPEAKER : + sig_subObj->sMod = f_value; + sig_subObj->sig_inner.sMod_p + = sig_subObj->sMod; + /*call the function needed to initialize the speaker factor*/ + mel_2_lin_init( + &(sig_subObj->sig_inner)); + break; + default : + break; + } + } + + /*CMD recognized : consume the command */ + sig_subObj->inReadPos += numinb; + if (sig_subObj->inReadPos + >= sig_subObj->inWritePos) { + sig_subObj->inReadPos = 0; + sig_subObj->inWritePos = 0; + } + /*prepare proc state*/ + sig_subObj->procState = PICOSIG_COLLECT; + sig_subObj->retState = PICOSIG_COLLECT; + return PICODATA_PU_BUSY; + break; + default: + break; + }/*switch command type*/ + } /*end if is command*/ + break; + + case FALSE: + + /*we DO NOT have to deal with this item on this PU. + * Normally these are still alive boundary or flush items*/ + /*copy item from PU input to PU output buffer, + * i.e. make it ready to FEED*/ + s_result = picodata_copy_item( + &(sig_subObj->inBuf[sig_subObj->inReadPos]), + numinb, + &(sig_subObj->outBuf[sig_subObj->outWritePos]), + sig_subObj->outBufSize - sig_subObj->outWritePos, + &numoutb); + if (s_result != PICO_OK) { + /*item not prepared properly to be sent to next PU : + * do not change state and retry next time*/ + sig_subObj->procState = PICOSIG_SCHEDULE; + sig_subObj->retState = PICOSIG_COLLECT; + return PICODATA_PU_BUSY; /*data still to process or to feed*/ + } + + /*if end of sentence reset number of frames(only needed for debugging purposes)*/ + if ((sig_subObj->inBuf[sig_subObj->inReadPos] + == PICODATA_ITEM_BOUND) + && ((sig_subObj->inBuf[sig_subObj->inReadPos + 1] + == PICODATA_ITEMINFO1_BOUND_SEND) + || (sig_subObj->inBuf[sig_subObj->inReadPos + + 1] + == PICODATA_ITEMINFO1_BOUND_TERM))) { + PICODBG_INFO(("End of sentence - Processed frames : %d", + sig_subObj->nNumFrame)); + sig_subObj->nNumFrame = 0; + } + + /*item processed and put in oputput buffer : consume the item*/ + sig_subObj->inReadPos += numinb; + sig_subObj->outWritePos += numoutb; + if (sig_subObj->inReadPos >= sig_subObj->inWritePos) { + /* inBuf exhausted */ + sig_subObj->inReadPos = 0; + sig_subObj->inWritePos = 0; + sig_subObj->needMoreInput = FALSE; + } + sig_subObj->procState = PICOSIG_FEED; + sig_subObj->retState = PICOSIG_COLLECT; + return PICODATA_PU_BUSY; /*data still to process or to feed*/ + break; + + default: + break; + }/*end switch s_deal_with*/ + + break; /*end case sig_schedule*/ + + case PICOSIG_PROCESS: + /* *************** item processing ***********************************/ + numinb = PICODATA_ITEM_HEADSIZE + + sig_subObj->inBuf[sig_subObj->inReadPos + 3]; + + /*Process a full item*/ + s_result = sigProcess(this, sig_subObj->inReadPos, numinb, + sig_subObj->outWritePos, &numoutb); + + if (s_result == PICO_OK) { + sig_subObj->inReadPos += numinb; + if (sig_subObj->inReadPos >= sig_subObj->inWritePos) { + sig_subObj->inReadPos = 0; + sig_subObj->inWritePos = 0; + sig_subObj->needMoreInput = FALSE; + } + sig_subObj->outWritePos += numoutb; + sig_subObj->procState = PICOSIG_FEED; + sig_subObj->retState = PICOSIG_COLLECT; + PICODBG_DEBUG(("picosig.sigStep -- leaving PICO_PROC, inReadPos = %i, outWritePos = %i",sig_subObj->inReadPos, sig_subObj->outWritePos)); + return PICODATA_PU_BUSY; /*data to feed*/ + } + return PICODATA_PU_BUSY; /*data still to process : remain in PROCESS STATE*/ + break; + + case PICOSIG_PLAY: + + /*management of wav file play*/ + s_data = (picoos_int16 *) &(sig_subObj->outBuf[sig_subObj->outWritePos + 4]); + hop_p_half = sig_subObj->sig_inner.hop_p / 2; + /*read directly into PU output buffer*/ + n_samp = hop_p_half; + b_res = picoos_sdfGetSamples(sig_subObj->sInSDFile, + sig_subObj->sInSDFilePos, &n_samp, s_data); + sig_subObj->sInSDFilePos += n_samp; + + if ((FALSE == b_res) || (0 == n_samp)) { + /*file play is complete or file read error*/ + picoos_sdfCloseIn(this->common, &(sig_subObj->sInSDFile)); + sig_subObj->sInSDFile = NULL; + sig_subObj->sInSDFileName[0] = '\0'; + sig_subObj->procState = PICOSIG_COLLECT; + sig_subObj->retState = PICOSIG_COLLECT; + return PICODATA_PU_BUSY; /*check if data in input buffer*/ + } + /*-----------------------------------*/ + /*Volume control of wav file playback*/ + /* (code borrowed from sigProcess)*/ + /*Volume mod and clipping control */ + /* directly into PU output buffer*/ + /*-----------------------------------*/ + sf_mlt = (picoos_int32) ((sig_subObj->vMod) * 16.0f); + s_t1 = &(s_data[0]); + + for (n_i = 0; n_i < n_samp; n_i++) { + if (*s_t1 != 0) { + sf_data = (picoos_int32) (*s_t1) * sf_mlt; + sf_data >>= 4; + if (sf_data > PICOSIG_MAXAMP) { + sf_data = PICOSIG_MAXAMP; + } else if (sf_data < PICOSIG_MINAMP) { + sf_data = PICOSIG_MINAMP; + } + *s_t1 = (picoos_int16) (sf_data); + } + s_t1++; + } + /*Add header info*/ + sig_subObj->outBuf[sig_subObj->outWritePos] + = (picoos_uint8) PICODATA_ITEM_FRAME; + sig_subObj->outBuf[sig_subObj->outWritePos + 1] + = (picoos_uint8) n_samp; + sig_subObj->outBuf[sig_subObj->outWritePos + 2] + = (picoos_uint8) (sig_subObj->nNumFrame % (hop_p_half)); /*number of frame % 64*/ + sig_subObj->outBuf[sig_subObj->outWritePos + 3] + = (picoos_uint8) n_samp * 2; + /*Item content*/ + sig_subObj->outWritePos += (n_samp * sizeof(picoos_int16)) + 4; /*including header*/ + sig_subObj->procState = PICOSIG_FEED; + sig_subObj->retState = PICOSIG_PLAY; + break; + + case PICOSIG_FEED: + /* ************** item output/feeding ***********************************/ + switch (sig_subObj->outSwitch) { + case 0: + /*feeding items to PU output buffer*/ + s_result = picodata_cbPutItem(this->cbOut, + &(sig_subObj->outBuf[sig_subObj->outReadPos]), + sig_subObj->outWritePos - sig_subObj->outReadPos, + &numoutb); + break; + case 1: + /*feeding items to file*/ + if (sig_subObj->outBuf[sig_subObj->outReadPos] + == PICODATA_ITEM_FRAME) { + if ((sig_subObj->sOutSDFile) != NULL) { + n_start = (picoos_uint32) (sig_subObj->outReadPos) + + PICODATA_ITEM_HEADSIZE; + n_bytes = (picoos_uint32) sig_subObj->outBuf[(sig_subObj->outReadPos) + + PICODATA_ITEMIND_LEN]; + n_fram = (picoos_uint32) sig_subObj->outBuf[(sig_subObj->outReadPos) + + PICODATA_ITEMIND_INFO2]; + if (picoos_sdfPutSamples( + sig_subObj->sOutSDFile, + n_bytes / 2, + (picoos_int16*) &(sig_subObj->outBuf[n_start]))) { + PICODBG_DEBUG(("Nframe:%d - Nbytes %d\n", n_fram, n_bytes)); + numoutb = n_bytes + 4; + s_result = PICO_OK; + /* also feed item to next PU */ + s_result = picodata_cbPutItem( + this->cbOut, + &(sig_subObj->outBuf[sig_subObj->outReadPos]), + sig_subObj->outWritePos + - sig_subObj->outReadPos, + &numoutb); + } else { + /*write error : close file + cleanup handles*/ + if (sig_subObj->sOutSDFile != NULL) { + picoos_sdfCloseOut(this->common, &(sig_subObj->sOutSDFile)); + sig_subObj->sOutSDFile = NULL; + } + sig_subObj->sOutSDFileName[0] = '\0'; + sig_subObj->outSwitch = 0; + PICODBG_DEBUG(("Error in writing :%d bytes to output file %s\n", numoutb, &(sig_subObj->sOutSDFileName[0]))); + s_result = PICO_ERR_OTHER; + } + } + } else { + /*continue to feed following PU with items != FRAME */ + s_result = picodata_cbPutItem( + this->cbOut, + &(sig_subObj->outBuf[sig_subObj->outReadPos]), + sig_subObj->outWritePos - sig_subObj->outReadPos, + &numoutb); + } + break; + default: + s_result = PICO_ERR_OTHER; + break; + } + PICODBG_DEBUG(("picosig.sigStep -- put item, status: %d",s_result)); + + if (PICO_OK == s_result) { + + sig_subObj->outReadPos += numoutb; + *numBytesOutput = numoutb; + /*-------------------------*/ + /*reset the output pointers*/ + /*-------------------------*/ + if (sig_subObj->outReadPos >= sig_subObj->outWritePos) { + sig_subObj->outReadPos = 0; + sig_subObj->outWritePos = 0; + sig_subObj->procState = sig_subObj->retState; + } + return PICODATA_PU_BUSY; + + } else if (PICO_EXC_BUF_OVERFLOW == s_result) { + + PICODBG_DEBUG(("picosig.sigStep ** feeding, overflow, PICODATA_PU_OUT_FULL")); + return PICODATA_PU_OUT_FULL; + + } else if ((PICO_EXC_BUF_UNDERFLOW == s_result) + || (PICO_ERR_OTHER == s_result)) { + + PICODBG_DEBUG(("picosig.sigStep ** feeding problem, discarding item")); + sig_subObj->outReadPos = 0; + sig_subObj->outWritePos = 0; + sig_subObj->procState = sig_subObj->retState; + return PICODATA_PU_ERROR; + + } + break; + default: + /*NOT feeding items*/ + s_result = PICO_EXC_BUF_IGNORE; + break; + }/*end switch*/ + return PICODATA_PU_BUSY; /*check if there is more data to process after feeding*/ + + }/*end while*/ + return PICODATA_PU_IDLE; +}/*sigStep*/ + +#ifdef __cplusplus +} +#endif + +/* Picosig.c end */ diff --git a/pico/lib/picosig.h b/pico/lib/picosig.h new file mode 100644 index 0000000..3e29e8f --- /dev/null +++ b/pico/lib/picosig.h @@ -0,0 +1,64 @@ +/* + * 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 picosig.h + * + * Signal Generation PU - Header file + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +/** + * @addtogroup picosig + * + * Pico Signal Generation module \n + * + * Pico Sig is the PU that makes the parametric representation produce a speech signal. + * The PU receives parametric vectors and translates them into signal vectors. + * Most of the processing is based on this 1 to 1 relationship between input and output vectors. + * + * NOTE : "picosig" includes logically "picosig2" module, that is the DSP implementation of the signal generation. +*/ + +#ifndef PICOSIG_H_ +#define PICOSIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/* ******************************************************************************* + * items related to the generic interface + ********************************************************************************/ +picodata_ProcessingUnit picosig_newSigUnit( + picoos_MemoryManager mm, + picoos_Common common, + picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, + picorsrc_Voice voice); + +#ifdef __cplusplus +} +#endif + +#endif /*PICOSIG_H_*/ diff --git a/pico/lib/picosig2.c b/pico/lib/picosig2.c new file mode 100644 index 0000000..e431c90 --- /dev/null +++ b/pico/lib/picosig2.c @@ -0,0 +1,4090 @@ +/* + * 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 picosig2.c + * + * Signal Generation PU - Internal functions - Implementation + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ +#include "picoos.h" +#include "picodsp.h" +#include "picosig2.h" +#include "picofftsg.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif +/*--------------------------------------------------------------------------- + * INTERNAL FUNCTIONS DECLARATION + *---------------------------------------------------------------------------*/ +static void gen_hann2(sig_innerobj_t *sig_inObj); +static void get_simple_excitation(sig_innerobj_t *sig_inObj, + picoos_int16 *nextPeak); +static void enh_wind_init(sig_innerobj_t *sig_inObj); +static void init_rand(sig_innerobj_t *sig_inObj); +static void get_trig(picoos_int32 ang, picoos_int32 *table, picoos_int32 *cs, + picoos_int32 *sn); + +/*--------------------------------------------------------------------------- + * PICO SYSTEM FUNCTIONS + *---------------------------------------------------------------------------*/ +/** + * allocation of DSP memory for SIG PU + * @param mm : memory manager + * @param sig_inObj : sig PU internal object of the sub-object + * @return PICO_OK : allocation successful + * @return PICO_ERR_OTHER : allocation NOT successful + * @callgraph + * @callergraph + */ +pico_status_t sigAllocate(picoos_MemoryManager mm, sig_innerobj_t *sig_inObj) +{ + picoos_int16 *data_i; + picoos_int32 *d32; + picoos_int32 nCount; + + sig_inObj->int_vec22 = + sig_inObj->int_vec23 = + sig_inObj->int_vec24 = + sig_inObj->int_vec25 = + sig_inObj->int_vec26 = + sig_inObj->int_vec28 = + sig_inObj->int_vec29 = + sig_inObj->int_vec38 = + sig_inObj->int_vec30 = + sig_inObj->int_vec31 = + sig_inObj->int_vec32 = + sig_inObj->int_vec33 = + sig_inObj->int_vec34 = + sig_inObj->int_vec35 = + sig_inObj->int_vec36 = + sig_inObj->int_vec37 = + sig_inObj->int_vec38 = + sig_inObj->int_vec39 = + sig_inObj->int_vec40 = NULL; + + sig_inObj->sig_vec1 = NULL; + + sig_inObj->idx_vect1 = sig_inObj->idx_vect2 = sig_inObj->idx_vect4 = NULL; + sig_inObj->idx_vect5 = sig_inObj->idx_vect6 = sig_inObj->idx_vect7 = + sig_inObj->idx_vect8 = sig_inObj->idx_vect9 = NULL; + sig_inObj->ivalue17 = sig_inObj->ivalue18 = 0; + + /*----------------------------------------------------------------- + * Memory allocations + * NOTE : it would be far better to do a single allocation + * and to do pointer initialization inside this routine + * ------------------------------------------------------------------*/ + data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) + * PICODSP_FFTSIZE); + if (NULL == data_i) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->idx_vect1 = data_i; + + data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) + * PICODSP_HFFTSIZE_P1); + if (NULL == data_i) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->idx_vect2 = data_i; + + data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) + * PICODSP_FFTSIZE); + if (NULL == data_i) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->idx_vect4 = data_i; + + data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) + * PICODSP_FFTSIZE); + if (NULL == data_i) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->idx_vect5 = data_i; + + data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) + * PICODSP_FFTSIZE); + if (NULL == data_i) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->idx_vect6 = data_i; + + data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) + * PICODSP_HFFTSIZE_P1); + if (NULL == data_i) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->idx_vect7 = data_i; + + data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) + * PICODSP_MAX_EX); + if (NULL == data_i) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->idx_vect8 = data_i; + + data_i = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) + * PICODSP_MAX_EX); + if (data_i == NULL) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->idx_vect9 = data_i; + + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_FFTSIZE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec22 = d32; + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_FFTSIZE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec23 = d32; + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_FFTSIZE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec24 = d32; + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_FFTSIZE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec25 = d32; + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_FFTSIZE * 2); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec26 = d32; + + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_FFTSIZE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec28 = d32; + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_FFTSIZE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec29 = d32; + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_FFTSIZE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec38 = d32; + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_FFTSIZE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec30 = d32; + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_FFTSIZE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec31 = d32; + + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_FFTSIZE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec32 = d32; + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_FFTSIZE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec33 = d32; + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_N_RAND_TABLE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec34 = d32; + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_N_RAND_TABLE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec35 = d32; + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_N_RAND_TABLE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec36 = d32; + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_N_RAND_TABLE); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec37 = d32; + + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_HFFTSIZE_P1); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec39 = d32; + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) * (1 + + PICODSP_COS_TABLE_LEN)); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec40 = d32; + + for (nCount = 0; nCount < CEPST_BUFF_SIZE; nCount++) { + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) * (PICODSP_CEPORDER)); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec41[nCount] = d32; + } + + for (nCount = 0; nCount < PHASE_BUFF_SIZE; nCount++) { + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) * (PICODSP_PHASEORDER)); + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->int_vec42[nCount] = d32; + } + + d32 = (picoos_int32 *) picoos_allocate(mm, sizeof(picoos_int32) + * PICODSP_FFTSIZE * 2); /* - fixed point */ + if (NULL == d32) { + sigDeallocate(mm, sig_inObj); + return PICO_ERR_OTHER; + } + sig_inObj->sig_vec1 = d32; + + return PICO_OK; +}/*sigAllocate*/ + +/** + * frees DSP memory for SIG PU + * @param mm : memory manager + * @param sig_inObj : sig PU internal object of the sub-object + * @return void + * @callgraph + * @callergraph + */ +void sigDeallocate(picoos_MemoryManager mm, sig_innerobj_t *sig_inObj) +{ + picoos_int32 nCount; + /*----------------------------------------------------------------- + * Memory de-allocations + * ------------------------------------------------------------------*/ + if (NULL != sig_inObj->idx_vect1) + picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect1)); + if (NULL != sig_inObj->idx_vect2) + picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect2)); + if (NULL != sig_inObj->idx_vect4) + picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect4)); + if (NULL != sig_inObj->idx_vect5) + picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect5)); + if (NULL != sig_inObj->idx_vect6) + picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect6)); + if (NULL != sig_inObj->idx_vect7) + picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect7)); + if (NULL != sig_inObj->idx_vect8) + picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect8)); + if (NULL != sig_inObj->idx_vect9) + picoos_deallocate(mm, (void *) &(sig_inObj->idx_vect9)); + + if (NULL != sig_inObj->int_vec22) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec22)); + if (NULL != sig_inObj->int_vec23) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec23)); + if (NULL != sig_inObj->int_vec24) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec24)); + if (NULL != sig_inObj->int_vec25) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec25)); + if (NULL != sig_inObj->int_vec26) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec26)); + if (NULL != sig_inObj->int_vec28) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec28)); + if (NULL != sig_inObj->int_vec29) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec29)); + if (NULL != sig_inObj->int_vec38) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec38)); + if (NULL != sig_inObj->int_vec30) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec30)); + if (NULL != sig_inObj->int_vec31) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec31)); + if (NULL != sig_inObj->int_vec32) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec32)); + if (NULL != sig_inObj->int_vec33) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec33)); + if (NULL != sig_inObj->int_vec34) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec34)); + if (NULL != sig_inObj->int_vec35) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec35)); + if (NULL != sig_inObj->int_vec36) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec36)); + if (NULL != sig_inObj->int_vec37) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec37)); + if (NULL != sig_inObj->int_vec39) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec39)); + if (NULL != sig_inObj->int_vec40) + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec40)); + + for (nCount = 0; nCount < CEPST_BUFF_SIZE; nCount++) { + if (NULL != sig_inObj->int_vec41[nCount]) { + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec41[nCount])); + } + } + + for (nCount = 0; nCount < PHASE_BUFF_SIZE; nCount++) { + if (NULL != sig_inObj->int_vec42[nCount]) { + picoos_deallocate(mm, (void *) &(sig_inObj->int_vec42[nCount])); + } + } + + if (NULL != sig_inObj->sig_vec1) { + picoos_deallocate(mm, (void *) &(sig_inObj->sig_vec1)); + } +}/*sigDeAllocate*/ + +/** + * initializes all memory neededed by DSP at instance creation time + * @param sig_inObj : sig PU internal object of the sub-object + * @return void + * @callgraph + * @callergraph + */ +void sigDspInitialize(sig_innerobj_t *sig_inObj) +{ + picoos_int32 i, j; + picoos_int32 *pnt; + + /*----------------------------------------------------------------- + * Initialization + * ------------------------------------------------------------------*/ + sig_inObj->warp_p = PICODSP_FREQ_WARP_FACT; + sig_inObj->VCutoff_p = PICODSP_V_CUTOFF_FREQ; /*voicing cut off frequency in Hz (will be modeled in the future)*/ + sig_inObj->UVCutoff_p = PICODSP_UV_CUTOFF_FREQ;/*unvoiced frames only (periodize lowest components to mask bad voicing transitions)*/ + sig_inObj->Fs_p = PICODSP_SAMP_FREQ; /*Sampling freq*/ + + sig_inObj->m1_p = PICODSP_CEPORDER; + sig_inObj->m2_p = PICODSP_FFTSIZE; /*also initializes windowLen*/ + sig_inObj->framesz_p = PICODSP_DISPLACE; /*1/4th of the frame size = displacement*/ + sig_inObj->hfftsize_p = PICODSP_H_FFTSIZE; /*half of the FFT size*/ + sig_inObj->voxbnd_p = (picoos_int32) ((picoos_single) sig_inObj->hfftsize_p + / ((picoos_single) sig_inObj->Fs_p / (picoos_single) 2) + * (picoos_single) sig_inObj->VCutoff_p); + sig_inObj->voxbnd2_p + = (picoos_int32) ((picoos_single) sig_inObj->hfftsize_p + / ((picoos_single) sig_inObj->Fs_p / (picoos_single) 2) + * (picoos_single) sig_inObj->UVCutoff_p); + sig_inObj->hop_p = sig_inObj->framesz_p; + sig_inObj->nextPeak_p = (((int) (PICODSP_FFTSIZE)) + / ((int) PICODSP_DISPLACE) - 1) * sig_inObj->hop_p; + sig_inObj->phId_p = 0; /*phonetic id*/ + sig_inObj->E_p = (picoos_single) 0.0f; + sig_inObj->F0_p = (picoos_single) 0.0f; + sig_inObj->voiced_p = 0; + sig_inObj->nV = sig_inObj->nU = 0; + sig_inObj->sMod_p = (picoos_single) 1.0f; + + /*cleanup vectors*/ + for (i = 0; i < 2 * PICODSP_FFTSIZE; i++) { + sig_inObj->sig_vec1[i] = 0; + sig_inObj->int_vec26[i] = 0; /*wav buff cleanup */ + } + + for (i = 0; i < PICODSP_FFTSIZE; i++) { + sig_inObj->idx_vect1[i] = sig_inObj->idx_vect4[i] + = sig_inObj->idx_vect5[i] = sig_inObj->idx_vect6[i] = 0; + sig_inObj->int_vec32[i] = sig_inObj->int_vec33[i] = 0; + } + + for (i = 0; i < PICODSP_HFFTSIZE_P1; i++) { + sig_inObj->idx_vect2[i] = (picoos_int16) 0; + } + + for (i = 0; i < CEPST_BUFF_SIZE; i++) { + sig_inObj->F0Buff[i]=0; + sig_inObj->PhIdBuff[i]=0; + sig_inObj->VoicingBuff[i]=0; + sig_inObj->FuVBuff[i]=0; + if (NULL != sig_inObj->CepBuff[i]) { + pnt = sig_inObj->CepBuff[i]; + for (j = 0; j < PICODSP_CEPORDER; j++) { + pnt[j] = 0; + } + } + } + + for (i = 0; i < PHASE_BUFF_SIZE; i++) { + if (NULL != sig_inObj->int_vec42[i]) { + pnt = sig_inObj->int_vec42[i]; + for (j = 0; j < PICODSP_PHASEORDER; j++) { + pnt[j] = 0; + } + } + } + sig_inObj->n_available=0; + /*--------------------------------------------- + Init formant enhancement window + hanning window, + Post Filter Hermite's interpolator Matrix + Mel-2-Lin lookup tables + ---------------------------------------------*/ + enh_wind_init(sig_inObj); /*creates the formant enhancement window*/ + init_rand(sig_inObj); + gen_hann2(sig_inObj); + mel_2_lin_init(sig_inObj); + +}/*sigDspInitialize*/ + +/*------------------------------------------------------------------------------- + PROCESSING FUNCTIONS : CALLED WITHIN sigStep (cfr. picosig.c) + --------------------------------------------------------------------------------*/ +/** + * convert from mel scale to linear scale + * @param sig_inObj : sig PU internal object of the sub-object + * @param scmeanMGC : mean value of the MGC + * @return void + * @callgraph + * @callergraph + * @remarks translated from matlab code to c-code + * Input + * - c1 : input mfcc vector (ceporder=m1, real) + * - m1 : input order + * - A,B,D : lookup tables + * - m2 : output order + * - Xr,Xi (m2=FFT size, real) temporary arrays for FFT + * - WNr,WNi (m2=FFT size, real) cos and sin precalculated tables + * Output + * - Xr (m2=FFT size, real) linear cepstral vector + */ +void mel_2_lin_lookup(sig_innerobj_t *sig_inObj, picoos_uint32 scmeanMGC) +{ + /*Local vars*/ + picoos_int16 nI, k; + picoos_int32 delta, term1, term2; + + /*Local vars to be linked with sig data object*/ + picoos_int32 *c1, *XXr; + picoos_single K1; + picoos_int32 *D, K2, shift; + picoos_int16 m1, *A, m2, m4, voiced, i; + + /*Link local variables with sig data object*/ + c1 = sig_inObj->wcep_pI; + m1 = sig_inObj->m1_p; + m2 = PICODSP_FFTSIZE; + m4 = m2 >> 1; + + A = sig_inObj->A_p; + D = sig_inObj->d_p; + + XXr = sig_inObj->wcep_pI; + voiced = sig_inObj->voiced_p; + + shift = 27 - scmeanMGC; + K2 = 1 << shift; + K1 = (picoos_single) PICODSP_START_FLOAT_NORM * K2; + XXr[0] = (picoos_int32) ((picoos_single) c1[0] * K1); + for (nI = 1; nI < m1; nI++) { + XXr[nI] = c1[nI] << shift; + } + i = sizeof(picoos_int32) * (PICODSP_FFTSIZE + 1 - m1); + picoos_mem_set(XXr + m1, 0, i); + dfct_nmf(m4, XXr); /* DFCT directly in fixed point */ + + /* ***************************************************************************************** + Linear frequency scale envelope through interpolation. + Two additions and one multiplication per entry. + + Optimization of linear interpolation algorithm + - Start from 1 and stop at PICODSP_H_FFTSIZE-1 because 0 and PICODSP_H_FFTSIZE are invariant points + - B[k]=A[k]+1 except for 0 and PICODSP_H_FFTSIZE + - get rid of extra -1 operation by adapting the table A[] + + *******************************************************************************************/ + for (nI = 1; nI < PICODSP_H_FFTSIZE; nI++) { + k = A[nI]; + term2 = XXr[k]; + term1 = XXr[k + 1]; + delta = term1 - term2; + XXr[nI] = term2 + ((D[nI] * delta) >> 5); /* ok because nI<=A[nI] <=B[nI] */ + } +}/*mel_2_lin_lookup*/ + +/** + * calculate phase + * @remarks voiced phase taken from phase codebook and smoothed, + * @remarks unvoiced phase - random + * @param sig_inObj : sig PU internal object of the sub-object + * @return void + * @callgraph + * @callergraph + */ +void phase_spec2(sig_innerobj_t *sig_inObj) +{ + picoos_int16 nI, iRand, firstUV; + picoos_int32 *tmp1, *tmp2; + picoos_int16 VOXBND_M1; + picoos_int32 *spect, *ang; + picoos_int16 voiced, m2; + picoos_int32 *co, *so, *c, *s, voxbnd, voxbnd2; + picoos_int16 i,j, k, n_comp; + picoos_int16 *Pvoxbnd; + picoos_int32 *phs_p2, *phs_p1, *phs_n1, *phs_n2; + picoos_int32 *phs; + + /*Link local variables to sig data object*/ + spect = sig_inObj->wcep_pI; /* spect_p;*/ + /* current spect scale : times PICODSP_FIX_SCALE1 */ + ang = sig_inObj->ang_p; + voxbnd = (picoos_int32) (sig_inObj->voxbnd_p * sig_inObj->voicing); + voxbnd2 = sig_inObj->voxbnd2_p; + voiced = sig_inObj->voiced_p; + m2 = sig_inObj->m2_p; + VOXBND_M1 = voxbnd - 1; + firstUV = 1; + + /*code starts here*/ + if (voiced == 1) { + firstUV = voxbnd; + Pvoxbnd = sig_inObj->VoxBndBuff; + n_comp = Pvoxbnd[2]; + phs_p2 = sig_inObj->PhsBuff[0]; + phs_p1 = sig_inObj->PhsBuff[1]; + phs = sig_inObj->PhsBuff[2]; + phs_n1 = sig_inObj->PhsBuff[3]; + phs_n2 = sig_inObj->PhsBuff[4]; + + /* find and smooth components which have full context */ + j = n_comp; + for (i=0; i<5; i++) { + if (Pvoxbnd[i]=0)?(*tmp2)>>PICODSP_SHIFT_FACT4:-((-(*tmp2))>>PICODSP_SHIFT_FACT4);tmp2++); + *tmp2 = (*tmp2 >= 0) ? (*tmp2) >> PICODSP_SHIFT_FACT4 : -((-(*tmp2)) + >> PICODSP_SHIFT_FACT4); /*ang[voxbnd-1]/=2;*/ + } + + /* now for the unvoiced part */ + iRand = sig_inObj->iRand; + c = sig_inObj->randCosTbl + iRand; + s = sig_inObj->randSinTbl + iRand; + co = sig_inObj->outCosTbl + firstUV; + so = sig_inObj->outSinTbl + firstUV; + for (nI = firstUV; nI < PICODSP_HFFTSIZE_P1 - 1; nI++) { + *co++ = *c++; + *so++ = *s++; + } + *co = 1; + *so = 0; + sig_inObj->iRand += (PICODSP_HFFTSIZE_P1 - firstUV); + if (sig_inObj->iRand > PICODSP_N_RAND_TABLE - PICODSP_HFFTSIZE_P1) + sig_inObj->iRand = 1 + sig_inObj->iRand + PICODSP_HFFTSIZE_P1 + - PICODSP_N_RAND_TABLE; +}/*phase_spec2*/ + +/** + * Prepare Envelope spectrum for inverse FFT + * @param sig_inObj : sig PU internal object of the sub-object + * @return void + * @remarks make phase bilateral -->> angh (FFT size, real) + * @remarks combine in complex input vector for IFFT F = e**(spet/2+j*ang) + * @remarks Compute energy -->> E (scalar, real) + * @callgraph + * @callergraph + * Input + * - spect (FFT size, real) + * - ang (half FFT size -1, real) + * - m2 fftsize + * - WNr,WNi (FFT size, real) the tabulated sine and cosine values + * - brev (FFT size, real) the tabulated bit reversal indexes + * Output + * - Fr, Fi (FFT size, complex) the envelope spectrum + * - E (scalar, real) the energy + */ +void env_spec(sig_innerobj_t *sig_inObj) +{ + + picoos_int16 nI; + picoos_int32 fcX, fsX, fExp, voxbnd; + picoos_int32 *spect, *ang, *ctbl; + picoos_int16 voiced, prev_voiced; + picoos_int32 *co, *so; + picoos_int32 *Fr, *Fi; + picoos_single mult; + + /*Link local variables to sig object*/ + spect = sig_inObj->wcep_pI; /*spect_p*/ + /* current spect scale : times PICODSP_FIX_SCALE1 */ + ang = sig_inObj->ang_p; + /* current spect scale : PICODSP_M_PI = PICODSP_FIX_SCALE2 */ + Fr = sig_inObj->F2r_p; + Fi = sig_inObj->F2i_p; + voiced = sig_inObj->voiced_p; + prev_voiced = sig_inObj->prevVoiced_p; + voxbnd = (picoos_int32) (sig_inObj->voxbnd_p * sig_inObj->voicing); + ctbl = sig_inObj->cos_table; + /* ctbl scale : times 4096 */ + mult = PICODSP_ENVSPEC_K1 / PICODSP_FIX_SCALE1; + + /*remove dc from real part*/ + if (sig_inObj->F0_p > 120) { + spect[0] = spect[1] = 0; + spect[2] /= PICODSP_ENVSPEC_K2; + } else { + spect[0] = 0; + } + + /* if using rand table, use sin and cos tables as well */ + if (voiced || (prev_voiced)) { + /*Envelope becomes a complex exponential : F=exp(.5*spect + j*angh);*/ + for (nI = 0; nI < voxbnd; nI++) { + get_trig(ang[nI], ctbl, &fcX, &fsX); + fExp = (picoos_int32) EXP((double)spect[nI]*mult); + Fr[nI] = fExp * fcX; + Fi[nI] = fExp * fsX; + } + /* ao=sig_inObj->ang_p+(picoos_int32)voxbnd; */ + co = sig_inObj->outCosTbl + voxbnd; + so = sig_inObj->outSinTbl + voxbnd; + + for (nI = voxbnd; nI < PICODSP_HFFTSIZE_P1; nI++) { + fcX = *co++; + fsX = *so++; + fExp = (picoos_int32) EXP((double)spect[nI]*mult); + Fr[nI] = fExp * fcX; + Fi[nI] = fExp * fsX; + } + } else { + /*ao=sig_inObj->ang_p+1;*/ + co = sig_inObj->outCosTbl + 1; + so = sig_inObj->outSinTbl + 1; + for (nI = 1; nI < PICODSP_HFFTSIZE_P1; nI++) { + fcX = *co++; + fsX = *so++; + fExp = (picoos_int32) EXP((double)spect[nI]*mult); + + Fr[nI] = fExp * fcX; + Fi[nI] = fExp * fsX; + } + } + +}/*env_spec*/ + +/** + * Calculates the impulse response of the comlpex spectrum through inverse rFFT + * @param sig_inObj : sig PU internal object of the sub-object + * @return void + * @remarks Imp corresponds with the real part of the FFT + * @callgraph + * @callergraph + * Input + * - Fr, Fi (FFT size, real & imaginary) the complex envelope spectrum (only first half of spectrum) + * Output + * - Imp: impulse response (length: m2) + * - E (scalar, real) RMS value + */ +void impulse_response(sig_innerobj_t *sig_inObj) +{ + /*Define local variables*/ + picoos_single f; + picoos_int16 nI, nn, m2, m4, voiced; + picoos_single *E; + picoos_int32 *norm_window; /* - fixed point */ + picoos_int32 *fr, *Fr, *Fi, *t1, ff; /* - fixed point */ + + /*Link local variables with sig object*/ + m2 = sig_inObj->m2_p; + m4 = m2 >> 1; + Fr = sig_inObj->F2r_p; + Fi = sig_inObj->F2i_p; + norm_window = sig_inObj->norm_window_p; + E = &(sig_inObj->E_p); /*as pointer: value will be modified*/ + voiced = sig_inObj->voiced_p; + fr = sig_inObj->imp_p; + + /*Inverse FFT*/ + for (nI = 0, nn = 0; nI < m4; nI++, nn += 2) { + fr[nn] = Fr[nI]; /* - fixed point */ + } + + fr[1] = (picoos_int32) (Fr[m4]); + for (nI = 1, nn = 3; nI < m4; nI++, nn += 2) { + fr[nn] = -Fi[nI]; /* - fixed point */ + } + + rdft(m2, -1, fr); + /*window, normalize and differentiate*/ + *E = norm_result(m2, fr, norm_window); + + if (*E > 0) + f = *E * PICODSP_FIXRESP_NORM; + else + f = 20; /*PICODSP_FIXRESP_NORM*/ + ff = (picoos_int32) f; + if (ff < 1) + ff = 1; + /*normalize impulse response*/ + t1 = fr;FAST_DEVICE(PICODSP_FFTSIZE,*(t1++) /= ff;); /* - fixed point */ + +} /* impulse_response */ + +/** + * time domain pitch synchronous overlap add over two frames (when no voicing transition) + * @param sig_inObj : sig PU internal object of the sub-object + * @return void + * @remarks Special treatment at voicing boundaries + * @remarks Introduced to get rid of time-domain aliasing (and additional speed up) + * @callgraph + * @callergraph + */ +void td_psola2(sig_innerobj_t *sig_inObj) +{ + picoos_int16 nI; + picoos_int16 hop, m2, *nextPeak, voiced; + picoos_int32 *t1, *t2; + picoos_int16 cnt; + picoos_int32 *fr, *v1, ff, f; + picoos_int16 a, i; + picoos_int32 *window; + picoos_int16 s = (picoos_int16) 1; + window = sig_inObj->window_p; + + /*Link local variables with sig object*/ + hop = sig_inObj->hop_p; + m2 = sig_inObj->m2_p; + nextPeak = &(sig_inObj->nextPeak_p); + voiced = sig_inObj->voiced_p; + fr = sig_inObj->imp_p; + /*toggle the pointers and initialize signal vector */ + v1 = sig_inObj->sig_vec1; + + t1 = v1; + FAST_DEVICE(PICODSP_FFTSIZE-PICODSP_DISPLACE,*(t1++)=0;); + t1 = &(v1[PICODSP_FFTSIZE - PICODSP_DISPLACE]); + t2 = &(v1[PICODSP_FFTSIZE]); + FAST_DEVICE(PICODSP_FFTSIZE, *(t1++)=*(t2++);); + t1 = &(v1[2 * PICODSP_FFTSIZE - PICODSP_DISPLACE]);FAST_DEVICE(PICODSP_DISPLACE,*(t1++)=0;); + /*calculate excitation points*/ + get_simple_excitation(sig_inObj, nextPeak); + + /*TD-PSOLA based on excitation vector */ + if ((sig_inObj->nU == 0) && (sig_inObj->voiced_p == 1)) { + /* purely voiced */ + for (nI = 0; nI < sig_inObj->nV; nI++) { + f = sig_inObj->EnV[nI]; + a = 0; + cnt = PICODSP_FFTSIZE; + ff = (f * window[sig_inObj->LocV[nI]]) >> PICODSP_SHIFT_FACT1; + t1 = &(v1[a + sig_inObj->LocV[nI]]); + t2 = &(fr[a]); + if (cnt > 0)FAST_DEVICE(cnt,*(t1++)+=*(t2++)*ff;); + } + } else if ((sig_inObj->nV == 0) && (sig_inObj->voiced_p == 0)) { + /* PURELY UNVOICED*/ + for (nI = 0; nI < sig_inObj->nU; nI++) { + f = sig_inObj->EnU[nI]; + s = -s; /*reverse order to reduce the periodicity effect*/ + if (s == 1) { + a = 0; + cnt = PICODSP_FFTSIZE; + ff = (f * window[sig_inObj->LocU[nI]]) >> PICODSP_SHIFT_FACT1; + t1 = &(v1[a + sig_inObj->LocU[nI]]); + t2 = &(fr[a]); + if (cnt > 0)FAST_DEVICE(cnt,*(t1++)+=*(t2++)*ff; ); + } else { /*s==-1*/ + a = 0; + cnt = PICODSP_FFTSIZE; + ff = (f * window[sig_inObj->LocU[nI]]) >> PICODSP_SHIFT_FACT1; + t1 = &(v1[(m2 - 1 - a) + sig_inObj->LocU[nI]]); + t2 = &(fr[a]); + if (cnt > 0)FAST_DEVICE(cnt,*(t1--)+=*(t2++)*ff; ); + } + } + } else if (sig_inObj->VoicTrans == 0) { + /*voicing transition from unvoiced to voiced*/ + for (nI = 0; nI < sig_inObj->nV; nI++) { + f = sig_inObj->EnV[nI]; + a = 0; + cnt = PICODSP_FFTSIZE; + ff = (f * window[sig_inObj->LocV[nI]]) >> PICODSP_SHIFT_FACT1; + t1 = &(v1[a + sig_inObj->LocV[nI]]); + t2 = &(fr[a]); + if (cnt > 0)FAST_DEVICE(cnt,*(t1++)+=*(t2++)*ff;); + } + /*add remaining stuff from unvoiced part*/ + for (nI = 0; nI < sig_inObj->nU; nI++) { + f = sig_inObj->EnU[nI]; + s = -s; /*reverse order to reduce the periodicity effect*/ + if (s == 1) { + a = 0; + cnt = PICODSP_FFTSIZE; + ff = (f * window[sig_inObj->LocU[nI]]) >> PICODSP_SHIFT_FACT1; + t1 = &(v1[a + sig_inObj->LocU[nI]]); + t2 = &(sig_inObj->ImpResp_p[a]); /*saved impulse response*/ + if (cnt > 0)FAST_DEVICE(cnt,*(t1++)+=*(t2++)*ff; ); + } else { + a = 0; + cnt = PICODSP_FFTSIZE; + ff = (f * window[sig_inObj->LocU[nI]]) >> PICODSP_SHIFT_FACT1; + t1 = &(v1[(m2 - 1 - a) + sig_inObj->LocU[nI]]); + t2 = &(sig_inObj->ImpResp_p[a]); + if (cnt > 0)FAST_DEVICE(cnt,*(t1--)+=*(t2++)*ff; ); + } + } + } else { + /*voiced to unvoiced*/ + for (nI = 0; nI < sig_inObj->nU; nI++) { + f = sig_inObj->EnU[nI]; + s = -s; /*reverse order to reduce the periodicity effect*/ + if (s > 0) { + a = 0; + cnt = PICODSP_FFTSIZE; + ff = (f * window[sig_inObj->LocU[nI]]) >> PICODSP_SHIFT_FACT1; + t1 = &(v1[a + sig_inObj->LocU[nI]]); + t2 = &(fr[a]); + if (cnt > 0)FAST_DEVICE(cnt,*(t1++)+=*(t2++)*ff; ); + } else { + a = 0; + cnt = PICODSP_FFTSIZE; + ff = (f * window[sig_inObj->LocU[nI]]) >> PICODSP_SHIFT_FACT1; + t1 = &(v1[(m2 - 1 - a) + sig_inObj->LocU[nI]]); + t2 = &(fr[a]); + if (cnt > 0)FAST_DEVICE(cnt,*(t1--)+=*(t2++)*ff; ); + } + } + /*add remaining stuff from voiced part*/ + for (nI = 0; nI < sig_inObj->nV; nI++) { + f = sig_inObj->EnV[nI]; + a = 0; + cnt = PICODSP_FFTSIZE; + ff = (f * window[sig_inObj->LocV[nI]]) >> PICODSP_SHIFT_FACT1; + t1 = &(v1[a + sig_inObj->LocV[nI]]); + t2 = &(sig_inObj->ImpResp_p[a]); + if (cnt > 0)FAST_DEVICE(cnt,*(t1++)+=*(t2++)*ff;); + } + } + + t1 = sig_inObj->sig_vec1; + for (i = 0; i < PICODSP_FFTSIZE; i++, t1++) { + if (*t1 >= 0) + *t1 >>= PICODSP_SHIFT_FACT5; + else + *t1 = -((-*t1) >> PICODSP_SHIFT_FACT5); + } + +}/*td_psola2*/ + +/** + * overlap + add summing of impulse responses on the final destination sample buffer + * @param sig_inObj : sig PU internal object of the sub-object + * @return void + * @remarks Special treatment at voicing boundaries + * @remarks Introduced to get rid of time-domain aliasing (and additional speed up) + * Input + * - wlet : the generic impulse response (FFT size, real) + * - window : the windowing funcion (FFT size, real) fixed + * - WavBuff : the destination buffer with past samples (FFT size*2, short) + * - m2 : fftsize + * Output + * - WavBuff : the destination buffer with updated samples (FFT size*2, short) + * @callgraph + * @callergraph + */ +void overlap_add(sig_innerobj_t *sig_inObj) +{ + /*Local variables*/ + picoos_int32 *w, *v; + + /*Link local variables with sig object*/ + w = sig_inObj->WavBuff_p; + v = sig_inObj->sig_vec1; + + FAST_DEVICE(PICODSP_FFTSIZE, *(w++)+=*(v++)<window_p; + norm = sig_inObj->norm_window_p; + + norm[0] = 80224; + norm[1] = 320832; + norm[2] = 721696; + norm[3] = 1282560; + norm[4] = 2003104; + norm[5] = 2882880; + norm[6] = 3921376; + norm[7] = 5117984; + norm[8] = 6471952; + norm[9] = 7982496; + norm[10] = 9648720; + norm[11] = 11469616; + norm[12] = 13444080; + norm[13] = 15570960; + norm[14] = 17848976; + norm[15] = 20276752; + norm[16] = 22852864; + norm[17] = 25575744; + norm[18] = 28443776; + norm[19] = 31455264; + norm[20] = 34608368; + norm[21] = 37901248; + norm[22] = 41331904; + norm[23] = 44898304; + norm[24] = 48598304; + norm[25] = 52429696; + norm[26] = 56390192; + norm[27] = 60477408; + norm[28] = 64688944; + norm[29] = 69022240; + norm[30] = 73474720; + norm[31] = 78043744; + norm[32] = 82726544; + norm[33] = 87520352; + norm[34] = 92422272; + norm[35] = 97429408; + norm[36] = 102538752; + norm[37] = 107747248; + norm[38] = 113051776; + norm[39] = 118449184; + norm[40] = 123936224; + norm[41] = 129509648; + norm[42] = 135166080; + norm[43] = 140902192; + norm[44] = 146714528; + norm[45] = 152599584; + norm[46] = 158553904; + norm[47] = 164573888; + norm[48] = 170655936; + norm[49] = 176796448; + norm[50] = 182991712; + norm[51] = 189238064; + norm[52] = 195531744; + norm[53] = 201868992; + norm[54] = 208246016; + norm[55] = 214659040; + norm[56] = 221104176; + norm[57] = 227577616; + norm[58] = 234075488; + norm[59] = 240593872; + norm[60] = 247128912; + norm[61] = 253676688; + norm[62] = 260233280; + norm[63] = 266794768; + norm[64] = 273357248; + norm[65] = 279916768; + norm[66] = 286469440; + norm[67] = 293011360; + norm[68] = 299538560; + norm[69] = 306047168; + norm[70] = 312533312; + norm[71] = 318993088; + norm[72] = 325422656; + norm[73] = 331818144; + norm[74] = 338175744; + norm[75] = 344491680; + norm[76] = 350762176; + norm[77] = 356983424; + norm[78] = 363151808; + norm[79] = 369263520; + norm[80] = 375315008; + norm[81] = 381302592; + norm[82] = 387222720; + norm[83] = 393071872; + norm[84] = 398846528; + norm[85] = 404543232; + norm[86] = 410158560; + norm[87] = 415689216; + norm[88] = 421131840; + norm[89] = 426483200; + norm[90] = 431740096; + norm[91] = 436899392; + norm[92] = 441958016; + norm[93] = 446912928; + norm[94] = 451761152; + norm[95] = 456499840; + norm[96] = 461126080; + norm[97] = 465637152; + norm[98] = 470030400; + norm[99] = 474303104; + norm[100] = 478452800; + norm[101] = 482476960; + norm[102] = 486373184; + norm[103] = 490139200; + norm[104] = 493772640; + norm[105] = 497271424; + norm[106] = 500633440; + norm[107] = 503856704; + norm[108] = 506939200; + norm[109] = 509879168; + norm[110] = 512674880; + norm[111] = 515324544; + norm[112] = 517826688; + norm[113] = 520179776; + norm[114] = 522382368; + norm[115] = 524433184; + norm[116] = 526331008; + norm[117] = 528074688; + norm[118] = 529663200; + norm[119] = 531095552; + norm[120] = 532370944; + norm[121] = 533488576; + norm[122] = 534447808; + norm[123] = 535248000; + norm[124] = 535888768; + norm[125] = 536369664; + norm[126] = 536690432; + norm[127] = 536850880; + norm[128] = 536850880; + norm[129] = 536690432; + norm[130] = 536369664; + norm[131] = 535888768; + norm[132] = 535248000; + norm[133] = 534447808; + norm[134] = 533488576; + norm[135] = 532370944; + norm[136] = 531095552; + norm[137] = 529663200; + norm[138] = 528074688; + norm[139] = 526331008; + norm[140] = 524433216; + norm[141] = 522382368; + norm[142] = 520179776; + norm[143] = 517826688; + norm[144] = 515324544; + norm[145] = 512674880; + norm[146] = 509879168; + norm[147] = 506939200; + norm[148] = 503856704; + norm[149] = 500633472; + norm[150] = 497271424; + norm[151] = 493772672; + norm[152] = 490139200; + norm[153] = 486373184; + norm[154] = 482476992; + norm[155] = 478452800; + norm[156] = 474303104; + norm[157] = 470030400; + norm[158] = 465637184; + norm[159] = 461126080; + norm[160] = 456499840; + norm[161] = 451761152; + norm[162] = 446912960; + norm[163] = 441958016; + norm[164] = 436899424; + norm[165] = 431740096; + norm[166] = 426483200; + norm[167] = 421131840; + norm[168] = 415689216; + norm[169] = 410158560; + norm[170] = 404543232; + norm[171] = 398846528; + norm[172] = 393071872; + norm[173] = 387222720; + norm[174] = 381302592; + norm[175] = 375315008; + norm[176] = 369263552; + norm[177] = 363151808; + norm[178] = 356983456; + norm[179] = 350762176; + norm[180] = 344491712; + norm[181] = 338175776; + norm[182] = 331818144; + norm[183] = 325422656; + norm[184] = 318993088; + norm[185] = 312533312; + norm[186] = 306047168; + norm[187] = 299538560; + norm[188] = 293011360; + norm[189] = 286469472; + norm[190] = 279916800; + norm[191] = 273357248; + norm[192] = 266794784; + norm[193] = 260233280; + norm[194] = 253676688; + norm[195] = 247128928; + norm[196] = 240593888; + norm[197] = 234075488; + norm[198] = 227577632; + norm[199] = 221104192; + norm[200] = 214659040; + norm[201] = 208246032; + norm[202] = 201868992; + norm[203] = 195531744; + norm[204] = 189238080; + norm[205] = 182991728; + norm[206] = 176796448; + norm[207] = 170655952; + norm[208] = 164573888; + norm[209] = 158553920; + norm[210] = 152599600; + norm[211] = 146714528; + norm[212] = 140902208; + norm[213] = 135166096; + norm[214] = 129509648; + norm[215] = 123936240; + norm[216] = 118449184; + norm[217] = 113051776; + norm[218] = 107747248; + norm[219] = 102538752; + norm[220] = 97429424; + norm[221] = 92422288; + norm[222] = 87520352; + norm[223] = 82726544; + norm[224] = 78043744; + norm[225] = 73474736; + norm[226] = 69022240; + norm[227] = 64688944; + norm[228] = 60477424; + norm[229] = 56390192; + norm[230] = 52429696; + norm[231] = 48598304; + norm[232] = 44898304; + norm[233] = 41331904; + norm[234] = 37901248; + norm[235] = 34608384; + norm[236] = 31455264; + norm[237] = 28443792; + norm[238] = 25575744; + norm[239] = 22852864; + norm[240] = 20276752; + norm[241] = 17848976; + norm[242] = 15570960; + norm[243] = 13444080; + norm[244] = 11469616; + norm[245] = 9648720; + norm[246] = 7982512; + norm[247] = 6471952; + norm[248] = 5117984; + norm[249] = 3921376; + norm[250] = 2882880; + norm[251] = 2003104; + norm[252] = 1282560; + norm[253] = 721696; + norm[254] = 320832; + norm[255] = 80224; + hann[0] = 0; + hann[1] = 0; + hann[2] = 1; + hann[3] = 2; + hann[4] = 3; + hann[5] = 5; + hann[6] = 7; + hann[7] = 9; + hann[8] = 12; + hann[9] = 15; + hann[10] = 18; + hann[11] = 21; + hann[12] = 25; + hann[13] = 29; + hann[14] = 34; + hann[15] = 38; + hann[16] = 43; + hann[17] = 48; + hann[18] = 54; + hann[19] = 59; + hann[20] = 66; + hann[21] = 72; + hann[22] = 78; + hann[23] = 85; + hann[24] = 92; + hann[25] = 100; + hann[26] = 107; + hann[27] = 115; + hann[28] = 123; + hann[29] = 131; + hann[30] = 140; + hann[31] = 148; + hann[32] = 157; + hann[33] = 166; + hann[34] = 176; + hann[35] = 185; + hann[36] = 195; + hann[37] = 205; + hann[38] = 215; + hann[39] = 225; + hann[40] = 236; + hann[41] = 247; + hann[42] = 257; + hann[43] = 268; + hann[44] = 279; + hann[45] = 291; + hann[46] = 302; + hann[47] = 313; + hann[48] = 325; + hann[49] = 337; + hann[50] = 349; + hann[51] = 360; + hann[52] = 372; + hann[53] = 385; + hann[54] = 397; + hann[55] = 409; + hann[56] = 421; + hann[57] = 434; + hann[58] = 446; + hann[59] = 458; + hann[60] = 471; + hann[61] = 483; + hann[62] = 496; + hann[63] = 508; + hann[64] = 521; + hann[65] = 533; + hann[66] = 546; + hann[67] = 558; + hann[68] = 571; + hann[69] = 583; + hann[70] = 596; + hann[71] = 608; + hann[72] = 620; + hann[73] = 632; + hann[74] = 645; + hann[75] = 657; + hann[76] = 669; + hann[77] = 680; + hann[78] = 692; + hann[79] = 704; + hann[80] = 715; + hann[81] = 727; + hann[82] = 738; + hann[83] = 749; + hann[84] = 760; + hann[85] = 771; + hann[86] = 782; + hann[87] = 792; + hann[88] = 803; + hann[89] = 813; + hann[90] = 823; + hann[91] = 833; + hann[92] = 842; + hann[93] = 852; + hann[94] = 861; + hann[95] = 870; + hann[96] = 879; + hann[97] = 888; + hann[98] = 896; + hann[99] = 904; + hann[100] = 912; + hann[101] = 920; + hann[102] = 927; + hann[103] = 934; + hann[104] = 941; + hann[105] = 948; + hann[106] = 954; + hann[107] = 961; + hann[108] = 966; + hann[109] = 972; + hann[110] = 977; + hann[111] = 982; + hann[112] = 987; + hann[113] = 992; + hann[114] = 996; + hann[115] = 1000; + hann[116] = 1003; + hann[117] = 1007; + hann[118] = 1010; + hann[119] = 1012; + hann[120] = 1015; + hann[121] = 1017; + hann[122] = 1019; + hann[123] = 1020; + hann[124] = 1022; + hann[125] = 1023; + hann[126] = 1023; + hann[127] = 1023; + hann[128] = 1023; + hann[129] = 1023; + hann[130] = 1023; + hann[131] = 1022; + hann[132] = 1020; + hann[133] = 1019; + hann[134] = 1017; + hann[135] = 1015; + hann[136] = 1012; + hann[137] = 1010; + hann[138] = 1007; + hann[139] = 1003; + hann[140] = 1000; + hann[141] = 996; + hann[142] = 992; + hann[143] = 987; + hann[144] = 982; + hann[145] = 977; + hann[146] = 972; + hann[147] = 966; + hann[148] = 961; + hann[149] = 954; + hann[150] = 948; + hann[151] = 941; + hann[152] = 934; + hann[153] = 927; + hann[154] = 920; + hann[155] = 912; + hann[156] = 904; + hann[157] = 896; + hann[158] = 888; + hann[159] = 879; + hann[160] = 870; + hann[161] = 861; + hann[162] = 852; + hann[163] = 842; + hann[164] = 833; + hann[165] = 823; + hann[166] = 813; + hann[167] = 803; + hann[168] = 792; + hann[169] = 782; + hann[170] = 771; + hann[171] = 760; + hann[172] = 749; + hann[173] = 738; + hann[174] = 727; + hann[175] = 715; + hann[176] = 704; + hann[177] = 692; + hann[178] = 680; + hann[179] = 669; + hann[180] = 657; + hann[181] = 645; + hann[182] = 632; + hann[183] = 620; + hann[184] = 608; + hann[185] = 596; + hann[186] = 583; + hann[187] = 571; + hann[188] = 558; + hann[189] = 546; + hann[190] = 533; + hann[191] = 521; + hann[192] = 508; + hann[193] = 496; + hann[194] = 483; + hann[195] = 471; + hann[196] = 458; + hann[197] = 446; + hann[198] = 434; + hann[199] = 421; + hann[200] = 409; + hann[201] = 397; + hann[202] = 385; + hann[203] = 372; + hann[204] = 360; + hann[205] = 349; + hann[206] = 337; + hann[207] = 325; + hann[208] = 313; + hann[209] = 302; + hann[210] = 291; + hann[211] = 279; + hann[212] = 268; + hann[213] = 257; + hann[214] = 247; + hann[215] = 236; + hann[216] = 225; + hann[217] = 215; + hann[218] = 205; + hann[219] = 195; + hann[220] = 185; + hann[221] = 176; + hann[222] = 166; + hann[223] = 157; + hann[224] = 148; + hann[225] = 140; + hann[226] = 131; + hann[227] = 123; + hann[228] = 115; + hann[229] = 107; + hann[230] = 100; + hann[231] = 92; + hann[232] = 85; + hann[233] = 78; + hann[234] = 72; + hann[235] = 66; + hann[236] = 59; + hann[237] = 54; + hann[238] = 48; + hann[239] = 43; + hann[240] = 38; + hann[241] = 34; + hann[242] = 29; + hann[243] = 25; + hann[244] = 21; + hann[245] = 18; + hann[246] = 15; + hann[247] = 12; + hann[248] = 9; + hann[249] = 7; + hann[250] = 5; + hann[251] = 3; + hann[252] = 2; + hann[253] = 1; + hann[254] = 0; + hann[255] = 0; + +} /* gen_hann2 */ + +/** + * Creates the non uniform enhancement window (bilinearly mapped hannning window) + * in order to reduce the formant enhancement in the high spectrum + * @param mm : memory manager + * @param sig_inObj : sig PU internal object of the sub-object + * @return void + * @callgraph + * @callergraph + * @remarks the outgput is based on the matlab script below\n + matlab script + ------------- + function makeEnhWind(alpha) + N=129; % =HFFTSIZEE_P1 + s=(bilinmap(alpha,N)); + h=[hann(N)']; + x=(1:N)/N; + W=interp1(x,h,s); W(1)=0; + + fid=fopen('enhwind.txt','wt'); + fprintf(fid,'picoos_int16 enh_wind_init(sig_innerobj_t *sig_inObj) {\n'); + for i=1:N, + fprintf(fid,[' sig_inObj->enhwind[' int2str(i) '] = (picoos_single)' num2str(W(i),'%0.7g') ';\n']); + end; + fprintf(fid,' return PICO_OK;\n'); + fprintf(fid,' }; \n'); + fclose(fid); + %figure(1); plot(x*8,W); + */ +static void enh_wind_init(sig_innerobj_t *sig_inObj) +{ + /* picoos_int16 i; */ + picoos_int32 *c; + + c = sig_inObj->cos_table; + + c[0] = 4096; + c[1] = 4095; + c[2] = 4095; + c[3] = 4095; + c[4] = 4095; + c[5] = 4095; + c[6] = 4095; + c[7] = 4095; + c[8] = 4094; + c[9] = 4094; + c[10] = 4094; + c[11] = 4093; + c[12] = 4093; + c[13] = 4092; + c[14] = 4092; + c[15] = 4091; + c[16] = 4091; + c[17] = 4090; + c[18] = 4089; + c[19] = 4089; + c[20] = 4088; + c[21] = 4087; + c[22] = 4086; + c[23] = 4085; + c[24] = 4084; + c[25] = 4083; + c[26] = 4082; + c[27] = 4081; + c[28] = 4080; + c[29] = 4079; + c[30] = 4078; + c[31] = 4077; + c[32] = 4076; + c[33] = 4075; + c[34] = 4073; + c[35] = 4072; + c[36] = 4071; + c[37] = 4069; + c[38] = 4068; + c[39] = 4066; + c[40] = 4065; + c[41] = 4063; + c[42] = 4062; + c[43] = 4060; + c[44] = 4058; + c[45] = 4057; + c[46] = 4055; + c[47] = 4053; + c[48] = 4051; + c[49] = 4049; + c[50] = 4047; + c[51] = 4045; + c[52] = 4043; + c[53] = 4041; + c[54] = 4039; + c[55] = 4037; + c[56] = 4035; + c[57] = 4033; + c[58] = 4031; + c[59] = 4029; + c[60] = 4026; + c[61] = 4024; + c[62] = 4022; + c[63] = 4019; + c[64] = 4017; + c[65] = 4014; + c[66] = 4012; + c[67] = 4009; + c[68] = 4007; + c[69] = 4004; + c[70] = 4001; + c[71] = 3999; + c[72] = 3996; + c[73] = 3993; + c[74] = 3990; + c[75] = 3988; + c[76] = 3985; + c[77] = 3982; + c[78] = 3979; + c[79] = 3976; + c[80] = 3973; + c[81] = 3970; + c[82] = 3967; + c[83] = 3963; + c[84] = 3960; + c[85] = 3957; + c[86] = 3954; + c[87] = 3950; + c[88] = 3947; + c[89] = 3944; + c[90] = 3940; + c[91] = 3937; + c[92] = 3933; + c[93] = 3930; + c[94] = 3926; + c[95] = 3923; + c[96] = 3919; + c[97] = 3915; + c[98] = 3912; + c[99] = 3908; + c[100] = 3904; + c[101] = 3900; + c[102] = 3897; + c[103] = 3893; + c[104] = 3889; + c[105] = 3885; + c[106] = 3881; + c[107] = 3877; + c[108] = 3873; + c[109] = 3869; + c[110] = 3864; + c[111] = 3860; + c[112] = 3856; + c[113] = 3852; + c[114] = 3848; + c[115] = 3843; + c[116] = 3839; + c[117] = 3834; + c[118] = 3830; + c[119] = 3826; + c[120] = 3821; + c[121] = 3816; + c[122] = 3812; + c[123] = 3807; + c[124] = 3803; + c[125] = 3798; + c[126] = 3793; + c[127] = 3789; + c[128] = 3784; + c[129] = 3779; + c[130] = 3774; + c[131] = 3769; + c[132] = 3764; + c[133] = 3759; + c[134] = 3754; + c[135] = 3749; + c[136] = 3744; + c[137] = 3739; + c[138] = 3734; + c[139] = 3729; + c[140] = 3723; + c[141] = 3718; + c[142] = 3713; + c[143] = 3708; + c[144] = 3702; + c[145] = 3697; + c[146] = 3691; + c[147] = 3686; + c[148] = 3680; + c[149] = 3675; + c[150] = 3669; + c[151] = 3664; + c[152] = 3658; + c[153] = 3652; + c[154] = 3647; + c[155] = 3641; + c[156] = 3635; + c[157] = 3629; + c[158] = 3624; + c[159] = 3618; + c[160] = 3612; + c[161] = 3606; + c[162] = 3600; + c[163] = 3594; + c[164] = 3588; + c[165] = 3582; + c[166] = 3576; + c[167] = 3570; + c[168] = 3563; + c[169] = 3557; + c[170] = 3551; + c[171] = 3545; + c[172] = 3538; + c[173] = 3532; + c[174] = 3526; + c[175] = 3519; + c[176] = 3513; + c[177] = 3506; + c[178] = 3500; + c[179] = 3493; + c[180] = 3487; + c[181] = 3480; + c[182] = 3473; + c[183] = 3467; + c[184] = 3460; + c[185] = 3453; + c[186] = 3447; + c[187] = 3440; + c[188] = 3433; + c[189] = 3426; + c[190] = 3419; + c[191] = 3412; + c[192] = 3405; + c[193] = 3398; + c[194] = 3391; + c[195] = 3384; + c[196] = 3377; + c[197] = 3370; + c[198] = 3363; + c[199] = 3356; + c[200] = 3348; + c[201] = 3341; + c[202] = 3334; + c[203] = 3326; + c[204] = 3319; + c[205] = 3312; + c[206] = 3304; + c[207] = 3297; + c[208] = 3289; + c[209] = 3282; + c[210] = 3274; + c[211] = 3267; + c[212] = 3259; + c[213] = 3252; + c[214] = 3244; + c[215] = 3236; + c[216] = 3229; + c[217] = 3221; + c[218] = 3213; + c[219] = 3205; + c[220] = 3197; + c[221] = 3190; + c[222] = 3182; + c[223] = 3174; + c[224] = 3166; + c[225] = 3158; + c[226] = 3150; + c[227] = 3142; + c[228] = 3134; + c[229] = 3126; + c[230] = 3117; + c[231] = 3109; + c[232] = 3101; + c[233] = 3093; + c[234] = 3085; + c[235] = 3076; + c[236] = 3068; + c[237] = 3060; + c[238] = 3051; + c[239] = 3043; + c[240] = 3034; + c[241] = 3026; + c[242] = 3018; + c[243] = 3009; + c[244] = 3000; + c[245] = 2992; + c[246] = 2983; + c[247] = 2975; + c[248] = 2966; + c[249] = 2957; + c[250] = 2949; + c[251] = 2940; + c[252] = 2931; + c[253] = 2922; + c[254] = 2914; + c[255] = 2905; + c[256] = 2896; + c[257] = 2887; + c[258] = 2878; + c[259] = 2869; + c[260] = 2860; + c[261] = 2851; + c[262] = 2842; + c[263] = 2833; + c[264] = 2824; + c[265] = 2815; + c[266] = 2806; + c[267] = 2796; + c[268] = 2787; + c[269] = 2778; + c[270] = 2769; + c[271] = 2760; + c[272] = 2750; + c[273] = 2741; + c[274] = 2732; + c[275] = 2722; + c[276] = 2713; + c[277] = 2703; + c[278] = 2694; + c[279] = 2684; + c[280] = 2675; + c[281] = 2665; + c[282] = 2656; + c[283] = 2646; + c[284] = 2637; + c[285] = 2627; + c[286] = 2617; + c[287] = 2608; + c[288] = 2598; + c[289] = 2588; + c[290] = 2578; + c[291] = 2569; + c[292] = 2559; + c[293] = 2549; + c[294] = 2539; + c[295] = 2529; + c[296] = 2519; + c[297] = 2510; + c[298] = 2500; + c[299] = 2490; + c[300] = 2480; + c[301] = 2470; + c[302] = 2460; + c[303] = 2450; + c[304] = 2439; + c[305] = 2429; + c[306] = 2419; + c[307] = 2409; + c[308] = 2399; + c[309] = 2389; + c[310] = 2379; + c[311] = 2368; + c[312] = 2358; + c[313] = 2348; + c[314] = 2337; + c[315] = 2327; + c[316] = 2317; + c[317] = 2306; + c[318] = 2296; + c[319] = 2286; + c[320] = 2275; + c[321] = 2265; + c[322] = 2254; + c[323] = 2244; + c[324] = 2233; + c[325] = 2223; + c[326] = 2212; + c[327] = 2201; + c[328] = 2191; + c[329] = 2180; + c[330] = 2170; + c[331] = 2159; + c[332] = 2148; + c[333] = 2138; + c[334] = 2127; + c[335] = 2116; + c[336] = 2105; + c[337] = 2094; + c[338] = 2084; + c[339] = 2073; + c[340] = 2062; + c[341] = 2051; + c[342] = 2040; + c[343] = 2029; + c[344] = 2018; + c[345] = 2007; + c[346] = 1997; + c[347] = 1986; + c[348] = 1975; + c[349] = 1964; + c[350] = 1952; + c[351] = 1941; + c[352] = 1930; + c[353] = 1919; + c[354] = 1908; + c[355] = 1897; + c[356] = 1886; + c[357] = 1875; + c[358] = 1864; + c[359] = 1852; + c[360] = 1841; + c[361] = 1830; + c[362] = 1819; + c[363] = 1807; + c[364] = 1796; + c[365] = 1785; + c[366] = 1773; + c[367] = 1762; + c[368] = 1751; + c[369] = 1739; + c[370] = 1728; + c[371] = 1717; + c[372] = 1705; + c[373] = 1694; + c[374] = 1682; + c[375] = 1671; + c[376] = 1659; + c[377] = 1648; + c[378] = 1636; + c[379] = 1625; + c[380] = 1613; + c[381] = 1602; + c[382] = 1590; + c[383] = 1579; + c[384] = 1567; + c[385] = 1555; + c[386] = 1544; + c[387] = 1532; + c[388] = 1520; + c[389] = 1509; + c[390] = 1497; + c[391] = 1485; + c[392] = 1474; + c[393] = 1462; + c[394] = 1450; + c[395] = 1438; + c[396] = 1427; + c[397] = 1415; + c[398] = 1403; + c[399] = 1391; + c[400] = 1379; + c[401] = 1368; + c[402] = 1356; + c[403] = 1344; + c[404] = 1332; + c[405] = 1320; + c[406] = 1308; + c[407] = 1296; + c[408] = 1284; + c[409] = 1272; + c[410] = 1260; + c[411] = 1248; + c[412] = 1237; + c[413] = 1225; + c[414] = 1213; + c[415] = 1201; + c[416] = 1189; + c[417] = 1176; + c[418] = 1164; + c[419] = 1152; + c[420] = 1140; + c[421] = 1128; + c[422] = 1116; + c[423] = 1104; + c[424] = 1092; + c[425] = 1080; + c[426] = 1068; + c[427] = 1056; + c[428] = 1043; + c[429] = 1031; + c[430] = 1019; + c[431] = 1007; + c[432] = 995; + c[433] = 983; + c[434] = 970; + c[435] = 958; + c[436] = 946; + c[437] = 934; + c[438] = 921; + c[439] = 909; + c[440] = 897; + c[441] = 885; + c[442] = 872; + c[443] = 860; + c[444] = 848; + c[445] = 836; + c[446] = 823; + c[447] = 811; + c[448] = 799; + c[449] = 786; + c[450] = 774; + c[451] = 762; + c[452] = 749; + c[453] = 737; + c[454] = 725; + c[455] = 712; + c[456] = 700; + c[457] = 687; + c[458] = 675; + c[459] = 663; + c[460] = 650; + c[461] = 638; + c[462] = 625; + c[463] = 613; + c[464] = 601; + c[465] = 588; + c[466] = 576; + c[467] = 563; + c[468] = 551; + c[469] = 538; + c[470] = 526; + c[471] = 513; + c[472] = 501; + c[473] = 488; + c[474] = 476; + c[475] = 463; + c[476] = 451; + c[477] = 438; + c[478] = 426; + c[479] = 413; + c[480] = 401; + c[481] = 388; + c[482] = 376; + c[483] = 363; + c[484] = 351; + c[485] = 338; + c[486] = 326; + c[487] = 313; + c[488] = 301; + c[489] = 288; + c[490] = 276; + c[491] = 263; + c[492] = 251; + c[493] = 238; + c[494] = 226; + c[495] = 213; + c[496] = 200; + c[497] = 188; + c[498] = 175; + c[499] = 163; + c[500] = 150; + c[501] = 138; + c[502] = 125; + c[503] = 113; + c[504] = 100; + c[505] = 87; + c[506] = 75; + c[507] = 62; + c[508] = 50; + c[509] = 37; + c[510] = 25; + c[511] = 12; + c[512] = 0; +} /*enh_wind_init*/ + +/** + * Initializes a useful large array of random numbers + * @param sig_inObj : sig PU internal object of the sub-object + * @return void + * @callgraph + * @callergraph + */ +static void init_rand(sig_innerobj_t *sig_inObj) +{ + picoos_int32 *q = sig_inObj->int_vec34; + picoos_int32 *r = sig_inObj->int_vec35; + + sig_inObj->iRand = 0; + + q[0] = -2198; + r[0] = 3455; + q[1] = 3226; + r[1] = -2522; + q[2] = -845; + r[2] = 4007; + q[3] = -1227; + r[3] = 3907; + q[4] = -3480; + r[4] = 2158; + q[5] = -1325; + r[5] = -3875; + q[6] = 2089; + r[6] = -3522; + q[7] = -468; + r[7] = 4069; + q[8] = 711; + r[8] = -4033; + q[9] = 3862; + r[9] = 1362; + q[10] = 4054; + r[10] = -579; + q[11] = 2825; + r[11] = 2965; + q[12] = 2704; + r[12] = -3076; + q[13] = 4081; + r[13] = 344; + q[14] = -3912; + r[14] = 1211; + q[15] = -3541; + r[15] = 2058; + q[16] = 2694; + r[16] = 3084; + q[17] = 835; + r[17] = 4009; + q[18] = -2578; + r[18] = -3182; + q[19] = 3205; + r[19] = 2550; + q[20] = -4074; + r[20] = -418; + q[21] = -183; + r[21] = -4091; + q[22] = -2665; + r[22] = -3110; + q[23] = -1367; + r[23] = 3860; + q[24] = -2266; + r[24] = -3411; + q[25] = 3327; + r[25] = -2387; + q[26] = -2807; + r[26] = -2982; + q[27] = -3175; + r[27] = -2587; + q[28] = -4095; + r[28] = 27; + q[29] = -811; + r[29] = -4014; + q[30] = 4082; + r[30] = 332; + q[31] = -2175; + r[31] = 3470; + q[32] = 3112; + r[32] = 2662; + q[33] = 1168; + r[33] = -3925; + q[34] = 2659; + r[34] = 3115; + q[35] = 4048; + r[35] = 622; + q[36] = 4092; + r[36] = -165; + q[37] = -4036; + r[37] = 697; + q[38] = 1081; + r[38] = -3950; + q[39] = -548; + r[39] = 4059; + q[40] = 4038; + r[40] = 685; + q[41] = -511; + r[41] = 4063; + q[42] = 3317; + r[42] = -2402; + q[43] = -3180; + r[43] = 2580; + q[44] = 851; + r[44] = -4006; + q[45] = 2458; + r[45] = -3276; + q[46] = -1453; + r[46] = 3829; + q[47] = -3577; + r[47] = 1995; + q[48] = -3708; + r[48] = -1738; + q[49] = -3890; + r[49] = 1282; + q[50] = 4041; + r[50] = 666; + q[51] = -3511; + r[51] = -2108; + q[52] = -1454; + r[52] = -3828; + q[53] = 2124; + r[53] = 3502; + q[54] = -3159; + r[54] = 2606; + q[55] = 2384; + r[55] = -3330; + q[56] = -3767; + r[56] = -1607; + q[57] = -4063; + r[57] = -513; + q[58] = 3952; + r[58] = -1075; + q[59] = -3778; + r[59] = -1581; + q[60] = -301; + r[60] = -4084; + q[61] = -4026; + r[61] = 751; + q[62] = -3346; + r[62] = 2361; + q[63] = -2426; + r[63] = 3299; + q[64] = 428; + r[64] = -4073; + q[65] = 3968; + r[65] = 1012; + q[66] = 2900; + r[66] = -2892; + q[67] = -263; + r[67] = 4087; + q[68] = 4083; + r[68] = 322; + q[69] = 2024; + r[69] = 3560; + q[70] = 4015; + r[70] = 808; + q[71] = -3971; + r[71] = -1000; + q[72] = 3785; + r[72] = -1564; + q[73] = -3726; + r[73] = 1701; + q[74] = -3714; + r[74] = 1725; + q[75] = 743; + r[75] = 4027; + q[76] = 875; + r[76] = -4001; + q[77] = 294; + r[77] = 4085; + q[78] = 2611; + r[78] = 3155; + q[79] = 2491; + r[79] = -3251; + q[80] = 1558; + r[80] = 3787; + q[81] = -2063; + r[81] = -3538; + q[82] = 3809; + r[82] = -1505; + q[83] = -2987; + r[83] = 2802; + q[84] = -1955; + r[84] = 3599; + q[85] = 1980; + r[85] = -3585; + q[86] = -539; + r[86] = -4060; + q[87] = -3210; + r[87] = 2543; + q[88] = 2415; + r[88] = -3308; + q[89] = 1587; + r[89] = 3775; + q[90] = -3943; + r[90] = 1106; + q[91] = 3476; + r[91] = 2165; + q[92] = 2253; + r[92] = 3420; + q[93] = -2584; + r[93] = 3177; + q[94] = 3804; + r[94] = -1518; + q[95] = -3637; + r[95] = 1883; + q[96] = 3289; + r[96] = -2440; + q[97] = -1621; + r[97] = 3761; + q[98] = 1645; + r[98] = 3751; + q[99] = -3471; + r[99] = 2173; + q[100] = 4071; + r[100] = -449; + q[101] = -872; + r[101] = -4001; + q[102] = -3897; + r[102] = 1259; + q[103] = -3590; + r[103] = 1970; + q[104] = -2456; + r[104] = -3277; + q[105] = -3004; + r[105] = 2783; + q[106] = 2589; + r[106] = 3173; + q[107] = 3727; + r[107] = -1698; + q[108] = 2992; + r[108] = 2796; + q[109] = 794; + r[109] = -4018; + q[110] = -918; + r[110] = 3991; + q[111] = 1446; + r[111] = -3831; + q[112] = 3871; + r[112] = -1338; + q[113] = -612; + r[113] = -4049; + q[114] = -1566; + r[114] = -3784; + q[115] = 672; + r[115] = -4040; + q[116] = 3841; + r[116] = 1422; + q[117] = 3545; + r[117] = -2051; + q[118] = -1982; + r[118] = -3584; + q[119] = -3413; + r[119] = 2263; + q[120] = -3265; + r[120] = -2473; + q[121] = -2876; + r[121] = -2915; + q[122] = 4094; + r[122] = -117; + q[123] = -269; + r[123] = 4087; + q[124] = -4077; + r[124] = 391; + q[125] = -3759; + r[125] = 1626; + q[126] = 1639; + r[126] = 3753; + q[127] = 3041; + r[127] = -2743; + q[128] = 5; + r[128] = 4095; + q[129] = 2778; + r[129] = -3009; + q[130] = 1121; + r[130] = -3939; + q[131] = -455; + r[131] = -4070; + q[132] = 3532; + r[132] = 2073; + q[133] = -143; + r[133] = -4093; + q[134] = -2357; + r[134] = -3349; + q[135] = 458; + r[135] = 4070; + q[136] = -2887; + r[136] = -2904; + q[137] = -1104; + r[137] = 3944; + q[138] = -2104; + r[138] = -3513; + q[139] = 126; + r[139] = 4094; + q[140] = -3655; + r[140] = -1848; + q[141] = -3896; + r[141] = 1263; + q[142] = -3874; + r[142] = -1327; + q[143] = 4058; + r[143] = 553; + q[144] = -1831; + r[144] = -3663; + q[145] = -255; + r[145] = -4088; + q[146] = -1211; + r[146] = 3912; + q[147] = 445; + r[147] = 4071; + q[148] = 2268; + r[148] = 3410; + q[149] = -4010; + r[149] = 833; + q[150] = 2621; + r[150] = 3147; + q[151] = -250; + r[151] = 4088; + q[152] = -3409; + r[152] = -2269; + q[153] = -2710; + r[153] = -3070; + q[154] = 4063; + r[154] = 518; + q[155] = -3611; + r[155] = -1933; + q[156] = -3707; + r[156] = -1741; + q[157] = -1151; + r[157] = -3930; + q[158] = 3976; + r[158] = -983; + q[159] = -1736; + r[159] = 3709; + q[160] = 3669; + r[160] = 1820; + q[161] = -143; + r[161] = 4093; + q[162] = -3879; + r[162] = -1313; + q[163] = -2242; + r[163] = -3427; + q[164] = -4095; + r[164] = 0; + q[165] = -1159; + r[165] = -3928; + q[166] = -3155; + r[166] = 2611; + q[167] = -2887; + r[167] = -2904; + q[168] = -4095; + r[168] = 56; + q[169] = -3861; + r[169] = -1364; + q[170] = -2814; + r[170] = 2976; + q[171] = -3680; + r[171] = -1798; + q[172] = -4094; + r[172] = -107; + q[173] = -3626; + r[173] = 1903; + q[174] = 3403; + r[174] = 2278; + q[175] = -1735; + r[175] = -3710; + q[176] = -2126; + r[176] = -3500; + q[177] = 3183; + r[177] = -2577; + q[178] = -3499; + r[178] = 2128; + q[179] = -1736; + r[179] = 3709; + q[180] = 2592; + r[180] = -3170; + q[181] = 3875; + r[181] = 1326; + q[182] = 3596; + r[182] = 1960; + q[183] = 3915; + r[183] = -1202; + q[184] = 1570; + r[184] = 3783; + q[185] = -3319; + r[185] = -2400; + q[186] = 4019; + r[186] = 787; + q[187] = -187; + r[187] = 4091; + q[188] = 1370; + r[188] = -3859; + q[189] = -4091; + r[189] = 199; + q[190] = 3626; + r[190] = 1904; + q[191] = -2943; + r[191] = 2848; + q[192] = 56; + r[192] = 4095; + q[193] = 2824; + r[193] = 2966; + q[194] = -3994; + r[194] = -904; + q[195] = 56; + r[195] = 4095; + q[196] = -2045; + r[196] = 3548; + q[197] = -3653; + r[197] = 1850; + q[198] = -2864; + r[198] = 2927; + q[199] = -1996; + r[199] = 3576; + q[200] = -4061; + r[200] = 527; + q[201] = 159; + r[201] = 4092; + q[202] = -3363; + r[202] = 2336; + q[203] = -4074; + r[203] = 421; + q[204] = 2043; + r[204] = 3549; + q[205] = 4095; + r[205] = -70; + q[206] = -2107; + r[206] = -3512; + q[207] = -1973; + r[207] = 3589; + q[208] = -3138; + r[208] = 2631; + q[209] = -3625; + r[209] = -1905; + q[210] = 2413; + r[210] = 3309; + q[211] = -50; + r[211] = -4095; + q[212] = 2813; + r[212] = 2976; + q[213] = -535; + r[213] = -4060; + q[214] = 1250; + r[214] = 3900; + q[215] = 1670; + r[215] = -3739; + q[216] = 1945; + r[216] = -3604; + q[217] = -476; + r[217] = -4068; + q[218] = -3659; + r[218] = -1840; + q[219] = 2745; + r[219] = 3039; + q[220] = -674; + r[220] = -4040; + q[221] = 2383; + r[221] = 3330; + q[222] = 4086; + r[222] = 274; + q[223] = -4030; + r[223] = 730; + q[224] = 768; + r[224] = -4023; + q[225] = 3925; + r[225] = 1170; + q[226] = 785; + r[226] = 4019; + q[227] = -3101; + r[227] = -2675; + q[228] = 4030; + r[228] = -729; + q[229] = 3422; + r[229] = 2249; + q[230] = -3847; + r[230] = 1403; + q[231] = 3902; + r[231] = -1243; + q[232] = 2114; + r[232] = -3507; + q[233] = -2359; + r[233] = 3348; + q[234] = 3754; + r[234] = -1638; + q[235] = -4095; + r[235] = -83; + q[236] = 2301; + r[236] = -3388; + q[237] = 3336; + r[237] = 2375; + q[238] = -2045; + r[238] = 3548; + q[239] = -413; + r[239] = -4075; + q[240] = 1848; + r[240] = 3655; + q[241] = 4072; + r[241] = -437; + q[242] = 4069; + r[242] = -463; + q[243] = 1386; + r[243] = -3854; + q[244] = 966; + r[244] = 3980; + q[245] = -1684; + r[245] = -3733; + q[246] = 2953; + r[246] = 2837; + q[247] = -3961; + r[247] = -1040; + q[248] = 3512; + r[248] = -2107; + q[249] = 1363; + r[249] = 3862; + q[250] = 1883; + r[250] = 3637; + q[251] = 2657; + r[251] = 3116; + q[252] = 2347; + r[252] = -3356; + q[253] = -1635; + r[253] = -3755; + q[254] = 3170; + r[254] = 2593; + q[255] = 2856; + r[255] = 2935; + q[256] = 494; + r[256] = 4066; + q[257] = 1936; + r[257] = -3609; + q[258] = 245; + r[258] = 4088; + q[259] = -1211; + r[259] = -3912; + q[260] = -3600; + r[260] = 1952; + q[261] = 1632; + r[261] = 3756; + q[262] = 2341; + r[262] = 3360; + q[263] = 186; + r[263] = -4091; + q[264] = 4011; + r[264] = 829; + q[265] = -3490; + r[265] = -2143; + q[266] = 269; + r[266] = -4087; + q[267] = -2939; + r[267] = 2852; + q[268] = 1600; + r[268] = 3770; + q[269] = -3405; + r[269] = -2275; + q[270] = -3134; + r[270] = -2636; + q[271] = 2642; + r[271] = -3129; + q[272] = 3629; + r[272] = 1898; + q[273] = 3413; + r[273] = 2264; + q[274] = 2050; + r[274] = 3545; + q[275] = 988; + r[275] = -3975; + q[276] = -660; + r[276] = 4042; + q[277] = 978; + r[277] = -3977; + q[278] = 1965; + r[278] = -3593; + q[279] = -1513; + r[279] = -3806; + q[280] = -4076; + r[280] = 401; + q[281] = -4094; + r[281] = -92; + q[282] = -1914; + r[282] = 3621; + q[283] = 2006; + r[283] = -3570; + q[284] = -1550; + r[284] = -3791; + q[285] = 3774; + r[285] = -1591; + q[286] = -3958; + r[286] = 1052; + q[287] = -3576; + r[287] = 1997; + q[288] = -382; + r[288] = 4078; + q[289] = 1288; + r[289] = 3888; + q[290] = -2965; + r[290] = -2825; + q[291] = 1608; + r[291] = 3767; + q[292] = 3052; + r[292] = -2731; + q[293] = -622; + r[293] = 4048; + q[294] = -3836; + r[294] = 1434; + q[295] = -3542; + r[295] = 2056; + q[296] = -2648; + r[296] = 3124; + q[297] = -1178; + r[297] = -3922; + q[298] = -1109; + r[298] = 3942; + q[299] = 3910; + r[299] = 1217; + q[300] = 1199; + r[300] = -3916; + q[301] = -3386; + r[301] = 2303; + q[302] = -3453; + r[302] = 2202; + q[303] = -2877; + r[303] = 2914; + q[304] = 4095; + r[304] = -47; + q[305] = 3635; + r[305] = 1886; + q[306] = -2134; + r[306] = -3495; + q[307] = 613; + r[307] = -4049; + q[308] = -2700; + r[308] = 3079; + q[309] = 4091; + r[309] = -195; + q[310] = 3989; + r[310] = -927; + q[311] = -2385; + r[311] = 3329; + q[312] = 4094; + r[312] = -103; + q[313] = 1044; + r[313] = -3960; + q[314] = -1734; + r[314] = -3710; + q[315] = 1646; + r[315] = 3750; + q[316] = 575; + r[316] = 4055; + q[317] = -2629; + r[317] = -3140; + q[318] = 3266; + r[318] = 2471; + q[319] = 4091; + r[319] = -194; + q[320] = -2154; + r[320] = 3483; + q[321] = 659; + r[321] = 4042; + q[322] = -1785; + r[322] = -3686; + q[323] = -717; + r[323] = -4032; + q[324] = 4095; + r[324] = -37; + q[325] = -2963; + r[325] = -2827; + q[326] = -2645; + r[326] = -3126; + q[327] = 2619; + r[327] = -3148; + q[328] = 1855; + r[328] = -3651; + q[329] = -3726; + r[329] = 1699; + q[330] = -3437; + r[330] = 2227; + q[331] = 2948; + r[331] = 2842; + q[332] = -2125; + r[332] = 3501; + q[333] = -1700; + r[333] = 3726; + q[334] = 4094; + r[334] = -101; + q[335] = 2084; + r[335] = -3525; + q[336] = 3225; + r[336] = -2524; + q[337] = 2220; + r[337] = 3442; + q[338] = 3174; + r[338] = 2588; + q[339] = 229; + r[339] = -4089; + q[340] = -2381; + r[340] = -3332; + q[341] = -3677; + r[341] = -1803; + q[342] = -3191; + r[342] = -2567; + q[343] = 2465; + r[343] = 3270; + q[344] = 2681; + r[344] = -3096; + q[345] = 975; + r[345] = -3978; + q[346] = 2004; + r[346] = -3572; + q[347] = -3442; + r[347] = -2219; + q[348] = 3676; + r[348] = -1805; + q[349] = -3753; + r[349] = 1638; + q[350] = 3544; + r[350] = 2053; + q[351] = 397; + r[351] = -4076; + q[352] = 2221; + r[352] = 3440; + q[353] = -302; + r[353] = 4084; + q[354] = 4083; + r[354] = -323; + q[355] = -2253; + r[355] = -3420; + q[356] = -3038; + r[356] = 2746; + q[357] = 2884; + r[357] = 2908; + q[358] = 4070; + r[358] = 454; + q[359] = -1072; + r[359] = -3953; + q[360] = 3831; + r[360] = 1449; + q[361] = 3663; + r[361] = -1831; + q[362] = -1971; + r[362] = 3590; + q[363] = 3226; + r[363] = -2522; + q[364] = -145; + r[364] = -4093; + q[365] = 1882; + r[365] = -3637; + q[366] = 529; + r[366] = 4061; + q[367] = 2637; + r[367] = 3133; + q[368] = -4077; + r[368] = 389; + q[369] = 2156; + r[369] = -3482; + q[370] = -3276; + r[370] = 2458; + q[371] = -2687; + r[371] = -3090; + q[372] = 3469; + r[372] = -2177; + q[373] = -4093; + r[373] = -139; + q[374] = -850; + r[374] = 4006; + q[375] = -625; + r[375] = 4048; + q[376] = 1110; + r[376] = -3942; + q[377] = -3078; + r[377] = -2702; + q[378] = -2719; + r[378] = 3063; + q[379] = 742; + r[379] = 4028; + q[380] = -3902; + r[380] = -1245; + q[381] = 3888; + r[381] = -1287; + q[382] = -4081; + r[382] = 347; + q[383] = 1070; + r[383] = 3953; + q[384] = -996; + r[384] = -3972; + q[385] = 4041; + r[385] = -668; + q[386] = -2712; + r[386] = 3069; + q[387] = -3403; + r[387] = -2279; + q[388] = -3320; + r[388] = -2398; + q[389] = 3036; + r[389] = -2749; + q[390] = 1308; + r[390] = -3881; + q[391] = 2256; + r[391] = 3418; + q[392] = -1486; + r[392] = 3816; + q[393] = -2771; + r[393] = -3015; + q[394] = -3883; + r[394] = -1302; + q[395] = -3867; + r[395] = -1349; + q[396] = 3952; + r[396] = -1075; + q[397] = -789; + r[397] = 4019; + q[398] = 1458; + r[398] = 3827; + q[399] = 3832; + r[399] = -1446; + q[400] = -3001; + r[400] = -2787; + q[401] = 3463; + r[401] = 2186; + q[402] = 3606; + r[402] = 1942; + q[403] = 4023; + r[403] = 764; + q[404] = 3387; + r[404] = 2303; + q[405] = 2648; + r[405] = -3124; + q[406] = 1370; + r[406] = -3860; + q[407] = -3134; + r[407] = 2636; + q[408] = 4051; + r[408] = -600; + q[409] = -1977; + r[409] = -3587; + q[410] = 3160; + r[410] = 2605; + q[411] = 4042; + r[411] = 659; + q[412] = 3004; + r[412] = 2783; + q[413] = 3370; + r[413] = 2327; + q[414] = -419; + r[414] = -4074; + q[415] = -1968; + r[415] = 3591; + q[416] = -3705; + r[416] = -1746; + q[417] = -3331; + r[417] = -2383; + q[418] = -3634; + r[418] = 1888; + q[419] = -1981; + r[419] = -3584; + q[420] = 4069; + r[420] = -469; + q[421] = -628; + r[421] = -4047; + q[422] = -1900; + r[422] = 3628; + q[423] = 1039; + r[423] = -3961; + q[424] = 2554; + r[424] = -3201; + q[425] = -2955; + r[425] = 2836; + q[426] = 2286; + r[426] = -3398; + q[427] = -1624; + r[427] = 3760; + q[428] = 2213; + r[428] = 3446; + q[429] = -3989; + r[429] = -926; + q[430] = 192; + r[430] = -4091; + q[431] = -723; + r[431] = 4031; + q[432] = 2878; + r[432] = 2913; + q[433] = -2109; + r[433] = 3511; + q[434] = 1463; + r[434] = -3825; + q[435] = -741; + r[435] = -4028; + q[436] = -1314; + r[436] = -3879; + q[437] = 3115; + r[437] = 2659; + q[438] = -3160; + r[438] = -2605; + q[439] = 1868; + r[439] = 3644; + q[440] = -824; + r[440] = 4012; + q[441] = 781; + r[441] = 4020; + q[442] = -1257; + r[442] = -3898; + q[443] = 3331; + r[443] = -2382; + q[444] = 1642; + r[444] = -3752; + q[445] = 3748; + r[445] = -1650; + q[446] = -487; + r[446] = -4066; + q[447] = 3085; + r[447] = -2694; + q[448] = 4009; + r[448] = 839; + q[449] = -2308; + r[449] = -3383; + q[450] = 3850; + r[450] = 1397; + q[451] = -4078; + r[451] = -374; + q[452] = 2989; + r[452] = -2799; + q[453] = 3023; + r[453] = -2762; + q[454] = 1397; + r[454] = -3850; + q[455] = 323; + r[455] = 4083; + q[456] = 268; + r[456] = -4087; + q[457] = 2414; + r[457] = 3308; + q[458] = 3876; + r[458] = 1322; + q[459] = -3584; + r[459] = 1982; + q[460] = 1603; + r[460] = 3769; + q[461] = -1502; + r[461] = 3810; + q[462] = 1318; + r[462] = 3878; + q[463] = 1554; + r[463] = -3789; + q[464] = 2492; + r[464] = 3250; + q[465] = -4093; + r[465] = -154; + q[466] = 4008; + r[466] = 842; + q[467] = -2279; + r[467] = 3403; + q[468] = 3013; + r[468] = 2774; + q[469] = 2557; + r[469] = 3199; + q[470] = 4068; + r[470] = 475; + q[471] = 3324; + r[471] = -2392; + q[472] = 2653; + r[472] = -3120; + q[473] = 796; + r[473] = 4017; + q[474] = -1312; + r[474] = 3880; + q[475] = 1794; + r[475] = 3681; + q[476] = -2347; + r[476] = -3356; + q[477] = -4008; + r[477] = -840; + q[478] = -3773; + r[478] = -1592; + q[479] = 1609; + r[479] = 3766; + q[480] = -1564; + r[480] = -3785; + q[481] = 3004; + r[481] = 2784; + q[482] = 1258; + r[482] = 3897; + q[483] = 3729; + r[483] = 1693; + q[484] = -4095; + r[484] = -28; + q[485] = -4093; + r[485] = -146; + q[486] = 1393; + r[486] = -3851; + q[487] = 297; + r[487] = -4085; + q[488] = 2294; + r[488] = 3393; + q[489] = -2562; + r[489] = 3195; + q[490] = -1716; + r[490] = -3718; + q[491] = 2224; + r[491] = -3439; + q[492] = 2032; + r[492] = 3555; + q[493] = -2968; + r[493] = 2822; + q[494] = 2338; + r[494] = 3363; + q[495] = 1584; + r[495] = -3776; + q[496] = -3072; + r[496] = 2708; + q[497] = -1596; + r[497] = -3771; + q[498] = -2256; + r[498] = -3418; + q[499] = 4095; + r[499] = 89; + q[500] = -1949; + r[500] = 3602; + q[501] = 1844; + r[501] = 3657; + q[502] = -3375; + r[502] = 2319; + q[503] = -1481; + r[503] = -3818; + q[504] = 3228; + r[504] = -2520; + q[505] = 1116; + r[505] = 3940; + q[506] = -2783; + r[506] = 3004; + q[507] = 3915; + r[507] = 1201; + q[508] = 283; + r[508] = 4086; + q[509] = -3732; + r[509] = 1685; + q[510] = -433; + r[510] = -4072; + q[511] = -3667; + r[511] = 1823; + q[512] = 3883; + r[512] = 1300; + q[513] = -3742; + r[513] = 1663; + q[514] = 4093; + r[514] = -143; + q[515] = 3874; + r[515] = 1328; + q[516] = -3800; + r[516] = 1528; + q[517] = -1257; + r[517] = 3898; + q[518] = -1606; + r[518] = 3767; + q[519] = 3394; + r[519] = 2291; + q[520] = 2255; + r[520] = 3419; + q[521] = -4094; + r[521] = 120; + q[522] = -3767; + r[522] = 1606; + q[523] = 1849; + r[523] = -3654; + q[524] = -2883; + r[524] = 2908; + q[525] = 3469; + r[525] = 2176; + q[526] = 2654; + r[526] = 3119; + q[527] = -239; + r[527] = 4088; + q[528] = -651; + r[528] = 4043; + q[529] = -1140; + r[529] = 3934; + q[530] = 328; + r[530] = -4082; + q[531] = 3246; + r[531] = 2497; + q[532] = 4026; + r[532] = -753; + q[533] = -2041; + r[533] = -3550; + q[534] = -1154; + r[534] = 3929; + q[535] = -2710; + r[535] = 3070; + q[536] = -2860; + r[536] = 2932; + q[537] = 2097; + r[537] = 3517; + q[538] = 3492; + r[538] = -2140; + q[539] = 3123; + r[539] = 2649; + q[540] = 3360; + r[540] = 2342; + q[541] = 2498; + r[541] = 3245; + q[542] = 3976; + r[542] = 982; + q[543] = -2441; + r[543] = -3288; + q[544] = 3601; + r[544] = 1951; + q[545] = -4008; + r[545] = -842; + q[546] = 1243; + r[546] = 3902; + q[547] = 4069; + r[547] = 466; + q[548] = -2031; + r[548] = 3556; + q[549] = 4077; + r[549] = 386; + q[550] = -3112; + r[550] = -2663; + q[551] = 4087; + r[551] = -262; + q[552] = 4087; + r[552] = 266; + q[553] = -3907; + r[553] = -1228; + q[554] = -1611; + r[554] = 3765; + q[555] = 3066; + r[555] = -2715; + q[556] = 2657; + r[556] = 3117; + q[557] = 3912; + r[557] = -1213; + q[558] = -2531; + r[558] = -3220; + q[559] = 3500; + r[559] = -2127; + q[560] = -76; + r[560] = -4095; + q[561] = 3413; + r[561] = -2264; + q[562] = -4071; + r[562] = -448; + q[563] = 828; + r[563] = 4011; + q[564] = 3664; + r[564] = 1830; + q[565] = -1578; + r[565] = 3779; + q[566] = 3555; + r[566] = 2033; + q[567] = 3868; + r[567] = -1345; + q[568] = 4054; + r[568] = -580; + q[569] = -4094; + r[569] = 124; + q[570] = -3820; + r[570] = -1477; + q[571] = -3658; + r[571] = -1842; + q[572] = 2595; + r[572] = 3168; + q[573] = 3354; + r[573] = 2350; + q[574] = -701; + r[574] = -4035; + q[575] = -772; + r[575] = -4022; + q[576] = 2799; + r[576] = 2990; + q[577] = -3632; + r[577] = 1893; + q[578] = 310; + r[578] = 4084; + q[579] = 3984; + r[579] = -947; + q[580] = 3794; + r[580] = -1542; + q[581] = -2419; + r[581] = 3304; + q[582] = -3916; + r[582] = 1200; + q[583] = -3886; + r[583] = 1292; + q[584] = -3299; + r[584] = 2426; + q[585] = -437; + r[585] = 4072; + q[586] = 2053; + r[586] = -3544; + q[587] = 3987; + r[587] = 937; + q[588] = -789; + r[588] = -4019; + q[589] = 4055; + r[589] = -575; + q[590] = -3894; + r[590] = 1270; + q[591] = 4003; + r[591] = -864; + q[592] = -3060; + r[592] = 2721; + q[593] = -4009; + r[593] = 836; + q[594] = -1655; + r[594] = -3746; + q[595] = 3954; + r[595] = -1067; + q[596] = -773; + r[596] = 4022; + q[597] = -422; + r[597] = 4074; + q[598] = -3384; + r[598] = 2306; + q[599] = 195; + r[599] = -4091; + q[600] = -298; + r[600] = 4085; + q[601] = -3988; + r[601] = 931; + q[602] = 2014; + r[602] = -3566; + q[603] = 3349; + r[603] = -2357; + q[604] = 3800; + r[604] = 1526; + q[605] = 3858; + r[605] = 1374; + q[606] = 2947; + r[606] = 2844; + q[607] = -1483; + r[607] = -3818; + q[608] = 4056; + r[608] = -565; + q[609] = 2612; + r[609] = -3154; + q[610] = 2326; + r[610] = 3371; + q[611] = -3545; + r[611] = 2051; + q[612] = -1001; + r[612] = -3971; + q[613] = 3211; + r[613] = 2541; + q[614] = -2717; + r[614] = 3065; + q[615] = -3159; + r[615] = -2606; + q[616] = 2869; + r[616] = -2922; + q[617] = -1290; + r[617] = -3887; + q[618] = 2479; + r[618] = 3260; + q[619] = 3420; + r[619] = 2252; + q[620] = 1823; + r[620] = 3667; + q[621] = 3368; + r[621] = 2330; + q[622] = -3819; + r[622] = -1480; + q[623] = 3800; + r[623] = 1528; + q[624] = 3773; + r[624] = 1594; + q[625] = -189; + r[625] = -4091; + q[626] = -4067; + r[626] = -485; + q[627] = 2277; + r[627] = -3404; + q[628] = -4089; + r[628] = -233; + q[629] = -3634; + r[629] = 1889; + q[630] = 3292; + r[630] = 2437; + q[631] = -530; + r[631] = 4061; + q[632] = -3109; + r[632] = 2666; + q[633] = -3741; + r[633] = 1667; + q[634] = -1903; + r[634] = -3626; + q[635] = 3879; + r[635] = -1315; + q[636] = 4083; + r[636] = -315; + q[637] = -1148; + r[637] = 3931; + q[638] = 2630; + r[638] = 3139; + q[639] = -4001; + r[639] = 876; + q[640] = -2295; + r[640] = -3392; + q[641] = 1090; + r[641] = -3948; + q[642] = -3024; + r[642] = 2762; + q[643] = 2728; + r[643] = -3054; + q[644] = -3305; + r[644] = 2419; + q[645] = 60; + r[645] = 4095; + q[646] = 4048; + r[646] = -620; + q[647] = 589; + r[647] = -4053; + q[648] = -3867; + r[648] = 1347; + q[649] = -2944; + r[649] = -2847; + q[650] = -2721; + r[650] = 3060; + q[651] = 2928; + r[651] = 2863; + q[652] = 801; + r[652] = 4016; + q[653] = -3644; + r[653] = 1870; + q[654] = -1648; + r[654] = -3749; + q[655] = 825; + r[655] = -4012; + q[656] = -2036; + r[656] = -3553; + q[657] = -1192; + r[657] = -3918; + q[658] = 2875; + r[658] = 2916; + q[659] = -1831; + r[659] = -3663; + q[660] = -2865; + r[660] = -2926; + q[661] = -575; + r[661] = -4055; + q[662] = -3870; + r[662] = 1340; + q[663] = -4080; + r[663] = -356; + q[664] = -2176; + r[664] = -3469; + q[665] = -2986; + r[665] = -2803; + q[666] = 3978; + r[666] = -972; + q[667] = 2437; + r[667] = 3291; + q[668] = -3528; + r[668] = 2080; + q[669] = -3300; + r[669] = -2425; + q[670] = 3085; + r[670] = 2693; + q[671] = -3700; + r[671] = -1756; + q[672] = 3216; + r[672] = -2535; + q[673] = 4094; + r[673] = -91; + q[674] = 3775; + r[674] = -1589; + q[675] = 1097; + r[675] = -3946; + q[676] = -152; + r[676] = -4093; + q[677] = -3490; + r[677] = 2142; + q[678] = 3747; + r[678] = 1654; + q[679] = -1490; + r[679] = -3815; + q[680] = -3998; + r[680] = -886; + q[681] = 3726; + r[681] = -1700; + q[682] = -1600; + r[682] = 3770; + q[683] = -87; + r[683] = 4095; + q[684] = 2538; + r[684] = -3214; + q[685] = -4095; + r[685] = 52; + q[686] = -3993; + r[686] = -910; + q[687] = 4051; + r[687] = 603; + q[688] = -1242; + r[688] = -3902; + q[689] = 2155; + r[689] = 3482; + q[690] = 1270; + r[690] = 3893; + q[691] = 1919; + r[691] = -3618; + q[692] = -3145; + r[692] = 2623; + q[693] = 2475; + r[693] = 3263; + q[694] = 2226; + r[694] = -3437; + q[695] = -3894; + r[695] = -1269; + q[696] = -429; + r[696] = 4073; + q[697] = -1346; + r[697] = 3868; + q[698] = 1297; + r[698] = 3885; + q[699] = 1699; + r[699] = 3726; + q[700] = -3375; + r[700] = 2319; + q[701] = 1577; + r[701] = -3779; + q[702] = -63; + r[702] = 4095; + q[703] = 1215; + r[703] = -3911; + q[704] = -1492; + r[704] = 3814; + q[705] = -1530; + r[705] = -3799; + q[706] = 3442; + r[706] = 2218; + q[707] = -3867; + r[707] = -1349; + q[708] = -3291; + r[708] = -2437; + q[709] = -2253; + r[709] = -3420; + q[710] = -150; + r[710] = -4093; + q[711] = -2686; + r[711] = -3092; + q[712] = 3470; + r[712] = 2175; + q[713] = -3826; + r[713] = -1461; + q[714] = -3148; + r[714] = 2619; + q[715] = -3858; + r[715] = 1375; + q[716] = -3844; + r[716] = -1412; + q[717] = -3652; + r[717] = 1854; + q[718] = 4018; + r[718] = -791; + q[719] = 179; + r[719] = -4092; + q[720] = 3498; + r[720] = 2129; + q[721] = -1999; + r[721] = -3574; + q[722] = 3531; + r[722] = 2075; + q[723] = 4050; + r[723] = -606; + q[724] = -1639; + r[724] = 3753; + q[725] = -3661; + r[725] = 1835; + q[726] = 4039; + r[726] = 679; + q[727] = 3561; + r[727] = 2023; + q[728] = 528; + r[728] = 4061; + q[729] = -634; + r[729] = -4046; + q[730] = 364; + r[730] = -4079; + q[731] = 2735; + r[731] = 3048; + q[732] = 3978; + r[732] = 973; + q[733] = -4073; + r[733] = -427; + q[734] = -3722; + r[734] = 1708; + q[735] = 2356; + r[735] = -3350; + q[736] = -1125; + r[736] = -3938; + q[737] = 4054; + r[737] = 580; + q[738] = 3328; + r[738] = -2387; + q[739] = 1439; + r[739] = -3834; + q[740] = 1746; + r[740] = 3705; + q[741] = 2507; + r[741] = 3238; + q[742] = 3839; + r[742] = -1427; + q[743] = 488; + r[743] = -4066; + q[744] = 1187; + r[744] = 3920; + q[745] = 2038; + r[745] = -3552; + q[746] = -905; + r[746] = -3994; + q[747] = -236; + r[747] = 4089; + q[748] = 208; + r[748] = -4090; + q[749] = 1660; + r[749] = 3744; + q[750] = -4074; + r[750] = -415; + q[751] = -2304; + r[751] = 3385; + q[752] = -2457; + r[752] = 3276; + q[753] = 3302; + r[753] = 2423; + q[754] = 1778; + r[754] = -3689; + q[755] = 2019; + r[755] = 3563; + q[756] = 4037; + r[756] = 687; + q[757] = -2365; + r[757] = 3343; + q[758] = 5; + r[758] = -4095; + q[759] = 160; + r[759] = -4092; + +} /*initRand*/ + +/** + * initializes the MEL-2_LINEAR LOOKUP TABLE + * @param sig_inObj : sig PU internal object of the sub-object + * @return void + * @remarks translated from matlab code to c-code + * @callgraph + * @callergraph + * + * input + * - bilinTab : base address of bilinTable destination vector + * - alpha : warping factor + * - size : size of the vectors to be generated + * - A,B : base address of array of indexes for lookup table implementation + * - D : base address of delta array for lookup table implementation + * + * output + * - bilinTab, A, B, D : initialized vectors + */ +void mel_2_lin_init(sig_innerobj_t *sig_inObj) +{ + + /*Declare variables tied to I/O PARAMS formerly passed by value or reference*/ + picoos_single alpha; + picoos_int32 *D; + picoos_int32 size; + picoos_int16 *A; + + /*Link local variables with sig data object*/ + + alpha = sig_inObj->warp_p; + size = (sig_inObj->hfftsize_p) + 1; + A = sig_inObj->A_p; + D = sig_inObj->d_p; + /* + fixed point interpolation tables + scaling factor: 0x20 + corresponding bit shift: 5 + */ + + A[0] = 0; + D[0] = 0; + A[1] = 2; + D[1] = 14; + A[2] = 4; + D[2] = 29; + A[3] = 7; + D[3] = 11; + A[4] = 9; + D[4] = 24; + A[5] = 12; + D[5] = 5; + A[6] = 14; + D[6] = 18; + A[7] = 16; + D[7] = 30; + A[8] = 19; + D[8] = 9; + A[9] = 21; + D[9] = 19; + A[10] = 23; + D[10] = 29; + A[11] = 26; + D[11] = 5; + A[12] = 28; + D[12] = 12; + A[13] = 30; + D[13] = 19; + A[14] = 32; + D[14] = 24; + A[15] = 34; + D[15] = 27; + A[16] = 36; + D[16] = 30; + A[17] = 38; + D[17] = 31; + A[18] = 40; + D[18] = 31; + A[19] = 42; + D[19] = 29; + A[20] = 44; + D[20] = 26; + A[21] = 46; + D[21] = 22; + A[22] = 48; + D[22] = 17; + A[23] = 50; + D[23] = 10; + A[24] = 52; + D[24] = 2; + A[25] = 53; + D[25] = 24; + A[26] = 55; + D[26] = 13; + A[27] = 57; + D[27] = 1; + A[28] = 58; + D[28] = 20; + A[29] = 60; + D[29] = 5; + A[30] = 61; + D[30] = 21; + A[31] = 63; + D[31] = 4; + A[32] = 64; + D[32] = 18; + A[33] = 65; + D[33] = 31; + A[34] = 67; + D[34] = 11; + A[35] = 68; + D[35] = 21; + A[36] = 69; + D[36] = 31; + A[37] = 71; + D[37] = 7; + A[38] = 72; + D[38] = 14; + A[39] = 73; + D[39] = 21; + A[40] = 74; + D[40] = 27; + A[41] = 75; + D[41] = 31; + A[42] = 77; + D[42] = 3; + A[43] = 78; + D[43] = 6; + A[44] = 79; + D[44] = 8; + A[45] = 80; + D[45] = 10; + A[46] = 81; + D[46] = 10; + A[47] = 82; + D[47] = 10; + A[48] = 83; + D[48] = 9; + A[49] = 84; + D[49] = 8; + A[50] = 85; + D[50] = 6; + A[51] = 86; + D[51] = 3; + A[52] = 86; + D[52] = 31; + A[53] = 87; + D[53] = 27; + A[54] = 88; + D[54] = 23; + A[55] = 89; + D[55] = 18; + A[56] = 90; + D[56] = 12; + A[57] = 91; + D[57] = 6; + A[58] = 91; + D[58] = 31; + A[59] = 92; + D[59] = 24; + A[60] = 93; + D[60] = 16; + A[61] = 94; + D[61] = 8; + A[62] = 94; + D[62] = 31; + A[63] = 95; + D[63] = 22; + A[64] = 96; + D[64] = 13; + A[65] = 97; + D[65] = 3; + A[66] = 97; + D[66] = 25; + A[67] = 98; + D[67] = 14; + A[68] = 99; + D[68] = 3; + A[69] = 99; + D[69] = 24; + A[70] = 100; + D[70] = 13; + A[71] = 101; + D[71] = 1; + A[72] = 101; + D[72] = 21; + A[73] = 102; + D[73] = 8; + A[74] = 102; + D[74] = 27; + A[75] = 103; + D[75] = 14; + A[76] = 104; + D[76] = 1; + A[77] = 104; + D[77] = 19; + A[78] = 105; + D[78] = 6; + A[79] = 105; + D[79] = 24; + A[80] = 106; + D[80] = 9; + A[81] = 106; + D[81] = 27; + A[82] = 107; + D[82] = 12; + A[83] = 107; + D[83] = 29; + A[84] = 108; + D[84] = 14; + A[85] = 108; + D[85] = 31; + A[86] = 109; + D[86] = 15; + A[87] = 109; + D[87] = 31; + A[88] = 110; + D[88] = 16; + A[89] = 110; + D[89] = 31; + A[90] = 111; + D[90] = 15; + A[91] = 111; + D[91] = 31; + A[92] = 112; + D[92] = 14; + A[93] = 112; + D[93] = 30; + A[94] = 113; + D[94] = 13; + A[95] = 113; + D[95] = 28; + A[96] = 114; + D[96] = 11; + A[97] = 114; + D[97] = 26; + A[98] = 115; + D[98] = 9; + A[99] = 115; + D[99] = 23; + A[100] = 116; + D[100] = 6; + A[101] = 116; + D[101] = 20; + A[102] = 117; + D[102] = 2; + A[103] = 117; + D[103] = 16; + A[104] = 117; + D[104] = 31; + A[105] = 118; + D[105] = 13; + A[106] = 118; + D[106] = 27; + A[107] = 119; + D[107] = 8; + A[108] = 119; + D[108] = 22; + A[109] = 120; + D[109] = 4; + A[110] = 120; + D[110] = 17; + A[111] = 120; + D[111] = 31; + A[112] = 121; + D[112] = 13; + A[113] = 121; + D[113] = 26; + A[114] = 122; + D[114] = 8; + A[115] = 122; + D[115] = 21; + A[116] = 123; + D[116] = 2; + A[117] = 123; + D[117] = 15; + A[118] = 123; + D[118] = 29; + A[119] = 124; + D[119] = 10; + A[120] = 124; + D[120] = 23; + A[121] = 125; + D[121] = 4; + A[122] = 125; + D[122] = 17; + A[123] = 125; + D[123] = 31; + A[124] = 126; + D[124] = 12; + A[125] = 126; + D[125] = 25; + A[126] = 127; + D[126] = 6; + A[127] = 127; + D[127] = 19; + A[128] = 128; + D[128] = 0; + +}/*mel_2_lin_init*/ + +/** + * function to be documented + * @param ang : ?? + * @param table : ?? + * @param cs : ?? + * @param sn : ?? + * @return void + * @callgraph + * @callergraph + */ +static void get_trig(picoos_int32 ang, picoos_int32 *table, picoos_int32 *cs, + picoos_int32 *sn) +{ + picoos_int32 i, j, k; + + i = k = ang >> PICODSP_PI_SHIFT; /* * PICODSP_COS_TABLE_LEN2/PICODSP_FIX_SCALE2 */ + if (i < 0) + i = -i; + j = 1; + i &= (PICODSP_COS_TABLE_LEN4 - 1); + if (i > PICODSP_COS_TABLE_LEN2) + i = PICODSP_COS_TABLE_LEN4 - i; + if (i > PICODSP_COS_TABLE_LEN) { + j = -1; + i = PICODSP_COS_TABLE_LEN2 - i; + } + if (j == 1) + *cs = table[i]; + else + *cs = -table[i]; + + i = k - PICODSP_COS_TABLE_LEN; + if (i < 0) + i = -i; + j = 1; + i &= (PICODSP_COS_TABLE_LEN4 - 1); + if (i > PICODSP_COS_TABLE_LEN2) + i = PICODSP_COS_TABLE_LEN4 - i; + if (i > PICODSP_COS_TABLE_LEN) { + j = -1; + i = PICODSP_COS_TABLE_LEN2 - i; + } + if (j == 1) + *sn = table[i]; + else + *sn = -table[i]; +}/*get_trig*/ + +/** + * function to be documented + * @param sig_inObj : sig PU internal object of the sub-object + * @return void + * @callgraph + * @callergraph + */ +void save_transition_frame(sig_innerobj_t *sig_inObj) +{ + picoos_int32 *tmp, *tmp2; /*for loop unrolling*/ + + if (sig_inObj->voiced_p != sig_inObj->prevVoiced_p) { + sig_inObj->VoicTrans = sig_inObj->prevVoiced_p; /*remember last voicing transition*/ + tmp = sig_inObj->ImpResp_p; + tmp2 = sig_inObj->imp_p; + FAST_DEVICE(PICODSP_FFTSIZE,*(tmp++)=*(tmp2++);); + if (sig_inObj->voiced_p == 1) + sig_inObj->nV = 0; + else + sig_inObj->nU = 0; /*to avoid problems in case of very short voiced or unvoiced parts (less than 4 frames long)*/ + } +}/*save_transition_frame*/ + +/** + * calculates an unweighted excitation window + * @param sig_inObj : sig PU internal object of the sub-object + * @param nextPeak : position of next peak (excitation position) + * @return PICO_OK + * @callgraph + * @callergraph + * input + * - hop : hop size in samples + * - winlen : excitation window length + * - E : energy + * - F0 : pitch + * - nextPeak : state that remembers next excitation index + * - Fs - sampling frequency + * output + * - LocV, LocU : (MAX_EN size) location of excitation points + * - EnV, EnU : (MAX_EN size) RMS values of excitation (scaled) + * - nV, nU : (integers) number of excitation points + * - nextPeak new position of lastPeak to calculate next frame + */ +static void get_simple_excitation(sig_innerobj_t *sig_inObj, + picoos_int16 *nextPeak) +{ + /*Define local variables*/ + picoos_int16 nI, nJ, k; + /* picoos_single InvSqrt3=(picoos_single)2/(picoos_single)sqrt(3.0); *//*constant*/ + picoos_int32 Ti, sqrtTi; + picoos_int16 hop, winlen, Fs; + picoos_single E, F0; + picoos_int16 voiced; + picoos_single fact; /*normalization factor*/ + picoos_single rounding = 0.5f; + + /*Link local variables to sig object*/ + hop = sig_inObj->hop_p; + winlen = sig_inObj->m2_p; + Fs = sig_inObj->Fs_p; + E = sig_inObj->E_p; + F0 = sig_inObj->F0_p; + voiced = sig_inObj->voiced_p; + + /* shift previous excitation window by hop samples*/ + for (nI = 0; nI < sig_inObj->nV; nI++) { + sig_inObj->LocV[nI] = sig_inObj->LocV[nI] - hop; + } + for (nI = 0; nI < sig_inObj->nU; nI++) { + sig_inObj->LocU[nI] = sig_inObj->LocU[nI] - hop; + } + + /*get rid of the voiced points that fall out of the interval*/ + nI = 0; + while ((sig_inObj->LocV[nI] < 0) && nI < sig_inObj->nV) + nI++; + + for (nJ = nI; nJ < sig_inObj->nV; nJ++) { + sig_inObj->LocV[nJ - nI] = sig_inObj->LocV[nJ]; + sig_inObj->EnV[nJ - nI] = sig_inObj->EnV[nJ]; + } + sig_inObj->nV -= nI; + /*get rid of the unvoiced points that fall out of the interval */ + nI = 0; + while ((sig_inObj->LocU[nI] < 0) && nI < sig_inObj->nU) + nI++; + + for (nJ = nI; nJ < sig_inObj->nU; nJ++) { + sig_inObj->LocU[nJ - nI] = sig_inObj->LocU[nJ]; + sig_inObj->EnU[nJ - nI] = sig_inObj->EnU[nJ]; + } + sig_inObj->nU -= nI; + + *nextPeak -= hop; + k = *nextPeak; + + fact = 3; + if (voiced == 0) { /*Unvoiced*/ + + Ti = (picoos_int32) (rounding + (picoos_single) Fs + / (picoos_single) sig_inObj->Fuv_p); /* round Period*/ + sqrtTi = (picoos_int32) (E * sqrt((double) Fs + / (hop * sig_inObj->Fuv_p)) * fact * PICODSP_GETEXC_K1); + while (k < winlen) { + if (k < winlen) { + sig_inObj->LocU[sig_inObj->nU] = k; + sig_inObj->EnU[sig_inObj->nU] = sqrtTi; + sig_inObj->nU++; + k += (picoos_int16) Ti; + } + } + } else { /*Voiced*/ + Ti + = (picoos_int32) (rounding + (picoos_single) Fs + / (picoos_single) F0); /*Period*/ + sqrtTi = (picoos_int32) (E + * sqrt((double) Fs / (hop * sig_inObj->F0_p)) * fact + * PICODSP_GETEXC_K1); + while (k < winlen) { + sig_inObj->LocV[sig_inObj->nV] = k; + sig_inObj->EnV[sig_inObj->nV] = sqrtTi; + sig_inObj->nV++; + k += (picoos_int16) Ti; + } + } + *nextPeak = k; + +}/*get_simple_excitation*/ + +#ifdef __cplusplus +} +#endif + +/* end picosig2.c */ diff --git a/pico/lib/picosig2.h b/pico/lib/picosig2.h new file mode 100644 index 0000000..f239ced --- /dev/null +++ b/pico/lib/picosig2.h @@ -0,0 +1,229 @@ +/* + * 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 picosig2.h + * + * Signal Generation PU - Internal functions - header file + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#ifndef PICOSIG2_H_ +#define PICOSIG2_H_ + +#include "picoos.h" +#include "picodsp.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/*---------------------------------------------------------- + // Name : sig_innerobj + // Function: innerobject definition for the sig processing + // Shortcut: sig + //---------------------------------------------------------*/ +typedef struct sig_innerobj +{ + + /*-----------------------Definition of the local storage for this PU--------*/ + picoos_int16 *idx_vect1; /*reserved for bit reversal tables*/ + picoos_int16 *idx_vect2; /*reserved for table lookup "A" vector*/ + picoos_int16 *idx_vect4; /*reserved for max peak index arrax in pchip*/ + picoos_int16 *idx_vect5; /*reserved for min index arrax in sigana_singleIMF*/ + picoos_int16 *idx_vect6; /*reserved for max index arrax in sigana_singleIMF*/ + picoos_int16 *idx_vect7; /*reserved for dispersed phase */ + picoos_int16 *idx_vect8; /*reserved for LocV*/ + picoos_int16 *idx_vect9; /*reserved for LocU*/ + + picoos_int32 *int_vec22; /*reserved for normalized hanning window - fixed point */ + picoos_int32 *int_vec23; /*reserved for impresp - fixed point */ + picoos_int32 *int_vec24; /*reserved for impresp - fixed point */ + picoos_int32 *int_vec25; /*reserved for window - fixed point */ + picoos_int32 *int_vec26; /*reserved for wavBuf - fixed point */ + picoos_int32 *int_vec28; /*reserved for cepstral vectors input - fixed point */ + picoos_int32 *int_vec29; /*reserved for cepstral vectors input - fixed point */ + picoos_int32 *int_vec38; /*reserved for cepstral vectors input - fixed point */ + picoos_int32 *int_vec30; /*reserved for cepstral vectors input - fixed point */ + picoos_int32 *int_vec31; /*reserved for cepstral vectors input - fixed point */ + + picoos_int32 *int_vec32; /*reserved for cepstral vectors input - fixed point */ + picoos_int32 *int_vec33; /*reserved for cepstral vectors input - fixed point */ + + picoos_int32 *int_vec34; /* reserved for sin table- fixed point */ + picoos_int32 *int_vec35; /* reserved for cos table - fixed point */ + picoos_int32 *int_vec36; /* reserved for currently used sin table- fixed point */ + picoos_int32 *int_vec37; /* reserved for currently used cos table - fixed point */ + + picoos_int32 *int_vec39; /* reserved for ang - fixed point */ + picoos_int32 *int_vec40; /* reserved for cos table - fixed point */ + + picoos_int32 *int_vec41[CEPST_BUFF_SIZE]; /*reserved for phase smoothing - cepstrum buffers */ + picoos_int32 *int_vec42[PHASE_BUFF_SIZE]; /*reserved for phase smoothing - phase buffers */ + + picoos_int16 idx_vect10[CEPST_BUFF_SIZE]; /*reserved for pitch value buffering before phase smoothing*/ + picoos_int16 idx_vect11[CEPST_BUFF_SIZE]; /*reserved for phonetic value bufferingid before phase smoothing*/ + picoos_int16 idx_vect12[CEPST_BUFF_SIZE]; /*reserved for voicing value bufferingbefore phase smoothing*/ + picoos_int16 idx_vect13[CEPST_BUFF_SIZE]; /*reserved for unrectified pitch value bufferingbefore phase smoothing*/ + picoos_int16 idx_vect14[PHASE_BUFF_SIZE]; /*reserved for vox_bnd value buffering before phase smoothing*/ + + picoos_int32 *sig_vec1; + + picoos_single bvalue1; /*reserved for warp*/ + picoos_int32 ibvalue2; /*reserved for voxbnd*/ + picoos_int32 ibvalue3; /*reserved for voxbnd2*/ + picoos_single bvalue4; /*reserved for E*/ + picoos_single bvalue5; /*reserved for F0*/ + picoos_single bvalue6; /*reserved for sMod*/ + + picoos_single bvalue7; /*reserved for voicing*/ + picoos_single bvalue8; /*reserved for unrectified pitch*/ + + picoos_int16 ivalue1; /*reserved for m1,ceporder*/ + picoos_int16 ivalue2; /*reserved for m2,fftorder,windowlen*/ + picoos_int16 ivalue3; /*reserved for fftorder/2*/ + picoos_int16 ivalue4; /*reserved for framelen, displacement*/ + picoos_int16 ivalue5; /*reserved for voiced*/ + picoos_int16 ivalue6; /*reserved for generic result code*/ + picoos_int16 ivalue7; /*reserved for i*/ + picoos_int16 ivalue8; /*reserved for j*/ + picoos_int16 ivalue9; /*reserved for hop*/ + picoos_int16 ivalue10; /*reserved for nextPeak*/ + picoos_int16 ivalue11; /*reserved for nFrame*/ + picoos_int16 ivalue12; /*reserved for raw*/ + picoos_int16 ivalue13; /*reserved for hts engine flag*/ + picoos_int16 ivalue14; /*reserved for ph id*/ + picoos_int16 ivalue15; /*reserved for Voiced*/ + picoos_int16 ivalue16; /*reserved for prevVoiced*/ + picoos_int16 ivalue17; /*reserved for nV (size of LocV)*/ + picoos_int16 ivalue18; /*reserved for nU (size of LocU)*/ + + picoos_int16 ivalue19; /*reserved for voicTrans*/ + + picoos_int16 ivalue20; /*reserved for n_availabe index*/ + + picoos_int32 lvalue1; /*reserved for sampling rate*/ + picoos_int32 lvalue2; /*reserved for VCutoff*/ + picoos_int32 lvalue3; /*reserved for UVCutoff*/ + picoos_int32 lvalue4; /*reserved for fMax */ + + picoos_int32 iRand; /*reserved for phase random table poointer ())*/ + +} sig_innerobj_t; + +/*------------------------------------------------------------------ + Exported (to picosig.c) Service routines : + routine name and I/O parameters are to be maintained for PICO compatibility!! + ------------------------------------------------------------------*/ +extern pico_status_t sigAllocate(picoos_MemoryManager mm, + sig_innerobj_t *sig_inObj); +extern void sigDeallocate(picoos_MemoryManager mm, sig_innerobj_t *sig_inObj); +extern void sigDspInitialize(sig_innerobj_t *sig_inObj); + +/*------------------------------------------------------------------ + Exported (to picosig.c) Processing routines : + routine number, name and content can be changed. unique I/O parameter should be "sig" + ------------------------------------------------------------------*/ +extern void mel_2_lin_init(sig_innerobj_t *sig_inObj); +extern void save_transition_frame(sig_innerobj_t *sig_inObj); +extern void mel_2_lin_init(sig_innerobj_t *sig_inObj); +extern void post_filter_init(sig_innerobj_t *sig_inObj); +extern void mel_2_lin_lookup(sig_innerobj_t *sig_inObj, picoos_uint32 mgc); +extern void post_filter(sig_innerobj_t *sig_inObj); +extern void phase_spec2(sig_innerobj_t *sig_inObj); +extern void env_spec(sig_innerobj_t *sig_inObj); +extern void save_transition_frame(sig_innerobj_t *sig_inObj); +extern void td_psola2(sig_innerobj_t *sig_inObj); +extern void impulse_response(sig_innerobj_t *sig_inObj); +extern void overlap_add(sig_innerobj_t *sig_inObj); + +/* ------------------------------------------------------------------- + * symbolic vs area assignements + * -------------------------------------------------------------------*/ +#define WavBuff_p int_vec26 /*output is Wav buffer (2*FFTSize)*/ +#define window_p int_vec25 /*window function (hanning) */ +#define ImpResp_p int_vec23 /*output step 6*/ +#define imp_p int_vec24 /*output step 6*/ +#define warp_p bvalue1 /*warp factor */ +#define voxbnd_p ibvalue2 /*phase spectra reconstruction noise factor V*/ /* fixed point */ +#define voxbnd2_p ibvalue3 /*phase spectra reconstruction noise factor UV */ /* fixed point */ +#define E_p bvalue4 /*energy after Envelope spectrum calculation */ +#define F0_p bvalue5 /*pitch*/ +#define sMod_p bvalue6 /*speaker modification factor*/ +#define voicing bvalue7 /*voicing*/ +#define Fuv_p bvalue8 /*unrectified pitch (for unvoiced too)*/ +#define m1_p ivalue1 /*ceporder(melorder=ceporder-1) */ +#define m2_p ivalue2 /*fftorder*/ +#define windowLen_p ivalue2 /*same as fftorder*/ +#define hfftsize_p ivalue3 /*fftorder/2*/ +#define framesz_p ivalue4 /*displacement*/ +#define voiced_p ivalue5 /*voicing state*/ +#define nRes_p ivalue6 /*generic result*/ +#define i_p ivalue7 /*generic counter*/ +#define j_p ivalue8 /*generic counter*/ +#define hop_p ivalue9 /*hop */ +#define nextPeak_p ivalue10 /*nextPeak*/ +#define phId_p ivalue14 /*phonetic id*/ +#define prevVoiced_p ivalue16 /*previous voicing state (for frame 1)*/ +#define nV ivalue17 +#define nU ivalue18 +#define VoicTrans ivalue19 /* */ +#define Fs_p lvalue1 /*Sampling frequency*/ +#define VCutoff_p lvalue2 /*voicing cut off frequency in Hz*/ +#define UVCutoff_p lvalue3 /*unvoicing cut off frequency in Hz*/ +/* Reusable area */ +#define wcep_pI int_vec28 /*input step1*/ +#define d_p int_vec38 /*output mel_2_lin_init : table lookup vector D*/ +#define A_p idx_vect2 /*output mel_2_lin_init : table lookup vector A*/ +#define ang_p int_vec39 /*output step4*/ +#define EnV int_vec30 +#define EnU int_vec31 +#define randCosTbl int_vec34 +#define randSinTbl int_vec35 +#define outCosTbl int_vec36 +#define outSinTbl int_vec37 +#define cos_table int_vec40 +#define norm_window_p int_vec22 /*window function (hanning) */ +#define norm_window2_p int_vec27 /*window function (hanning) */ +#define F2r_p int_vec32 /*output step 7*/ +#define F2i_p int_vec33 /*output step 7*/ +#define LocV idx_vect8 /*excitation position voiced pulses*/ +#define LocU idx_vect9 /*excitation position unvoiced pulses*/ + +#define CepBuff int_vec41 /*Buffer for incoming cepstral vector pointers*/ +#define PhsBuff int_vec42 /*Buffer for incoming phase vector pointers*/ +#define F0Buff idx_vect10 /*Buffer for incoming F0 values*/ +#define PhIdBuff idx_vect11 /*Buffer for incoming PhId values*/ +#define VoicingBuff idx_vect12 /*Buffer for incoming voicing values*/ +#define FuVBuff idx_vect13 /*Buffer for incoming FuV values*/ +#define VoxBndBuff idx_vect14 /*Buffer for incoming VoxBnd values*/ + +#define n_available ivalue20 /*variable for indexing the incoming buffers*/ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pico/lib/picospho.c b/pico/lib/picospho.c new file mode 100644 index 0000000..0d0cdf8 --- /dev/null +++ b/pico/lib/picospho.c @@ -0,0 +1,1694 @@ +/* + * 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 picospho.c + * + * sentence phonemic/phonetic FSTs PU + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#include "picoos.h" +#include "picodbg.h" +#include "picodata.h" + +#include "picoknow.h" +#include "picokfst.h" +#include "picoktab.h" +#include "picotrns.h" + +#include "picospho.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +#define SPHO_BUFSIZE (3 * PICODATA_BUFSIZE_DEFAULT) + + + +#define SPHO_MAX_ALTDESC_SIZE (60 * PICOTRNS_MAX_NUM_POSSYM) + + +#define SPHO_SMALLEST_SIL_DUR 1 + + +/** @addtogroup picospho + * + * Algorithmic description + * ======================= + * The main function, sphoStep, is divided into the subprocesses (processing states) described further down. + * + * Flow control: + * ------------ + * The processing flow is controlled by setting + * - 'procState' : the next state to be processed + * - 'feedFollowState' : the state to be processed after the feed state (the feed state is treated like a primitive "subroutine") + * - some other flags + * + * Buffering: + * --------- + * - The input items are mainly stored and processed in two buffers, collectively called 'inBuf' + * - cbuf : unstructured buffer containing item contents + * - headx : structured buffer containing item heads, each expanded by a pointer to the item contents + * and space for a boundary potentially to be inserted (to the left of the original item) + * - For transduction, phonemes and their position are extracted from inBuf into + * - phonBuf, + * processed there, and the resulting phonemes realigned with inBuf. + * - Word items are split into syllables, stored in + * - sylBuf + * - Items to be output are stored in outBuf + * + * Windowing: + * --------- + * Optimal solutions are achieved if a whole sentence is processed at once. However, if any of the buffers are too small, + * only sentence parts are processed. To improve the quality of such sub-optimal solutions, a moving-window-with-overlap is applied: + * - [0,headxReadPos[ : the window considered for transduction + * - [activeStartPos,activeEndPos[ : the "active" subrange of the window actually used for output + * - penultima : the position (within the active range) that should be used as new window start when shifting the window + * + * After PROCESS_PARSE: + * 0 activeStartPos penultima activeEndPos headxReadPos headxWritePos + * | | | | | | + * |-------------=================================---------------| ['----': context '====' : active subrange) + * + * After PROCESS_SHIFT: + * 0 activeStartPos headWritePos + * | | | | + * |------------... (only left context is known; new active range, penultima, and right context to be established at next parse) + * + * Processing states: + * ----------------- + * - INIT : initialize state variables + * - COLLECT : collect items into internal buffers ("inBuf") + * - PROCESS_PARSE : go through inBuf items and extract position/phoneme pairs into phoneme buffer 'phonBuf' + * word boundary phonemes are inserted between words + * - PROCESS_TRANSDUCE : transduce phonBuf + * - PROCESS_BOUNDS : go through inBuf items again and match against transduced pos/phoneme + * this is the first round of alignment, only inserting/deleting/modifying bounds, according to + * - existing BOUND items + * - newly produced word bounds separating WORDPHON items + * - bound upgrades/downgrades from transduction + * - bound upgrades/downgrades/insertions from SIL command items (originating e.g. from text commands) + * all relevant bounds are placed in the corresponding headx extention; original bound items become invalid. + * - PROCESS_RECOMB : go through inBuf items again and match against transduced pos/phoneme + * this is the second round of alignment, treating non-BOUND items + * - WORDPHONs are broken into syllables by "calling" PROCESS_SYL + * - "side-bounds" (in the headx extension) are output by "calling" FEED + * - BOUND items are consumed with no effect + * - other items are output unchanged "calling" FEED + * - PROCESS_SYL : the WORDPHON coming from RECOMB is matched against the phonBuf and (new) SYLLPHON items + * are created. (the original wordphon is consumed) + * - FEED : feeds one item and returns to spho->feedFollowState + * - SHIFT : items in inBuf are shifted left to make room for new items. If a sentence doesn't fit + * inBuf in its entirety, left and/or right contexts are kept so they can be considered in + * the next transduction. + */ + + + +/* PU sphoStep states */ +#define SPHO_STEPSTATE_INIT 0 +#define SPHO_STEPSTATE_COLLECT 1 +#define SPHO_STEPSTATE_PROCESS_PARSE 2 +#define SPHO_STEPSTATE_PROCESS_TRANSDUCE 3 +#define SPHO_STEPSTATE_PROCESS_BOUNDS 4 +#define SPHO_STEPSTATE_PROCESS_RECOMB 5 +#define SPHO_STEPSTATE_PROCESS_SYL 6 +#define SPHO_STEPSTATE_FEED 7 +#define SPHO_STEPSTATE_SHIFT 8 + +#define SPHO_POS_INVALID (PICOTRNS_POS_INVALID) /* indicates that no position was set yet */ + +/* nr item restriction: maximum number of extended item heads in headx */ +#define SPHO_MAXNR_HEADX 60 + +/* nr item restriction: maximum size of all item contents together in cont */ +#define SPHO_MAXSIZE_CBUF (30 * 255) + +/* "expanded head": item head expanded by a content position and a by boundary information + * potentially inserted "to the left" of the item */ +typedef struct { + picodata_itemhead_t head; + picoos_uint16 cind; + picoos_uint8 boundstrength; /* bstrength to the left, 0 if not set */ + picoos_uint8 phrasetype; /* btype for following phrase, 0 if not set */ + picoos_int16 sildur; /* silence duration for boundary, -1 if not set */ +} picospho_headx_t; + + + +#define SPHO_MSGSTR_SIZE 32 + +/** object : SentPhoUnit + * shortcut : spho + * derived from : picodata_ProcessingUnit + */ +typedef struct spho_subobj { + picoos_Common common; + + /* we use int16 for buffer positions so we can indicate exceptional positions (invalid etc.) with negative + * integers */ + picoos_uint8 procState; /* for next processing step decision */ + + /* buffer for item headers */ + picoos_uint8 tmpbuf[PICODATA_MAX_ITEMSIZE]; /* tmp. location for an item */ + + picospho_headx_t headx[SPHO_MAXNR_HEADX]; /* "expanded head" buffer */ + picoos_uint16 headxBufSize; /* actually allocated size (if one day headxBuf is allocated dynamically) */ + picoos_uint16 headxReadPos, headxWritePos; + + picoos_uint8 cbuf[SPHO_MAXSIZE_CBUF]; + picoos_uint16 cbufBufSize; /* actually allocated size */ + picoos_uint16 cbufWritePos; /* next position to write to, 0 if buffer empty */ + + picoos_uint8 outBuf[PICODATA_BUFSIZE_DEFAULT]; /* internal output buffer to hold just one item */ + picoos_uint16 outBufSize; /* actually allocated size (if one day outBuf is allocated dynamically) */ + picoos_uint16 outReadPos; /* next pos to read from inBuf for output */ + + /* picoos_int16 outWritePos; */ /* next pos to output from in buf */ + + picoos_uint8 sylBuf[255]; /* internal buffer to hold contents of syl item to be output */ + picoos_uint8 sylReadPos, sylWritePos; /* next pos to read from sylBuf, next pos to write to sylBuf */ + + /* buffer for internal calculation of transducer */ + picotrns_AltDesc altDescBuf; + /* the number of AltDesc in the buffer */ + picoos_uint16 maxAltDescLen; + + /* the input to a transducer should not be larger than PICOTRNS_MAX_NUM_POSSYM + * so the output may expand (up to 4*PICOTRNS_MAX_NUM_POSSYM) */ + + picotrns_possym_t phonBufA[4 * PICOTRNS_MAX_NUM_POSSYM + 1]; + picotrns_possym_t phonBufB[4 * PICOTRNS_MAX_NUM_POSSYM + 1]; + picotrns_possym_t * phonBuf; + picotrns_possym_t * phonBufOut; + picoos_uint16 phonReadPos, phonWritePos; /* next pos to read from phonBufIn, next pos to write to phonBufIn */ + + picoos_int16 activeStartPos; /* start position of items to be treated (at end of left context) */ + picoos_int16 penultima, activeEndPos; /* positions of last two bounds/words; SPHO_POS_INVALID means uninitialized */ + picoos_int16 lastPhraseBoundPos; /* position of the last bound encountered (<0 if inexistent or not reachable */ + picoos_uint8 lastPhraseType; /* phrase type of the last phrase boundary, 0 if not set */ + + picoos_uint8 needMoreInput, /* more data necessary to decide on token */ + suppressParseWordBound, /* dont produce word boundary */ + suppressRecombWordBound, /* dont produce word boundary */ + breakPending, /* received a break but didn't interpret it yet */ + /* sentEnd, */ /* sentence end detected */ + force, /* in forced state */ + wordStarted, /* is it the first syl in the word: expect POS */ + sentenceStarted; + + picoos_uint16 breakTime; /* time argument of the pending break command */ + + picoos_uint8 feedFollowState; /* where to return after feed */ + + /* fst knowledge bases */ + picoos_uint8 numFsts; + picokfst_FST fst[PICOKNOW_MAX_NUM_SPHO_FSTS]; + picoos_uint8 curFst; /* the fst to be applied next */ + + /* fixed ids knowledge base */ + picoktab_FixedIds fixedIds; + + /* phones kb */ + picoktab_Phones phones; + + /* some soecial ids from phones */ + picoos_uint8 primStressId, secondStressId, syllSepId; + +} spho_subobj_t; + + +static pico_status_t sphoReset(register picodata_ProcessingUnit this) +{ + + spho_subobj_t * spho; + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(this->common->em, + PICO_ERR_NULLPTR_ACCESS, NULL, NULL); + } + spho = (spho_subobj_t *) this->subObj; + + spho->curFst = 0; + +/* processing state */ + spho->procState = SPHO_STEPSTATE_INIT; + spho->needMoreInput = TRUE; + spho->suppressParseWordBound = FALSE; + spho->suppressRecombWordBound = FALSE; + spho->breakPending = FALSE; + spho->force = 0; + spho->sentenceStarted = 0; + + + /* item buffer headx/cbuf */ + spho->headxBufSize = SPHO_MAXNR_HEADX; + spho->headxReadPos = 0; + spho->headxWritePos = 0; + + spho->cbufWritePos = 0; + spho->cbufBufSize = SPHO_MAXSIZE_CBUF; + + /* possym buffer */ + spho->phonBuf = spho->phonBufA; + spho->phonBufOut = spho->phonBufB; + spho->phonReadPos = 0; + + /* overlapping */ + spho->activeStartPos = 0; + spho->penultima = SPHO_POS_INVALID; + spho->activeEndPos = SPHO_POS_INVALID; + + return PICO_OK; +} + + +static pico_status_t sphoInitialize(register picodata_ProcessingUnit this) +{ + picoos_uint8 i; + spho_subobj_t * spho; + picokfst_FST fst; + + picoknow_kb_id_t myKbIds[PICOKNOW_MAX_NUM_SPHO_FSTS] = PICOKNOW_KBID_SPHO_ARRAY; + + PICODBG_DEBUG(("init")); + + if (NULL == this || NULL == this->subObj) { + return picoos_emRaiseException(this->common->em, + PICO_ERR_NULLPTR_ACCESS, NULL, NULL); + } + + spho = (spho_subobj_t *) this->subObj; + + spho->numFsts = 0; + + spho->curFst = 0; + + for (i = 0; ivoice->kbArray[myKbIds[i]]); + if (NULL != fst) { + spho->fst[spho->numFsts++] = fst; + } + } + spho->fixedIds = picoktab_getFixedIds(this->voice->kbArray[PICOKNOW_KBID_FIXED_IDS]); + spho->phones = picoktab_getPhones(this->voice->kbArray[PICOKNOW_KBID_TAB_PHONES]); + + spho->syllSepId = picoktab_getSyllboundID(spho->phones); + spho->primStressId = picoktab_getPrimstressID(spho->phones); + spho->secondStressId = picoktab_getSecstressID(spho->phones); + + PICODBG_DEBUG(("got %i fsts", spho->numFsts)); + + + return sphoReset(this); + +} + +static picodata_step_result_t sphoStep(register picodata_ProcessingUnit this, + picoos_int16 mode, picoos_uint16 *numBytesOutput); + + + + +static pico_status_t sphoTerminate(register picodata_ProcessingUnit this) +{ + return PICO_OK; +} + + +static pico_status_t sphoSubObjDeallocate(register picodata_ProcessingUnit this, + picoos_MemoryManager mm) +{ + spho_subobj_t * spho; + + spho = (spho_subobj_t *) this->subObj; + + if (NULL != this) { + if (NULL != this->subObj) { + spho = (spho_subobj_t *) (this->subObj); + picotrns_deallocate_alt_desc_buf(spho->common->mm,&spho->altDescBuf); + picoos_deallocate(mm, (void *) &this->subObj); + } + } + return PICO_OK; +} + +picodata_ProcessingUnit picospho_newSentPhoUnit(picoos_MemoryManager mm, + picoos_Common common, picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, picorsrc_Voice voice) +{ + spho_subobj_t * spho; + + picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, cbOut, voice); + if (this == NULL) { + return NULL; + } + + this->initialize = sphoInitialize; + this->step = sphoStep; + this->terminate = sphoTerminate; + this->subDeallocate = sphoSubObjDeallocate; + + this->subObj = picoos_allocate(mm, sizeof(spho_subobj_t)); + if (this->subObj == NULL) { + picoos_deallocate(mm, (void **)(void*)&this); + return NULL; + } + spho = (spho_subobj_t *) this->subObj; + + spho->common = this->common; + + /* these are given by the pre-allocated array sizes */ + spho->outBufSize = PICODATA_BUFSIZE_DEFAULT; + + + spho->altDescBuf = picotrns_allocate_alt_desc_buf(spho->common->mm, SPHO_MAX_ALTDESC_SIZE, &spho->maxAltDescLen); + if (NULL == spho->altDescBuf) { + picotrns_deallocate_alt_desc_buf(spho->common->mm,&spho->altDescBuf); + picoos_emRaiseException(spho->common->em,PICO_EXC_OUT_OF_MEM, NULL,NULL); + return NULL; + } + + sphoInitialize(this); + return this; +} + + +/* ***********************************************************************/ +/* process buffered item list */ +/* ***********************************************************************/ + + +/* shift relevant data in headx/'cbuf' (between 'readPos' incl and writePos non-incl) to 'start'. + * modify read/writePos accordingly */ +static picoos_int16 shift_range_left_1(spho_subobj_t *spho, picoos_int16 * from, picoos_int16 to) +{ + + /* remember shift parameters for cbuf */ + picoos_uint16 + c_i, + c_j, + c_diff, + c_writePos, + i, + j, + diff, + writePos; + i = to; + j = *from; + diff = j-i; + writePos = spho->headxWritePos; + c_i = spho->headx[to].cind; + if (j < writePos) { + c_j = spho->headx[j].cind; + } else { + c_j = spho->cbufWritePos; + } + c_diff = c_j - c_i; + c_writePos = spho->cbufWritePos; + + PICODBG_DEBUG(( + "shifting buffer region [%i,%i[ down to %i",*from, writePos, to + )); + + + /* PICODBG_ASSERT((i j) { + return -1; + } + /* shift cbuf */ + while (c_j < c_writePos) { + spho->cbuf[c_i++] = spho->cbuf[c_j++]; + } + /* shift headx */ + while (j < writePos) { + spho->headx[j].cind -= c_diff; + spho->headx[i++] = spho->headx[j++]; + } + spho->headxWritePos -= diff; + *from = to; + spho->cbufWritePos -= c_diff; + /* */ + PICODBG_DEBUG(( + "readPos,WritePos are now [%i,%i[, returning shift amount %i",*from, spho->headxWritePos, diff + )); + return diff; +} + +static pico_status_t sphoAddPhoneme(register spho_subobj_t *spho, picoos_int16 pos, picoos_int16 sym) { + picoos_uint8 plane, unshifted; + /* just for debuging */ + unshifted = picotrns_unplane(sym,&plane); + PICODBG_TRACE(("adding %i/%i (%c on plane %i) at phonBuf[%i]",pos,sym,unshifted,plane,spho->phonWritePos)); + if (2* PICOTRNS_MAX_NUM_POSSYM <= spho->phonWritePos) { + /* not an error! */ + PICODBG_DEBUG(("couldn't add because phon buffer full")); + return PICO_EXC_BUF_OVERFLOW; + } else { + spho->phonBuf[spho->phonWritePos].pos = pos; + spho->phonBuf[spho->phonWritePos].sym = sym; + spho->phonWritePos++; + return PICO_OK; + } +} + +static pico_status_t sphoAddStartPhoneme(register spho_subobj_t *spho) { + return sphoAddPhoneme(spho, PICOTRNS_POS_IGNORE, + (PICOKFST_PLANE_INTERN << 8) + spho->fixedIds->phonStartId); +} + +static pico_status_t sphoAddTermPhonemes(register spho_subobj_t *spho, picoos_uint16 pos) { + return sphoAddPhoneme(spho, pos, + (PICOKFST_PLANE_PB_STRENGTHS << 8) + PICODATA_ITEMINFO1_BOUND_SEND) + && sphoAddPhoneme(spho, PICOTRNS_POS_IGNORE, + (PICOKFST_PLANE_INTERN << 8) + spho->fixedIds->phonTermId); +} + +/* return "syllable accent" (or prominence) symbol, given "word accent" symbol 'wacc' and stress value (no=0, primary=1, secondary=2) */ +static picoos_uint16 sphoGetSylAccent(register spho_subobj_t *spho, + picoos_uint8 wacc, picoos_uint8 sylStress) +{ + PICODBG_ASSERT(sylStress <= 2); + + spho = spho; /* avoid warning "var not used in this function"*/ + + switch (sylStress) { + case 0: /* non-stressed syllable gets no prominence */ + /* return spho->fixedIds->accId[0]; */ + return PICODATA_ACC0; + break; + case 1: /* primary-stressed syllable gets word prominence */ + return wacc; + break; + case 2: /* secondary-stressed syllable gets no prominence or secondary stress prom. (4) */ + return (PICODATA_ACC0 == wacc) ? PICODATA_ACC0 + : PICODATA_ACC4; + /*return (spho->fixedIds->accId[0] == wacc) ? spho->fixedIds->accId[0] + : spho->fixedIds->accId[4]; */ + break; + default: + /* never occurs :-) */ + return PICODATA_ACC0; + break; + } +} + + +/* ***********************************************************************/ +/* extract phonemes of an item into a phonBuf */ +/* ***********************************************************************/ +static pico_status_t sphoExtractPhonemes(register picodata_ProcessingUnit this, + register spho_subobj_t *spho, picoos_uint16 pos, + picoos_uint8 convertAccents, picoos_uint8 * suppressWB) +{ + pico_status_t rv = PICO_OK; + picoos_uint16 i, j; + picoos_int16 fstSymbol; + picoos_uint8 curStress; + picotrns_possym_t tmpPosSym; + picoos_uint16 oldPos, curPos; + picodata_itemhead_t * head; + picoos_uint8* content; + +#if defined(PICO_DEBUG) + picoos_char msgstr[SPHO_MSGSTR_SIZE]; +#endif + + + /* + Items considered in a transduction are a BOUND or a WORDPHON item. its starting offset within the + headxBuf is given as 'pos'. + Elements that go into the transduction receive "their" position in the buffer. + */ + + oldPos = spho->phonWritePos; + + head = &(spho->headx[pos].head); + content = spho->cbuf + spho->headx[pos].cind; + + PICODBG_TRACE(("doing item %s\n", + picodata_head_to_string(head,msgstr,SPHO_MSGSTR_SIZE))); + + switch (head->type) { + case PICODATA_ITEM_BOUND: + /* map SBEG, SEND and TERM (as sentence closing) to SEND */ + fstSymbol = (PICODATA_ITEMINFO1_BOUND_SBEG == head->info1 || PICODATA_ITEMINFO1_BOUND_TERM == head->info1) ? PICODATA_ITEMINFO1_BOUND_SEND : head->info1; + PICODBG_TRACE(("found bound of type %c\n",head->info1)); + /* BOUND() */ + /* insert bound strength */ + PICODBG_TRACE(("inserting phrase bound phoneme %c and setting suppresWB=1\n",fstSymbol)); + fstSymbol += (PICOKFST_PLANE_PB_STRENGTHS << 8); + rv = sphoAddPhoneme(spho,pos,fstSymbol); + /* phrase type not used */ + /* suppress next word boundary */ + (*suppressWB) = 1; + break; + + case PICODATA_ITEM_WORDPHON: + /* WORDPHON(POS,WACC)phon */ + PICODBG_TRACE(("found WORDPHON")); + /* insert word boundary if not suppressed */ + if (!(*suppressWB)) { + fstSymbol = (PICOKFST_PLANE_PB_STRENGTHS << 8) + PICODATA_ITEMINFO1_BOUND_PHR0; + PICODBG_TRACE(("adding word boundary phone")); + rv = sphoAddPhoneme(spho,pos,fstSymbol); + } + (*suppressWB) = 0; + /* for the time being, we force to use POS so we can transduce all fsts in a row without reconsulting the items */ + + + /* If 'convertAccents' then the accentuation is not directly encoded. It rather influences the mapping of + * the word accent symbol to the actual accent phoneme which is put after the syllable separator. */ + if (convertAccents) { + PICODBG_TRACE(("converting accents")); + /* extracting phonemes IN REVERSE order replacing syllable symbols with prominence symbols */ + curPos = spho->phonWritePos; + curStress = 0; /* no stress */ + for (i = head->len; i > 0 ;) { + i--; + if (spho->primStressId == content[i]) { + curStress = 1; + PICODBG_DEBUG(("skipping primary stress at pos %i (in 1 .. %i)",i, head->len)); + continue; /* skip primary stress symbol */ + } else if (spho->secondStressId == content[i]) { + curStress = 2; + PICODBG_DEBUG(("skipping secondary stress at pos %i (in 1 .. %i)",i, head->len)); + continue; /* skip secundary stress symbol */ + } else if (spho->syllSepId == content[i]) { + fstSymbol = (PICOKFST_PLANE_POS << 8) + head->info1; + rv = sphoAddPhoneme(spho, pos, fstSymbol); + /* replace syllSepId by combination of syllable stress and word prominence */ + fstSymbol = sphoGetSylAccent(spho,head->info2,curStress); + curStress = 0; + /* add accent */ + fstSymbol += (PICOKFST_PLANE_ACCENTS << 8); + rv = sphoAddPhoneme(spho,pos,fstSymbol); + if (PICO_OK != rv) { + break; + } + /* and keep syllable boundary */ + fstSymbol = (PICOKFST_PLANE_PHONEMES << 8) + content[i]; + } else { + /* normal phoneme */ + fstSymbol = (PICOKFST_PLANE_PHONEMES << 8) + content[i]; + } + if (PICO_OK == rv) { + rv = sphoAddPhoneme(spho,pos,fstSymbol); + } + } + if (PICO_OK == rv) { + /* bug 366: we position the "head" into the item header and not on the first phoneme + * because there might be no phonemes at all */ + /* insert head of the first syllable of a word */ + fstSymbol = (PICOKFST_PLANE_POS << 8) + head->info1; + rv = sphoAddPhoneme(spho,pos,fstSymbol); + fstSymbol = sphoGetSylAccent(spho,head->info2,curStress); + curStress = 0; + fstSymbol += (PICOKFST_PLANE_ACCENTS << 8); + rv = sphoAddPhoneme(spho,pos,fstSymbol); + } + if (PICO_OK == rv) { + /* invert sympos portion */ + i = curPos; + j=spho->phonWritePos-1; + while (i < j) { + tmpPosSym.pos = spho->phonBuf[i].pos; + tmpPosSym.sym = spho->phonBuf[i].sym; + spho->phonBuf[i].pos = spho->phonBuf[j].pos; + spho->phonBuf[i].sym = spho->phonBuf[j].sym; + spho->phonBuf[j].pos = tmpPosSym.pos; + spho->phonBuf[j].sym = tmpPosSym.sym; + i++; + j--; + } + } + } else { /* convertAccents */ + for (i = 0; i len; i++) { + fstSymbol = (PICOKFST_PLANE_PHONEMES << 8) + content[i]; + rv = sphoAddPhoneme(spho,pos,fstSymbol); + } + } + break; + default: + picoos_emRaiseException(this->common->em,rv,NULL,NULL); + break; + } /* switch(head->type) */ + if (PICO_OK != rv) { + spho->phonWritePos = oldPos; + } + return rv; +} + + + + + +#define SPHO_POSSYM_OK 0 +#define SPHO_POSSYM_OUT_OF_RANGE 1 +#define SPHO_POSSYM_END 2 +#define SPHO_POSSYM_INVALID -3 +/* *readPos is the next position in phonBuf to be read, and *writePos is the first position not to be read (may be outside + * buf). + * 'rangeEnd' is the first possym position outside the desired range. + * Possible return values: + * SPHO_POSSYM_OK : 'pos' and 'sym' are set to the read possym, *readPos is advanced + * SPHO_POSSYM_OUT_OF_RANGE : pos is out of range. 'pos' is set to that of the read possym, 'sym' is undefined + * SPHO_POSSYM_UNDERFLOW : no more data in buf. 'pos' is set to PICOTRNS_POS_INVALID, 'sym' is undefined + * SPHO_POSSYM_INVALID : "strange" pos. 'pos' is set to PICOTRNS_POS_INVALID, 'sym' is undefined + */ +static pico_status_t getNextPosSym(spho_subobj_t * spho, picoos_int16 * pos, picoos_int16 * sym, + picoos_int16 rangeEnd) { + /* skip POS_IGNORE */ + while ((spho->phonReadPos < spho->phonWritePos) && (PICOTRNS_POS_IGNORE == spho->phonBuf[spho->phonReadPos].pos)) { + PICODBG_DEBUG(("ignoring phone at spho->phonBuf[%i] because it has pos==IGNORE",spho->phonReadPos)); + spho->phonReadPos++; + } + if ((spho->phonReadPos < spho->phonWritePos)) { + *pos = spho->phonBuf[spho->phonReadPos].pos; + if ((PICOTRNS_POS_INSERT == *pos) || ((0 <= *pos) && (*pos < rangeEnd))) { + *sym = spho->phonBuf[spho->phonReadPos++].sym; + return SPHO_POSSYM_OK; + } else if (*pos < 0){ /* *pos is "strange" (e.g. POS_INVALID) */ + return SPHO_POSSYM_INVALID; + } else { + return SPHO_POSSYM_OUT_OF_RANGE; + } + } else { + /* no more possyms to read */ + *pos = PICOTRNS_POS_INVALID; + return SPHO_POSSYM_END; + } +} + + + +/** Calculate bound strength modified by transduction + * + * Given the original bound strength 'orig' and the desired target strength 'target' (suggested by fst), + * calculate the modified bound strength. + * + * @param orig original bound strength + * @param target target bound strength + * @return resulting bound strength + */ +static picoos_uint8 fstModifiedBoundStrength(picoos_uint8 orig, picoos_uint8 target) +{ + switch (orig) { + case PICODATA_ITEMINFO1_BOUND_PHR1: + case PICODATA_ITEMINFO1_BOUND_PHR2: + /* don't allow primary phrase bounds to be demoted to word bound */ + if (PICODATA_ITEMINFO1_BOUND_PHR0 == target) { + return PICODATA_ITEMINFO1_BOUND_PHR3; + } + case PICODATA_ITEMINFO1_BOUND_PHR0: + case PICODATA_ITEMINFO1_BOUND_PHR3: + return target; + break; + default: + /* don't allow bounds other than phrase or word bounds to be changed */ + return orig; + break; + } +} + +/** Calculate bound strength modified by a \ command + * + * Given the original (predicted and possibly fst-modified) bound strength, and a time value from an + * overwriding \ command, calculate the modified bound strength. + * + * @param orig original bound strength + * @param time time given as property of \ command + * @param wasPrimary + * @return modified bound strength + */ +static picoos_uint8 breakModifiedBoundStrength(picoos_uint8 orig, picoos_uint16 time, picoos_bool wasPrimary) +{ + picoos_uint8 modified = (0 == time) ? PICODATA_ITEMINFO1_BOUND_PHR3 : + (50 < time) ? PICODATA_ITEMINFO1_BOUND_PHR1 : PICODATA_ITEMINFO1_BOUND_PHR2; + switch (orig) { + /* for word and phrase breaks, return 'modified', unless a non-silence gets time==0, in which + * case return no break (word break) */ + case PICODATA_ITEMINFO1_BOUND_PHR0: + if (0 == time) { + return PICODATA_ITEMINFO1_BOUND_PHR0; + } + case PICODATA_ITEMINFO1_BOUND_PHR3: + if (!wasPrimary && (0 == time)) { + return PICODATA_ITEMINFO1_BOUND_PHR0; + } + case PICODATA_ITEMINFO1_BOUND_PHR1: + case PICODATA_ITEMINFO1_BOUND_PHR2: + return modified; + break; + default: + return orig; + break; + } +} + +static picoos_bool breakStateInterrupting(picodata_itemhead_t * head, + picoos_bool * breakBefore, picoos_bool * breakAfter) { + + picoos_bool result = 1; + + *breakBefore = 0; + *breakAfter = 0; + + if (PICODATA_ITEM_WORDPHON == head->type) { + + } else if (PICODATA_ITEM_CMD == head->type) { + if ((PICODATA_ITEMINFO1_CMD_PLAY == head->info1) + || (PICODATA_ITEMINFO1_CMD_SAVE == head->info1) + || (PICODATA_ITEMINFO1_CMD_UNSAVE == head->info1)) { + *breakBefore = 1; + *breakAfter = 1; + } else if (PICODATA_ITEMINFO1_CMD_SAVE == head->info1) { + *breakBefore = 1; + } else if (PICODATA_ITEMINFO1_CMD_UNSAVE == head->info1) { + *breakAfter = 1; + } else if (PICODATA_ITEMINFO1_CMD_IGNSIG == head->info1) { + if (PICODATA_ITEMINFO2_CMD_START == head->info2) { + *breakBefore = 1; + } else { + *breakAfter = 1; + } + } + } else { + result = 0; + } + return result; +} + + +static void putSideBoundToOutput(spho_subobj_t * spho) +{ + + picodata_itemhead_t ohead; + picoos_uint8 ocontent[2*sizeof(picoos_uint16)]; + picoos_int16 sildur; + picoos_uint16 clen; + + /* create boundary */ + ohead.type = PICODATA_ITEM_BOUND; + ohead.info1 = spho->headx[spho->outReadPos].boundstrength; + ohead.info2 = spho->headx[spho->outReadPos].phrasetype; + sildur = spho->headx[spho->outReadPos].sildur; + if ((sildur < 0) + || (PICODATA_ITEMINFO1_BOUND_PHR0 == ohead.info1) + || (PICODATA_ITEMINFO1_BOUND_PHR3 == ohead.info1)) { + PICODBG_DEBUG(("outputting a bound of strength '%c' and type '%c' without duration constraints",ohead.info1, ohead.info2)); + ohead.len = 0; + } else { + picoos_uint32 pos = 0; + picoos_write_mem_pi_uint16(ocontent,&pos,sildur); + picoos_write_mem_pi_uint16(ocontent,&pos,sildur); + PICODBG_DEBUG(("outputting a bound of strength '%c' and type '%c' with duration constraints [%i,%i]",ohead.info1, ohead.info2,sildur, sildur)); + ohead.len = pos; + } + picodata_put_itemparts(&ohead, ocontent, ohead.len, + spho->outBuf, spho->outBufSize, &clen); + /* disable side bound */ + spho->headx[spho->outReadPos].boundstrength = 0; +} + +/** Set bound strength and sil dur. + * + * given the original bound strength 'orig_strength' and the fst-suggested bound strength 'fst_strength' + * and possibly being in a pending break state, calculate the resulting bound strength and set boundstrength + * and sildur of the current item (spho->headx[spho->outReadPos]) accordingly. + * if a boundstrength was set, also calculate the phrasetype and if necessary (and reachable), modify the phrase type + * of the previous phrase boundary. + * + * @param spho + * @param orig_strength + * @param orig_type + * @param fst_strength + */ +static void setSideBound(spho_subobj_t * spho, picoos_uint8 orig_strength, picoos_uint8 orig_type, picoos_uint8 fst_strength) { + picoos_uint8 strength; + + /* insert modified bound according to transduction symbol, if any */ + if (PICODATA_ITEMINFO1_NA == orig_strength) { + /* no original/fst strength given */ + orig_strength = PICODATA_ITEMINFO1_BOUND_PHR0; + strength = PICODATA_ITEMINFO1_BOUND_PHR0; + } else { + strength = fstModifiedBoundStrength(orig_strength,fst_strength); + spho->headx[spho->outReadPos].boundstrength = strength; + spho->headx[spho->outReadPos].sildur = -1; + PICODBG_DEBUG(("setting bound strength to fst-suggested value %c (was %c)",strength, spho->headx[spho->outReadPos].boundstrength, spho->breakTime)); + } + + /* insert modified bound according to pending break, if any */ + if (spho->breakPending) { + /* the calculation is based on the fst-modified value (because this is what the customer wants to + * override) + */ + strength = breakModifiedBoundStrength(strength, spho->breakTime, (PICODATA_ITEMINFO1_BOUND_PHR1 == orig_strength)); + PICODBG_DEBUG(("setting bound strength to break-imposed value %c (was %c) and time to %i",strength, spho->headx[spho->outReadPos].boundstrength, spho->breakTime)); + spho->headx[spho->outReadPos].boundstrength = strength; + spho->headx[spho->outReadPos].sildur = spho->breakTime; + spho->breakPending = FALSE; + } + if (spho->headx[spho->outReadPos].boundstrength) { + /* we did set a bound strength, possibly promoting or demoting a boundary; now set the phrase type + * possibly also changing the phrase type of the previous phrase bound + */ + picoos_uint8 fromPhrase = ((PICODATA_ITEMINFO1_BOUND_PHR0 != orig_strength)); + picoos_uint8 toPhrase = ((PICODATA_ITEMINFO1_BOUND_PHR0 != strength)); + + PICODBG_DEBUG(("setting phrase type (wasPhrase=%i, isPhrase=%i)",fromPhrase,toPhrase)); + if (toPhrase) { + if (fromPhrase) { + spho->lastPhraseType = orig_type; + } else { /*promote */ + if (spho->activeStartPos <= spho->lastPhraseBoundPos) { + /* we still can change prev phrase bound */ + /* since a new phrase boundary is introduced, we have to 'invent' + * an additional phrase type here. For that, we have to use some of the + * knowledge that otherwise is handled in picoacph. + */ + spho->headx[spho->lastPhraseBoundPos].phrasetype + = PICODATA_ITEMINFO2_BOUNDTYPE_P; + } + } + spho->lastPhraseBoundPos = spho->outReadPos; + spho->headx[spho->lastPhraseBoundPos].phrasetype + = spho->lastPhraseType; + + } else { + spho->headx[spho->outReadPos].phrasetype = PICODATA_ITEMINFO2_NA; + if (fromPhrase) { /* demote */ + spho->lastPhraseType = orig_type; + if (spho->activeStartPos <= spho->lastPhraseBoundPos) { + /* we still can change prev phrase bound */ + spho->headx[spho->lastPhraseBoundPos].phrasetype + = spho->lastPhraseType; + } + } + } + } +} + + +/* ***********************************************************************/ +/* sphoStep function */ +/* ***********************************************************************/ + + +static picodata_step_result_t sphoStep(register picodata_ProcessingUnit this, + picoos_int16 mode, picoos_uint16 * numBytesOutput) +{ + + register spho_subobj_t *spho; + pico_status_t rv= PICO_OK; + picoos_uint16 blen; + picodata_itemhead_t ihead, ohead; + picoos_uint8 *icontent; + picoos_uint16 nextInPos; +#if defined(PICO_DEBUG) + picoos_char msgstr[SPHO_MSGSTR_SIZE]; +#endif + + /* used in FEED and FEED_SYM */ + picoos_uint16 clen; + picoos_int16 pos, sym, sylsym; + picoos_uint8 plane; + + /* used in BOUNDS */ + picoos_bool breakBefore, breakAfter; + + /* pico_status_t rvP= PICO_OK; */ + + picoos_uint16 curPos /*, nextPos */; + picoos_uint16 remHeadxSize, remCbufSize; + + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + spho = (spho_subobj_t *) this->subObj; + + mode = mode; /* avoid warning "var not used in this function"*/ + + *numBytesOutput = 0; + while (1) { /* exit via return */ + PICODBG_INFO(("doing state %i, headxReadPos: %d, headxWritePos: %d", + spho->procState, spho->headxReadPos, spho->headxWritePos)); + + switch (spho->procState) { + + case SPHO_STEPSTATE_INIT: + /* **********************************************************************/ + /* INIT */ + /* **********************************************************************/ + PICODBG_DEBUG(("INIT")); + /* (re)set values for PARSE */ + spho->penultima = SPHO_POS_INVALID; + spho->activeEndPos = SPHO_POS_INVALID; + spho->headxReadPos = 0; + spho->phonReadPos = 0; + spho->phonWritePos = 0; + spho->lastPhraseType = PICODATA_ITEMINFO2_NA; + spho->lastPhraseBoundPos = -1; + + spho->procState = SPHO_STEPSTATE_COLLECT; + break; + + + case SPHO_STEPSTATE_COLLECT: + /* **********************************************************************/ + /* COLLECT */ + /* **********************************************************************/ + /* collect state: get items from charBuf and store in + * internal inBuf + */ + PICODBG_TRACE(("COLLECT")); + rv = PICO_OK; + remHeadxSize = spho->headxBufSize - spho->headxWritePos; + remCbufSize = spho->cbufBufSize - spho->cbufWritePos; + curPos = spho->headxWritePos; + while ((PICO_OK == rv) && (remHeadxSize > 0) && (remCbufSize > 0)) { + PICODBG_DEBUG(("COLLECT getting item at headxWritePos %i (remaining %i)",spho->headxWritePos, remHeadxSize)); + rv = picodata_cbGetItem(this->cbIn, spho->tmpbuf, PICODATA_MAX_ITEMSIZE, &blen); + if (PICO_OK == rv) { + rv = picodata_get_itemparts(spho->tmpbuf, + PICODATA_MAX_ITEMSIZE, &(spho->headx[spho->headxWritePos].head), + &(spho->cbuf[spho->cbufWritePos]), remCbufSize, &blen); + if (PICO_OK == rv) { + spho->headx[spho->headxWritePos].cind = spho->cbufWritePos; + spho->headx[spho->headxWritePos].boundstrength = 0; + spho->headxWritePos++; + remHeadxSize--; + spho->cbufWritePos += blen; + remCbufSize -= blen; + } + } + } + if ((PICO_OK == rv) && ((remHeadxSize <= 0) || (remCbufSize <= 0))) { + rv = PICO_EXC_BUF_OVERFLOW; + } + + /* in normal circumstances, rv is either PICO_EOF (no more items in cbIn) or PICO_BUF_OVERFLOW + * (if no more items fit into headx) */ + if ((PICO_EOF != rv) && (PICO_EXC_BUF_OVERFLOW != rv)) { + PICODBG_DEBUG(("COLLECT ** problem getting item, unhandled, rv: %i", rv)); + picoos_emRaiseException(this->common->em, rv, + NULL, NULL); + return PICODATA_PU_ERROR; + } + if (PICO_EOF == rv) { /* there are no more items available */ + if (curPos < spho->headxWritePos) { /* we did get some new items */ + PICODBG_DEBUG(("COLLECT read %i items", + spho->headxWritePos - curPos)); + spho->needMoreInput = FALSE; + } + if (spho->needMoreInput) { /* not enough items to proceed */ + PICODBG_DEBUG(("COLLECT need more data, returning IDLE")); + return PICODATA_PU_IDLE; + } else { + spho->procState = SPHO_STEPSTATE_PROCESS_PARSE; + /* uncomment next to split into two steps */ + /* return PICODATA_PU_ATOMIC; */ + } + } else { /* input buffer full */ + PICODBG_DEBUG(("COLLECT input buffer full")); + if (spho->needMoreInput) { /* forced output because we can't get more data */ + spho->needMoreInput = FALSE; + spho->force = TRUE; + } + spho->procState = SPHO_STEPSTATE_PROCESS_PARSE; + } + break; + + case SPHO_STEPSTATE_PROCESS_PARSE: + + /* **********************************************************************/ + /* PARSE: items -> input pos/phon pairs */ + /* **********************************************************************/ + + /* parse one item at a time */ + /* If + * - the item is a sentence end or + * - it is the last item and force=1 or + * - the phon buffer is full + * then set inReadPos to 0 and go to TRANSDUCE + * else advance by one item */ + + /* look at the current item */ + PICODBG_TRACE(("PARSE")); + if (spho->headxReadPos >= spho->headxWritePos) { + /* no more items in headx */ + if (spho->force) { + PICODBG_INFO(("no more items in headx but we are forced to transduce")); + + /* headx is full; we are forced to transduce before reaching the sentence end */ + spho->force = FALSE; + if (SPHO_POS_INVALID == spho->activeEndPos) { + spho->activeEndPos = spho->headxReadPos; + } + spho->procState = SPHO_STEPSTATE_PROCESS_TRANSDUCE; + } else { + /* we try to get more data */ + PICODBG_INFO(("no more items in headx, try to collect more")); + spho->needMoreInput = TRUE; + spho->procState = SPHO_STEPSTATE_COLLECT; + } + break; + } + + ihead = spho->headx[spho->headxReadPos].head; + icontent = spho->cbuf + spho->headx[spho->headxReadPos].cind; + + PICODBG_DEBUG(("PARSE looking at item %s",picodata_head_to_string(&ihead,msgstr,SPHO_MSGSTR_SIZE))); + /* treat header */ + if (PICODATA_ITEM_BOUND == ihead.type) { + /* see if it is a sentence end or termination boundary (flush) */ + if ((PICODATA_ITEMINFO1_BOUND_SEND == ihead.info1) + || (PICODATA_ITEMINFO1_BOUND_TERM == ihead.info1)) { + PICODBG_INFO(("PARSE found sentence end or term BOUND")); + + if (spho->sentenceStarted) { + /* its the end of the sentence */ + PICODBG_INFO(("PARSE found sentence end")); + spho->sentenceStarted = 0; + /* there is no need for a right context; move the active end to the end */ + /* add sentence termination phonemes */ + sphoAddTermPhonemes(spho, spho->headxReadPos); + spho->headxReadPos++; + spho->activeEndPos = spho->headxReadPos; + /* we may discard all information up to activeEndPos, after processing of last + * sentence part + */ + spho->penultima = spho->activeEndPos; + + /* transduce */ + spho->procState = SPHO_STEPSTATE_PROCESS_TRANSDUCE; + /* uncomment to split */ + /* return PICODATA_PU_BUSY; */ + break; + } else { + if (PICODATA_ITEMINFO1_BOUND_TERM == ihead.info1) { + /* its the end of input (flush) */ + PICODBG_INFO(("PARSE forwarding input end (flush)")); + /* copy item unmodified */ + picodata_put_itemparts(&ihead, + icontent, + ihead.len, + spho->outBuf, spho->outBufSize, + &clen); + + spho->headxReadPos++; + spho->activeEndPos = spho->headxReadPos; + spho->penultima = SPHO_POS_INVALID; + spho->feedFollowState = SPHO_STEPSTATE_SHIFT; + spho->procState = SPHO_STEPSTATE_FEED; + break; + } else { + /* this should never happen */ + /* eliminate bound */ + spho->headxReadPos++; + spho->activeEndPos = spho->headxReadPos; + spho->penultima = SPHO_POS_INVALID; + PICODBG_ERROR(("PARSE found a sentence end without a sentence start; eliminated")); + } + } + } else if (PICODATA_ITEMINFO1_BOUND_SBEG == ihead.info1) { + /* its the start of the sentence */ + PICODBG_INFO(("PARSE found sentence start")); + /* add sentence starting phoneme */ + sphoAddStartPhoneme(spho); + + spho->sentenceStarted = 1; + } + } + + if ((PICODATA_ITEM_WORDPHON == ihead.type) + || (PICODATA_ITEM_BOUND == ihead.type)) { + /* if it is a word or a bound try to extract phonemes */ + PICODBG_INFO(("PARSE found WORD phon or phrase BOUND")); + rv = sphoExtractPhonemes(this, spho, spho->headxReadPos, + TRUE /* convertAccents */, + &spho->suppressParseWordBound); + if (PICO_OK == rv) { + PICODBG_INFO(("PARSE successfully returned from phoneme extraction")); + /* replace activeEndPos if the new item is a word, or activeEndPos was not set yet, or + * activeEndPos was a bound */ + if ((spho->activeStartPos <= spho->headxReadPos) && ((PICODATA_ITEM_WORDPHON == ihead.type) + || (SPHO_POS_INVALID == spho->activeEndPos) + || (PICODATA_ITEM_BOUND == spho->headx[spho->activeEndPos].head.type))) { + PICODBG_INFO(("PARSE found new activeEndPos: %i,%i -> %i,%i", + spho->penultima,spho->activeEndPos,spho->activeEndPos,spho->headxReadPos)); + spho->penultima = spho->activeEndPos; + spho->activeEndPos = spho->headxReadPos; + } + + } else if (PICO_EXC_BUF_OVERFLOW == rv) { + /* phoneme buffer cannot take this item anymore; + if the phoneme buffer has some contents, we are forced to transduce before reaching the sentence end + else we skip the (too long word) */ + PICODBG_INFO(("PARSE returned from phoneme extraction with overflow, number of phonemes in phonBuf: %i; forced to TRANSDUCE", spho->phonWritePos)); + if ((SPHO_POS_INVALID == spho->activeEndPos) || (spho->activeStartPos == spho->activeEndPos)) { + spho->activeEndPos = spho->headxReadPos; + } + spho->procState = SPHO_STEPSTATE_PROCESS_TRANSDUCE; + break; + } else { + PICODBG_ERROR(("PARSE returned from phoneme extraction with exception %i",rv)); + return (picodata_step_result_t)picoos_emRaiseException(this->common->em, + PICO_ERR_OTHER, NULL, NULL); + } + } else { + PICODBG_INFO(("PARSE found other item, passing over")); + /* it is "other" item, ignore */ + } + /* set pos at next item */ + PICODBG_INFO(("PARSE going to next item: %i -> %i",spho->headxReadPos, spho->headxReadPos + 1)); + spho->headxReadPos++; + break; + + case SPHO_STEPSTATE_PROCESS_TRANSDUCE: + + /* **********************************************************************/ + /* TRANSDUCE: transduction input pos/phon pairs to output pos/phon pairs */ + /* **********************************************************************/ + PICODBG_DEBUG(("TRANSDUCE (%i-th of %i fsts",spho->curFst+1, spho->numFsts)); + + /* termination condition first */ + if (spho->curFst >= spho->numFsts) { + +#if defined(PICO_DEBUG) + { + PICODBG_INFO_CTX(); + PICODBG_INFO_MSG(("result of all transductions: ")); + PICOTRNS_PRINTSYMSEQ(this->voice->kbArray[PICOKNOW_KBID_DBG], spho->phonBufOut, spho->phonWritePos); + PICODBG_INFO_MSG(("\n")); + } +#endif + + /* reset for next transduction */ + spho->curFst = 0; + /* prepare BOUNDS */ + spho->outReadPos = 0; + spho->phonReadPos = 0; + + spho->procState = SPHO_STEPSTATE_PROCESS_BOUNDS; + break; + } + + /* transduce from phonBufIn to PhonBufOut */ + { + + picoos_uint32 nrSteps; +#if defined(PICO_DEBUG) + { + PICODBG_INFO_CTX(); + PICODBG_INFO_MSG(("spho trying to transduce: ")); + PICOTRNS_PRINTSYMSEQ(this->voice->kbArray[PICOKNOW_KBID_DBG], spho->phonBuf, spho->phonWritePos); + PICODBG_INFO_MSG(("\n")); + } +#endif + rv = picotrns_transduce(spho->fst[spho->curFst], FALSE, + picotrns_printSolution, spho->phonBuf, spho->phonWritePos, spho->phonBufOut, + &spho->phonWritePos, + 4*PICOTRNS_MAX_NUM_POSSYM, spho->altDescBuf, + spho->maxAltDescLen, &nrSteps); + if (PICO_OK == rv) { +#if defined(PICO_DEBUG) + { + PICODBG_INFO_CTX(); + PICODBG_INFO_MSG(("result of transduction: (output symbols: %i)", spho->phonWritePos)); + PICOTRNS_PRINTSYMSEQ(this->voice->kbArray[PICOKNOW_KBID_DBG], spho->phonBufOut, spho->phonWritePos); + PICODBG_INFO_MSG(("\n")); + } +#endif + PICODBG_TRACE(("number of steps done in tranduction: %i", nrSteps)); + } else { + picoos_emRaiseWarning(this->common->em, PICO_WARN_FALLBACK,NULL,(picoos_char *)"phon buffer full"); + } + } + /* eliminate deep epsilons */ + picotrns_eliminate_epsilons(spho->phonBufOut, spho->phonWritePos, spho->phonBuf, + &spho->phonWritePos,4*PICOTRNS_MAX_NUM_POSSYM); + + spho->curFst++; + + /* return PICODATA_PU_ATOMIC */ + break; + + + case SPHO_STEPSTATE_PROCESS_BOUNDS: + /* ************************************************************************/ + /* BOUNDS: combine input item with pos/phon pairs to insert/modify bounds */ + /* ************************************************************************/ + + PICODBG_INFO(("BOUNDS")); + + /* get the suppressRecombWordBound in the left context */ + spho->suppressRecombWordBound = FALSE; + while (spho->outReadPos < spho->activeStartPos) { + /* look at the current item */ + ihead = spho->headx[spho->outReadPos].head; + /* icontent = spho->cbuf + spho->headx[spho->outReadPos].cind; */ + PICODBG_INFO(("in position %i, looking at item %s",spho->outReadPos,picodata_head_to_string(&ihead,msgstr,SPHO_MSGSTR_SIZE))); + if (PICODATA_ITEM_BOUND == ihead.type) { + spho->suppressRecombWordBound = TRUE; + } else if (PICODATA_ITEM_WORDPHON == ihead.type) { + spho->suppressRecombWordBound = FALSE; + } + spho->outReadPos++; + } + /* spho->outReadPos point now to the active region */ + + /* advance the phone reading pos to the active range */ + spho->phonReadPos = 0; + while (SPHO_POSSYM_OK == (rv = getNextPosSym(spho, &pos, &sym, + spho->activeStartPos))) { + /* ignore */ + } + PICODBG_INFO(("skipping left context phones results in %s", (SPHO_POSSYM_OUT_OF_RANGE==rv) ? "OUT_OF_RANGE" : (SPHO_POSSYM_END ==rv) ? "END" : "OTHER")); + + /* + * Align input items with transduced phones and note bound stregth changes and break commands + */ + + while (spho->outReadPos < spho->activeEndPos) { + + /* look at the current item */ + ihead = spho->headx[spho->outReadPos].head; + icontent = spho->cbuf + spho->headx[spho->outReadPos].cind; + nextInPos = spho->outReadPos + 1; + /* */ + PICODBG_INFO(("in position %i, looking at item %s",spho->outReadPos,picodata_head_to_string(&ihead,msgstr,SPHO_MSGSTR_SIZE))); + + if ((PICODATA_ITEM_BOUND == ihead.type) + || ((PICODATA_ITEM_WORDPHON == ihead.type) + && (!spho->suppressRecombWordBound))) { + /* there was a boundary originally */ + picoos_uint8 orig_strength, orig_type; + if (PICODATA_ITEM_BOUND == ihead.type) { + orig_strength = ihead.info1; + orig_type = ihead.info2; + spho->suppressRecombWordBound = TRUE; + } else { + orig_strength = PICODATA_ITEMINFO1_BOUND_PHR0; + orig_type = PICODATA_ITEMINFO2_NA; + } + /* i expect a boundary phone here */ + /* consume FST bound phones, consider pending break and set the side-bound */ + PICODBG_INFO(("got BOUND or WORDPHON item and expects corresponding phone")); + rv = getNextPosSym(spho, &pos, &sym, nextInPos); + if (SPHO_POSSYM_OK != rv) { + PICODBG_ERROR(("unexpected symbol or unexpected end of phoneme list (%s)", (SPHO_POSSYM_OUT_OF_RANGE==rv) ? "OUT_OF_RANGE" : (SPHO_POSSYM_END ==rv) ? "END" :"OTHER")); + return (picodata_step_result_t)picoos_emRaiseException(this->common->em, + PICO_ERR_OTHER, NULL, NULL); + } + sym = picotrns_unplane(sym, &plane); + /* */ + PICODBG_ASSERT((PICOKFST_PLANE_PB_STRENGTHS == plane)); + + /* insert modified bound according to transduction and possibly pending break */ + setSideBound(spho, orig_strength, orig_type, + (picoos_uint8) sym); + } else if ((PICODATA_ITEM_CMD == ihead.type) + && (PICODATA_ITEMINFO1_CMD_SIL == ihead.info1)) { + /* it's a SIL (break) command */ + picoos_uint16 time; + picoos_uint32 pos = 0; + picoos_read_mem_pi_uint16(icontent, &pos, &time); + if (spho->breakPending) { + spho->breakTime += time; + } else { + spho->breakTime = time; + spho->breakPending = TRUE; + } + } else if ((PICODATA_ITEM_CMD == ihead.type) && (PICODATA_ITEMINFO1_CMD_PLAY == ihead.info1)) { + /* insert break of at least one ms */ + if (!spho->breakPending || (spho->breakTime <= 0)) { + spho->breakTime = SPHO_SMALLEST_SIL_DUR; + spho->breakPending = TRUE; + } + setSideBound(spho, PICODATA_ITEMINFO1_NA, + PICODATA_ITEMINFO2_NA, PICODATA_ITEMINFO1_NA); + /* force following break to be at least one ms */ + spho->breakTime = SPHO_SMALLEST_SIL_DUR; + spho->breakPending = TRUE; + } else if (breakStateInterrupting(&ihead, &breakBefore, &breakAfter)) { + + if (breakBefore &&(!spho->breakPending || (spho->breakTime <= 0))) { + spho->breakTime = SPHO_SMALLEST_SIL_DUR; + spho->breakPending = TRUE; + } + setSideBound(spho, PICODATA_ITEMINFO1_NA, + PICODATA_ITEMINFO2_NA, PICODATA_ITEMINFO1_NA); + + if (breakAfter) { + spho->breakTime = SPHO_SMALLEST_SIL_DUR; + spho->breakPending = TRUE; + } + if (PICODATA_ITEM_WORDPHON == ihead.type) { + spho->suppressRecombWordBound = FALSE; + } + } + + /* skip phones of that item */ + while (SPHO_POSSYM_OK == (rv = getNextPosSym(spho, &pos, + &sym, nextInPos))) { + /* ignore */ + } + spho->outReadPos++; + } + + /* reset for RECOMB */ + spho->outReadPos = 0; + spho->phonReadPos = 0; + spho->suppressRecombWordBound = FALSE; + + spho->procState = SPHO_STEPSTATE_PROCESS_RECOMB; + return PICODATA_PU_ATOMIC; + + break; + + case SPHO_STEPSTATE_PROCESS_RECOMB: + /* **********************************************************************/ + /* RECOMB: combine input item with pos/phon pairs to output item */ + /* **********************************************************************/ + + PICODBG_TRACE(("RECOMB")); + + /* default place to come after feed: here */ + spho->feedFollowState = SPHO_STEPSTATE_PROCESS_RECOMB; + + /* check termination condition first */ + if (spho->outReadPos >= spho->activeEndPos) { + PICODBG_DEBUG(("RECOMB reached active region's end at %i",spho->outReadPos)); + spho->procState = SPHO_STEPSTATE_SHIFT; + break; + } + + /* look at the current item */ + ihead = spho->headx[spho->outReadPos].head; + icontent = spho->cbuf + spho->headx[spho->outReadPos].cind; + + PICODBG_DEBUG(("RECOMB looking at item %s",picodata_head_to_string(&ihead,msgstr,SPHO_MSGSTR_SIZE))); + + nextInPos = spho->outReadPos + 1; + + PICODBG_DEBUG(("RECOMB treating item in headx at pos %i",spho->outReadPos)); + if (nextInPos <= spho->activeStartPos) { /* we're in the (passive) left context. Just skip it */ + PICODBG_DEBUG(("RECOMB skipping item in the left context (%i <= %i)",nextInPos, spho->activeStartPos)); + if (PICODATA_ITEM_BOUND == ihead.type) { + spho->suppressRecombWordBound = 1; + } else if (PICODATA_ITEM_WORDPHON == ihead.type) { + spho->suppressRecombWordBound = 0; + } + + /* consume possyms */ + while (SPHO_POSSYM_OK == (rv = getNextPosSym(spho,&pos,&sym,nextInPos))) { + /* ignore */ + } + if (rv == SPHO_POSSYM_INVALID) { + return (picodata_step_result_t)picoos_emRaiseException(this->common->em, + PICO_ERR_OTHER, NULL, NULL); + } + spho->outReadPos = nextInPos; + } else { /* active region */ + if (spho->headx[spho->outReadPos].boundstrength) { +/* ***************** "side-bound" *********************/ + /* copy to outbuf */ + putSideBoundToOutput(spho); + /* mark as processed */ + spho->headx[spho->outReadPos].boundstrength = 0; + /* output it */ + spho->procState = SPHO_STEPSTATE_FEED; + } else if (PICODATA_ITEM_BOUND == ihead.type) { +/* ***************** BOUND *********************/ + /* expect a boundary phone here */ + PICODBG_DEBUG(("RECOMB got BOUND item and expects corresponding phone")); + rv = getNextPosSym(spho, &pos, &sym, nextInPos); + if (SPHO_POSSYM_OK != rv) { + PICODBG_ERROR(("unexpected symbol or unexpected end of phoneme list")); + return (picodata_step_result_t)picoos_emRaiseException( + this->common->em, PICO_ERR_OTHER, NULL, + NULL); + } + sym = picotrns_unplane(sym, &plane); + /* */ + PICODBG_ASSERT((PICOKFST_PLANE_PB_STRENGTHS == plane)); + + spho->suppressRecombWordBound = TRUE; /* if word following, don't need word boundary */ + /* just consume item and come back here*/ + spho->outReadPos = nextInPos; + + } else if (PICODATA_ITEM_WORDPHON == ihead.type) { +/* ***************** WORDPHON *********************/ + spho->wordStarted = TRUE; + /* i expect a word boundary symbol in this range unless a phrase boundary was encountered before */ + if (spho->suppressRecombWordBound) { + PICODBG_DEBUG(("RECOMB got WORDPHON item but skips expecting BOUND")); + spho->suppressRecombWordBound = FALSE; + } else { + PICODBG_DEBUG(("RECOMB got WORDPHON item and expects corresponding bound phone")); + rv = getNextPosSym(spho, &pos, &sym, nextInPos); + if (SPHO_POSSYM_OK != rv) { + PICODBG_ERROR(("unexpected symbol or unexpected end of phoneme list")); + return (picodata_step_result_t)picoos_emRaiseException(this->common->em, + PICO_ERR_OTHER, NULL, NULL); + } + } + spho->procState = SPHO_STEPSTATE_PROCESS_SYL; + } else if ((PICODATA_ITEM_CMD == ihead.type) && (PICODATA_ITEMINFO1_CMD_SIL == ihead.info1)) { +/* ***************** BREAK COMMAND *********************/ + /* just consume and come back here */ + PICODBG_DEBUG(("RECOMB consuming item from inBuf %i -> %i",spho->outReadPos, nextInPos)); + spho->outReadPos = nextInPos; + } else { +/* ***************** OTHER *********************/ + /* just copy item */ + PICODBG_DEBUG(("RECOMB found other item, just copying")); + picodata_put_itemparts(&ihead, icontent, ihead.len, + spho->outBuf, spho->outBufSize, &clen); + PICODBG_DEBUG(("RECOMB consuming item from inBuf %i -> %i",spho->outReadPos, nextInPos)); + spho->outReadPos = nextInPos; + /* and output it */ + spho->procState = SPHO_STEPSTATE_FEED; + } /* if (ihead.type) */ + + } + + /* return PICODATA_PU_BUSY; */ + break; + + case SPHO_STEPSTATE_PROCESS_SYL: + /* **********************************************************************/ + /* SYL: combine input word item with pos/phon pairs to syl output item */ + /* **********************************************************************/ + + /* consume all transduced phonemes with pos in in the range [spho->outReadPos,nextInPos[ */ + PICODBG_DEBUG(("SYL")); + + spho->feedFollowState = SPHO_STEPSTATE_PROCESS_SYL; + + /* look at the current item */ + ihead = spho->headx[spho->outReadPos].head; + icontent = spho->cbuf + spho->headx[spho->outReadPos].cind; + nextInPos = spho->outReadPos + 1; + PICODBG_DEBUG(("SYL (1) treating item in headx at pos %i",spho->outReadPos)); + /* create syllable item in ohead (head) and sylBuf (contents) */ + ohead.type = PICODATA_ITEM_SYLLPHON; + + PICODBG_TRACE(("SYL expects accent at phonBuf[%i] = (%i,%i) (outReadPos=%i)", spho->phonReadPos, spho->phonBuf[spho->phonReadPos].pos, spho->phonBuf[spho->phonReadPos].sym,spho->outReadPos)); + rv = getNextPosSym(spho,&pos,&sym,nextInPos); + if (SPHO_POSSYM_OK != rv) { + PICODBG_ERROR(("unexpected symbol or unexpected end of phoneme list (%i)",rv)); + return (picodata_step_result_t)picoos_emRaiseException(this->common->em, PICO_ERR_OTHER, NULL, NULL); + } + ohead.info2 = picotrns_unplane(sym, &plane); + PICODBG_ASSERT((PICOKFST_PLANE_ACCENTS == plane)); + PICODBG_DEBUG(("SYL sets accent to %c", sym)); + + /* for the time being, we force to use POS so we can transduce all fsts in a row without reconsulting the items */ + PICODBG_TRACE(("SYL expects POS")); + PICODBG_DEBUG(("SYL (2) treating item in inBuf range [%i,%i[",spho->outReadPos,nextInPos)); + rv = getNextPosSym(spho,&pos,&sym,nextInPos); + if (SPHO_POSSYM_OK != rv) { + PICODBG_ERROR(("unexpected symbol or unexpected end of phoneme list")); + return (picodata_step_result_t)picoos_emRaiseException(this->common->em, PICO_ERR_OTHER, NULL, NULL); + } + if (spho->wordStarted) { + spho->wordStarted = FALSE; + ohead.info1 = picotrns_unplane(sym, &plane); + /* */ + PICODBG_ASSERT(PICOKFST_PLANE_POS == plane); + /* */ + PICODBG_DEBUG(("SYL setting POS to %c", ohead.info1)); + } else { + ohead.info1 = PICODATA_ITEMINFO1_NA; + } + + PICODBG_DEBUG(("SYL (3) treating item in inBuf range [%i,%i[",spho->outReadPos,nextInPos)); + /* get phonemes of that syllable; stop if syllable boundary or outside word */ + sylsym = (PICOKFST_PLANE_PHONEMES << 8) + + spho->syllSepId; + PICODBG_DEBUG(("collecting syllable phonemes before headx position %i",nextInPos)); + spho->sylWritePos = 0; + while (SPHO_POSSYM_OK == (rv = getNextPosSym(spho,&pos,&sym,nextInPos)) && (sym != sylsym)) { + spho->sylBuf[spho->sylWritePos++] = picotrns_unplane(sym, &plane); + /* */ + PICODBG_TRACE(("SYL adding phoneme to syllable: (pos %i,sym %i)[plane %i,sym %c]",pos,sym,plane,sym & 0xFF)); + PICODBG_ASSERT((PICOKFST_PLANE_PHONEMES == plane)); + } + PICODBG_DEBUG(("SYL (4) treating item in inBuf range [%i,%i[",spho->outReadPos,nextInPos)); + ohead.len = spho->sylWritePos; + if (SPHO_POS_INVALID == rv) { + PICODBG_ERROR(("unexpected symbol or unexpected end of phoneme list")); + return (picodata_step_result_t)picoos_emRaiseException(this->common->em, PICO_WARN_INCOMPLETE, NULL, NULL); + } else if ((SPHO_POSSYM_OUT_OF_RANGE == rv) || (SPHO_POSSYM_END == rv)) { + PICODBG_DEBUG(("SYL arrived at end of word and/or end of phon buffer, go to next word")); + spho->outReadPos = nextInPos; /* advance to next item */ + spho->feedFollowState = SPHO_STEPSTATE_PROCESS_RECOMB; /* go to RECOMB after feed */ + } else { + PICODBG_ASSERT((sym == sylsym)); + } + PICODBG_DEBUG(("SYL (5) treating item in inBuf range [%i,%i[",spho->outReadPos,nextInPos)); + + if (ohead.len > 0) { + /* prepare syllable output */ + picodata_put_itemparts(&ohead, spho->sylBuf, + PICODATA_BUFSIZE_DEFAULT, spho->outBuf, + spho->outBufSize, &clen); + + spho->procState = SPHO_STEPSTATE_FEED; + } else { /* skip feeding output of empty syllable */ + spho->procState = spho->feedFollowState; + } + break; + + case SPHO_STEPSTATE_FEED: + /* **********************************************************************/ + /* FEED: output output item and proceed to feedFollowState */ + /* **********************************************************************/ + + PICODBG_DEBUG(("FEED")); + + PICODBG_DEBUG(("FEED putting outBuf item into cb")); + + /*feeding items to PU output buffer*/ + rv = picodata_cbPutItem(this->cbOut, spho->outBuf, + spho->outBufSize, &clen); + + PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], + (picoos_uint8 *)"spho: ", + spho->outBuf, spho->outBufSize); + + if (PICO_EXC_BUF_OVERFLOW == rv) { + /* we have to redo this item */ + PICODBG_DEBUG(("FEED got overflow, returning ICODATA_PU_OUT_FULL")); + return PICODATA_PU_OUT_FULL; + } else if (PICO_OK == rv) { + *numBytesOutput += clen; + spho->procState = spho->feedFollowState; + PICODBG_DEBUG(("FEED ok, going back to procState %i", spho->procState)); + return PICODATA_PU_BUSY; + } else { + PICODBG_DEBUG(("FEED got exception %i when trying to output item",rv)); + spho->procState = spho->feedFollowState; + return (picodata_step_result_t)rv; + } + break; + + case SPHO_STEPSTATE_SHIFT: + /* **********************************************************************/ + /* SHIFT */ + /* **********************************************************************/ + /* If there exists a valid penultima, it should replace any left context (from 0 to activeStartPos) + * else discard the current active range (from activeStartPos to activeEndPos), leaving the current + * left context intact. Often, PARSE would move activeStartPos to 0, so that there is no left context + * after the shift. + */ + + PICODBG_DEBUG(("SHIFT")); + + if (spho->penultima != SPHO_POS_INVALID) { + picoos_int16 shift; + /* set penultima as new left context and set activeStartPos to the shifted activeEndPos */ + PICODBG_DEBUG(( + "SHIFT shifting penultima from %i to 0", + spho->penultima)); + shift = shift_range_left_1(spho, &spho->penultima, 0); + if (shift < 0) { + picoos_emRaiseException(this->common->em,PICO_ERR_OTHER,NULL,NULL); + return PICODATA_PU_ERROR; + } + spho->activeStartPos = spho->activeEndPos + - shift; + spho->lastPhraseBoundPos -= shift; + spho->suppressParseWordBound = FALSE; + spho->suppressRecombWordBound = FALSE; + + } else { + picoos_int16 shift; + picoos_bool lastPhraseBoundActive; + if (spho->activeStartPos == spho->activeEndPos) { + /* no items consumed; we have to abandon left context */ + spho->activeStartPos = 0; + } + lastPhraseBoundActive = (spho->lastPhraseBoundPos >= spho->activeStartPos); + /* dummy comment */ + PICODBG_DEBUG(("SHIFT shift active end from %i to %i", + spho->activeEndPos, spho->activeStartPos)); + shift = shift_range_left_1(spho, &spho->activeEndPos, spho->activeStartPos); + if (shift < 0) { + picoos_emRaiseException(this->common->em,PICO_ERR_OTHER,NULL,NULL); + return PICODATA_PU_ERROR; + } + if (lastPhraseBoundActive) { + spho->lastPhraseBoundPos -= shift; + } + } + + spho->procState = SPHO_STEPSTATE_INIT; + break; + + default: + picoos_emRaiseException(this->common->em, PICO_ERR_OTHER, NULL, NULL); + return PICODATA_PU_ERROR; + break; + + } /* switch (spho->procState) */ + + } /* while (1) */ + + /* should be never reached */ + picoos_emRaiseException(this->common->em, PICO_ERR_OTHER, NULL, NULL); + return PICODATA_PU_ERROR; +} + +#ifdef __cplusplus +} +#endif + +/* end picospho.c */ diff --git a/pico/lib/picospho.h b/pico/lib/picospho.h new file mode 100644 index 0000000..0c4a0d8 --- /dev/null +++ b/pico/lib/picospho.h @@ -0,0 +1,175 @@ +/* + * 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 picospho.h + * + * sentence phonemic/phonetic FSTs PU + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +/** @addtogroup picospho +itemtype, iteminfo1, iteminfo2, content -> TYPE(INFO1,INFO2)content +in the following + +items input +=========== + +processed: + +- WORDPHON(POS,WACC)phon + +- BOUND(BOUNDstrength,BOUNDtype) + + +unprocessed: +- all other item types are forwared through the PU without modification + + + +- POS + a the single, unambiguous POS + +cf. picodata.h for +- WACC (sentence-level accent (aka prominence)) + PICODATA_ACC0 + PICODATA_ACC1 + PICODATA_ACC2 (<- maybe mapped to ACC1, ie. no ACC2 in output) + PICODATA_ACC3 + + +- BOUNDstrength + PICODATA_ITEMINFO1_BOUND_SBEG (sentence start) + PICODATA_ITEMINFO1_BOUND_SEND (at sentence end) + PICODATA_ITEMINFO1_BOUND_TERM (replaces a flush) + PICODATA_ITEMINFO1_BOUND_PHR0 (no break) + PICODATA_ITEMINFO1_BOUND_PHR1 (primary boundary) + PICODATA_ITEMINFO1_BOUND_PHR2 (short break) + PICODATA_ITEMINFO1_BOUND_PHR3 (secondary phrase boundary, no break) + +- BOUNDtype (actually phrase type of the following phrase) + PICODATA_ITEMINFO2_BOUNDTYPE_P (non-terminal phrase) + PICODATA_ITEMINFO2_BOUNDTYPE_T (terminal phrase) + PICODATA_ITEMINFO2_BOUNDTYPE_Q (question terminal phrase) + PICODATA_ITEMINFO2_BOUNDTYPE_E (exclamation terminal phrase) + + +output sequence (without CMDs): + + = { BOUND(BOUND_SBEG,PHRASEtype) BOUND(BOUND_SEND,..)} BOUND(BOUND_TERM,..) + + = { BOUND(BOUND_PHR1|2|3,PHRASEtype) } + + = WORDPHON(POS,ACC)phon { WORDPHON(POS,ACC)phon } + + + +mapping ACC & word-level stress to syllable accent value + + ACC0 prim -> 0 + ACC1 prim -> 1 + ACC2 prim -> 2 + ACC3 prim -> 3 + + ACC0 sec -> 0 + ACC1 sec -> 4 + ACC2 sec -> 4 + ACC3 sec -> 4 + +Mapping of values to FST symbol id (has to identical to the symbol table used when compiling the FST) + +Value FST symbol id +phoneme_id -> phoneme_id + 256 * PICOKFST_PLANE_PHONEMES +POS_id -> POS_id + 256 * PICOKFST_PLANE_POS +phrasetype_id -> phrasetype_id + 256 * PICOKFST_PLANE_PHRASETYPES +accentlevel_id -> accentlevel_id + 256 * PICOKFST_PLANE_ACCENTS + + + + + + + +minimal input size (before processing starts) +================== + +processing (ie. sequencially applying spho transducers to phoneme sequence composed of + - phonemes inside WORDPHON items and + - pseudo-phonemes derived from boundaries and POS) is possible with + +- one phrase, consisting of a sequence of maximal 30 non-PUNC items + terminated by a PUNC item. A PUNC is artificially enforced if + needed to start processing. + +- as long as the internal buffer is empty, non-processed item types + can be processed immediately + + + +items output +============ +- BOUND(BOUNDstrength,BOUNDtype) + + bound strength may be changed by the fsts + + in addition, BOUNDs of BOUNDstrength = PHR0 are inserted to mark word boundaries + +- SYLLPHON(POS,ACC)phon + where POS is only set for the first syllable of a word, otherwise NA + + + + + + +other limitations +================= + + + */ +#ifndef PICOSPHO_H_ +#define PICOSPHO_H_ + +#include "picoos.h" +#include "picodata.h" +#include "picorsrc.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +picodata_ProcessingUnit picospho_newSentPhoUnit( + picoos_MemoryManager mm, + picoos_Common common, + picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, + picorsrc_Voice voice); + +#ifdef __cplusplus +} +#endif + + +#endif /*PICOSPHO_H_*/ diff --git a/pico/lib/picotok.c b/pico/lib/picotok.c new file mode 100644 index 0000000..4488609 --- /dev/null +++ b/pico/lib/picotok.c @@ -0,0 +1,1563 @@ +/* + * 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 picotok.c + * + * tokenizer + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + + +/* ************************************************************/ +/* tokenisation and markup handling */ +/* ************************************************************/ + +/** @addtogroup picotok + @b tokenisation_overview + + markup handling overview: + + The following markups are recognized + - ignore + - speed + - pitch + - volume + - voice + - preproccontext + - mark + - play + - usesig + - genfile + - sentence + - s + - paragraph + - p + - break + - spell (pauses between letter) + - phoneme + + All markups which are recognized but are not yet implemented in pico + system have the mark. +*/ + + +#include "picodefs.h" +#include "picoos.h" +#include "picobase.h" +#include "picodbg.h" +#include "picodata.h" +#include "picotok.h" +#include "picoktab.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/* *****************************************************************************/ + +#define IN_BUF_SIZE 255 +#define OUT_BUF_SIZE IN_BUF_SIZE + 3 * PICODATA_ITEM_HEADSIZE + 3 + +#define MARKUP_STRING_BUF_SIZE (IN_BUF_SIZE*5) +#define MAX_NR_MARKUP_PARAMS 6 +#define MARKUP_HANDLING_DISABLED 0 +#define MARKUP_HANDLING_ENABLED 1 +#define EOL '\n' + + +typedef picoos_int8 pico_tokenSubType; +typedef picoos_uint8 pico_tokenType; + +/** @todo : consider adding these specialized exception codes: */ + +#define PICO_ERR_MARKUP_VALUE_OUT_OF_RANGE PICO_ERR_OTHER +#define PICO_ERR_INVALID_MARKUP_TAG PICO_ERR_OTHER +#define PICO_ERR_INTERNAL_LIMIT PICO_ERR_OTHER + +typedef enum {MIDummyStart, MIIgnore, + MIPitch, MISpeed, MIVolume, + MIVoice, MIPreprocContext, MIMarker, + MIPlay, MIUseSig, MIGenFile, MIParagraph, + MISentence, MIBreak, MISpell, MIPhoneme, MIItem, MISpeaker, MIDummyEnd + } MarkupId; +typedef enum {MSNotInMarkup, MSGotStart, MSExpectingmarkupTagName, MSInmarkupTagName, + MSGotmarkupTagName, MSInAttrName, MSGotAttrName, MSGotEqual, MSInAttrValue, + MSInAttrValueEscaped, MSGotAttrValue, MSGotEndSlash, MSGotEnd, + MSError, MSErrorTooLong, MSErrorSyntax + } MarkupState; +typedef enum {MENone, MEMissingStart, MEUnknownTag, MEIdent, MEMissingEqual, + MEMissingQuote, MEMissingEnd, MEUnexpectedChar, MEInterprete + } MarkupParseError; + +typedef enum {MTNone, MTStart, MTEnd, MTEmpty} MarkupTagType; + +#define UTF_CHAR_COMPLETE 2 +#define UTF_CHAR_INCOMPLETE 1 +#define UTF_CHAR_MALFORMED 0 + +#define TOK_MARKUP_KW_IGNORE (picoos_uchar*)"ignore" +#define TOK_MARKUP_KW_SPEED (picoos_uchar*)"speed" +#define TOK_MARKUP_KW_PITCH (picoos_uchar*)"pitch" +#define TOK_MARKUP_KW_VOLUME (picoos_uchar*)"volume" +#define TOK_MARKUP_KW_VOICE (picoos_uchar*)"voice" +#define TOK_MARKUP_KW_CONTEXT (picoos_uchar*)"preproccontext" +#define TOK_MARKUP_KW_MARK (picoos_uchar*)"mark" +#define TOK_MARKUP_KW_PLAY (picoos_uchar*)"play" +#define TOK_MARKUP_KW_USESIG (picoos_uchar*)"usesig" +#define TOK_MARKUP_KW_GENFILE (picoos_uchar*)"genfile" +#define TOK_MARKUP_KW_SENTENCE (picoos_uchar*)"sentence" +#define TOK_MARKUP_KW_S (picoos_uchar*)"s" +#define TOK_MARKUP_KW_PARAGRAPH (picoos_uchar*)"paragraph" +#define TOK_MARKUP_KW_P (picoos_uchar*)"p" +#define TOK_MARKUP_KW_BREAK (picoos_uchar*)"break" +#define TOK_MARKUP_KW_SPELL (picoos_uchar*)"spell" +#define TOK_MARKUP_KW_PHONEME (picoos_uchar*)"phoneme" +#define TOK_MARKUP_KW_ITEM (picoos_uchar*)"item" +#define TOK_MARKUP_KW_SPEAKER (picoos_uchar*)"speaker" + +#define KWLevel (picoos_uchar *)"level" +#define KWName (picoos_uchar *)"name" +#define KWProsDomain (picoos_uchar *)"prosodydomain" +#define KWTime (picoos_uchar *)"time" +#define KWMode (picoos_uchar *)"mode" +#define KWSB (picoos_uchar *)"sb" +#define KWPB (picoos_uchar *)"pb" +#define KWFile (picoos_uchar *)"file" +#define KWType (picoos_uchar *)"type" +#define KWF0Beg (picoos_uchar *)"f0beg" +#define KWF0End (picoos_uchar *)"f0end" +#define KWXFadeBeg (picoos_uchar *)"xfadebeg" +#define KWXFadeEnd (picoos_uchar *)"xfadeend" +#define KWAlphabet (picoos_uchar *)"alphabet" +#define KWPH (picoos_uchar *)"ph" +#define KWOrthMode (picoos_uchar *)"orthmode" +#define KWIgnorePunct (picoos_uchar *)"ignorepunct" +#define KWInfo1 (picoos_uchar *)"info1" +#define KWInfo2 (picoos_uchar *)"info2" +#define KWDATA (picoos_uchar *)"data" + +#define PICO_SPEED_MIN 20 +#define PICO_SPEED_MAX 500 +#define PICO_SPEED_DEFAULT 100 +#define PICO_SPEED_FACTOR_MIN 500 +#define PICO_SPEED_FACTOR_MAX 2000 + +#define PICO_PITCH_MIN 50 +#define PICO_PITCH_MAX 200 +#define PICO_PITCH_DEFAULT 100 +#define PICO_PITCH_FACTOR_MIN 500 +#define PICO_PITCH_FACTOR_MAX 2000 +#define PICO_PITCH_ADD_MIN -100 +#define PICO_PITCH_ADD_MAX 100 +#define PICO_PITCH_ADD_DEFAULT 0 + +#define PICO_VOLUME_MIN 0 +#define PICO_VOLUME_MAX 500 +#define PICO_VOLUME_DEFAULT 100 +#define PICO_VOLUME_FACTOR_MIN 500 +#define PICO_VOLUME_FACTOR_MAX 2000 + +#define PICO_SPEAKER_MIN 20 +#define PICO_SPEAKER_MAX 180 +#define PICO_SPEAKER_DEFAULT 100 +#define PICO_SPEAKER_FACTOR_MIN 500 +#define PICO_SPEAKER_FACTOR_MAX 2000 + +#define PICO_CONTEXT_DEFAULT (picoos_uchar*)"DEFAULT" + +#define PARAGRAPH_PAUSE_DUR 500 +#define SPELL_WITH_PHRASE_BREAK 1 +#define SPELL_WITH_SENTENCE_BREAK 2 + +/* *****************************************************************************/ + +#define TOK_PUNC_FLUSH (picoos_char) '\0' + +typedef picoos_uchar Word[MARKUP_STRING_BUF_SIZE]; + + +struct MarkupParam { + Word paramId; + Word paramVal; +}; + +typedef struct MarkupParam MarkupParams[MAX_NR_MARKUP_PARAMS]; + + +/** subobject : TokenizeUnit + * shortcut : tok + */ +typedef struct tok_subobj +{ + picoos_int32 ignLevel; + + picoos_uchar utf[5]; + picoos_int32 utfpos; + picoos_int32 utflen; + + MarkupParams markupParams; + picoos_int32 nrMarkupParams; + MarkupState markupState; + picoos_uchar markupStr[MARKUP_STRING_BUF_SIZE]; + picoos_int32 markupPos; + picoos_int32 markupLevel[MIDummyEnd+1]; + picoos_uchar markupTagName[IN_BUF_SIZE]; + MarkupTagType markupTagType; + MarkupParseError markupTagErr; + + picoos_int32 strPos; + picoos_uchar strDelim; + picoos_bool isFileAttr; + + pico_tokenType tokenType; + pico_tokenSubType tokenSubType; + + picoos_int32 tokenPos; + picoos_uchar tokenStr[IN_BUF_SIZE]; + + picoos_int32 nrEOL; + + picoos_bool markupHandlingMode; /* to be moved ??? */ + picoos_bool aborted; /* to be moved ??? */ + + picoos_bool start; + + picoos_uint8 outBuf[OUT_BUF_SIZE]; /* internal output buffer */ + picoos_uint16 outReadPos; /* next pos to read from outBuf */ + picoos_uint16 outWritePos; /* next pos to write to outBuf */ + + picoos_uchar saveFile[IN_BUF_SIZE]; + Word phonemes; + + picotrns_SimpleTransducer transducer; + + /* kbs */ + + picoktab_Graphs graphTab; + picokfst_FST xsampa_parser; + picokfst_FST svoxpa_parser; + picokfst_FST xsampa2svoxpa_mapper; + + + +} tok_subobj_t; + +/* *****************************************************************************/ + +static void tok_treatMarkupAsSimpleToken (picodata_ProcessingUnit this, tok_subobj_t * tok); +static void tok_treatChar (picodata_ProcessingUnit this, tok_subobj_t * tok, picoos_uchar ch, picoos_bool markupHandling); +static void tok_treatMarkup (picodata_ProcessingUnit this, tok_subobj_t * tok); +static void tok_putToMarkup (picodata_ProcessingUnit this, tok_subobj_t * tok, picoos_uchar str[]); +static void tok_treatSimpleToken (picodata_ProcessingUnit this, tok_subobj_t * tok); +static MarkupId tok_markupTagId (picoos_uchar tagId[]); + +/* *****************************************************************************/ + +static picoos_bool tok_strEqual(picoos_uchar * str1, picoos_uchar * str2) +{ + return (picoos_strcmp((picoos_char*)str1, (picoos_char*)str2) == 0); +} + +static void tok_reduceBlanks(picoos_uchar * str) + /* Remove leading and trailing blanks of 'str' and reduce + groups of blanks within string to exactly one blank. */ + +{ + int i = 0; + int j = 0; + + while (str[j] != 0) { + if (str[j] == (picoos_uchar)' ') { + /* note one blank except at the beginning of string */ + if (i > 0) { + str[i] = (picoos_uchar)' '; + i++; + } + j++; + while (str[j] == (picoos_uchar)' ') { + j++; + } + } else { + str[i] = str[j]; + j++; + i++; + } + } + + /* remove blanks at end of string */ + if ((i > 0) && (str[i - 1] == ' ')) { + i--; + } + str[i] = 0; +} + + +static void tok_startIgnore (tok_subobj_t * tok) +{ + tok->ignLevel++; +} + + +static void tok_endIgnore (tok_subobj_t * tok) +{ + if (tok->ignLevel > 0) { + tok->ignLevel--; + } +} + + +static void tok_getParamIntVal (MarkupParams params, picoos_uchar paramId[], picoos_int32 * paramVal, picoos_bool * paramFound) +{ + int i=0; + + while ((i < MAX_NR_MARKUP_PARAMS) && !tok_strEqual(paramId,params[i].paramId)) { + i++; + } + if ((i < MAX_NR_MARKUP_PARAMS)) { + (*paramVal) = picoos_atoi((picoos_char*)params[i].paramVal); + (*paramFound) = TRUE; + } else { + (*paramVal) = -1; + (*paramFound) = FALSE; + } +} + + + +static void tok_getParamStrVal (MarkupParams params, picoos_uchar paramId[], picoos_uchar paramStrVal[], picoos_bool * paramFound) +{ + int i=0; + + while ((i < MAX_NR_MARKUP_PARAMS) && !tok_strEqual(paramId,params[i].paramId)) { + i++; + } + if (i < MAX_NR_MARKUP_PARAMS) { + picoos_strcpy((picoos_char*)paramStrVal, (picoos_char*)params[i].paramVal); + (*paramFound) = TRUE; + } else { + paramStrVal[0] = 0; + (*paramFound) = FALSE; + } +} + + +static void tok_getParamPhonesStr (MarkupParams params, picoos_uchar paramId[], picoos_uchar alphabet[], picoos_uchar phones[], picoos_int32 phoneslen, picoos_bool * paramFound) +{ + + int i; + picoos_bool done; + + i = 0; + while ((i < MAX_NR_MARKUP_PARAMS) && !tok_strEqual(paramId, params[i].paramId)) { + i++; + } + if (i < MAX_NR_MARKUP_PARAMS) { + if (tok_strEqual(alphabet, PICODATA_XSAMPA) || tok_strEqual(alphabet, (picoos_uchar*)"")) { + picoos_strlcpy((picoos_char*)phones, (picoos_char*)params[i].paramVal, phoneslen); + done = TRUE; + } else { + done = FALSE; + } + (*paramFound) = TRUE; + } else { + done = FALSE; + (*paramFound) = FALSE; + } + if (!done) { + phones[0] = 0; + } +} + + +static void tok_clearMarkupParams (MarkupParams params) +{ + int i; + + for (i = 0; i= '0') && (durStr[i] <= '9')) { + num = 10 * num + (int)durStr[i] - (int)'0'; + tmpWord[i] = ' '; + i++; + } + tok_reduceBlanks(tmpWord); + if (tok_strEqual(tmpWord, (picoos_uchar*)"s")) { + (*dur) = (1000 * num); + (*done) = TRUE; + } else if (tok_strEqual(tmpWord,(picoos_uchar*)"ms")) { + (*dur) = num; + (*done) = TRUE; + } else { + (*dur) = 0; + (*done) = FALSE; + } +} + + +static picoos_int32 tok_putToUtf (tok_subobj_t * tok, picoos_uchar ch) +{ + if (tok->utfpos < PICOBASE_UTF8_MAXLEN) { + tok->utf[tok->utfpos] = ch; + if (tok->utfpos == 0) { + tok->utflen = picobase_det_utf8_length(ch); + } else if (((ch < (picoos_uchar)'\200') || (ch >= (picoos_uchar)'\300'))) { + tok->utflen = 0; + } + (tok->utfpos)++; + if ((tok->utfpos == tok->utflen)) { + if ((tok->utfpos < PICOBASE_UTF8_MAXLEN)) { + tok->utf[tok->utfpos] = 0; + } + return UTF_CHAR_COMPLETE; + } else if (tok->utfpos < tok->utflen) { + return UTF_CHAR_INCOMPLETE; + } else { + return UTF_CHAR_MALFORMED; + } + } else { + return UTF_CHAR_MALFORMED; + } +} + + +static picoos_bool tok_isRelative (picoos_uchar strval[], picoos_uint32 * val) +{ + picoos_int32 len; + picoos_bool rel; + + rel = FALSE; + len = picoos_strlen((picoos_char*)strval); + if (len > 0) { + if (strval[len - 1] == '%') { + strval[len - 1] = 0; + if ((strval[0] == '+') || (strval[0] == '-')) { + (*val) = 1000 + (picoos_atoi((picoos_char*)strval) * 10); + } else { + (*val) = picoos_atoi((picoos_char*)strval) * 10; + } + rel = TRUE; + } + } + return rel; +} + + +static void tok_putItem (picodata_ProcessingUnit this, tok_subobj_t * tok, + picoos_uint8 itemType, picoos_uint8 info1, picoos_uint8 info2, + picoos_uint16 val, + picoos_uchar str[]) +{ + picoos_int32 len, i; + + if ((itemType == PICODATA_ITEM_CMD) && (info1 == PICODATA_ITEMINFO1_CMD_FLUSH)) { + tok->outBuf[tok->outWritePos++] = itemType; + tok->outBuf[tok->outWritePos++] = info1; + tok->outBuf[tok->outWritePos++] = info2; + tok->outBuf[tok->outWritePos++] = 0; + } + else if (tok->ignLevel <= 0) { + switch (itemType) { + case PICODATA_ITEM_CMD: + switch (info1) { + case PICODATA_ITEMINFO1_CMD_CONTEXT: + case PICODATA_ITEMINFO1_CMD_VOICE: + case PICODATA_ITEMINFO1_CMD_MARKER: + case PICODATA_ITEMINFO1_CMD_PLAY: + case PICODATA_ITEMINFO1_CMD_SAVE: + case PICODATA_ITEMINFO1_CMD_UNSAVE: + case PICODATA_ITEMINFO1_CMD_PROSDOMAIN: + case PICODATA_ITEMINFO1_CMD_PHONEME: + len = picoos_strlen((picoos_char*)str); + if (tok->outWritePos + 4 + len < OUT_BUF_SIZE) { + tok->outBuf[tok->outWritePos++] = itemType; + tok->outBuf[tok->outWritePos++] = info1; + tok->outBuf[tok->outWritePos++] = info2; + tok->outBuf[tok->outWritePos++] = len; + for (i=0; ioutBuf[tok->outWritePos++] = str[i]; + } + } + else { + PICODBG_WARN(("tok_putItem: output buffer too small")); + } + break; + case PICODATA_ITEMINFO1_CMD_IGNSIG: + case PICODATA_ITEMINFO1_CMD_IGNORE: + if (tok->outWritePos + 4 < OUT_BUF_SIZE) { + tok->outBuf[tok->outWritePos++] = itemType; + tok->outBuf[tok->outWritePos++] = info1; + tok->outBuf[tok->outWritePos++] = info2; + tok->outBuf[tok->outWritePos++] = 0; + } + else { + PICODBG_WARN(("tok_putItem: output buffer too small")); + } + break; + case PICODATA_ITEMINFO1_CMD_SPEED: + case PICODATA_ITEMINFO1_CMD_PITCH: + case PICODATA_ITEMINFO1_CMD_VOLUME: + case PICODATA_ITEMINFO1_CMD_SPELL: + case PICODATA_ITEMINFO1_CMD_SIL: + case PICODATA_ITEMINFO1_CMD_SPEAKER: + if (tok->outWritePos + 4 + 2 < OUT_BUF_SIZE) { + tok->outBuf[tok->outWritePos++] = itemType; + tok->outBuf[tok->outWritePos++] = info1; + tok->outBuf[tok->outWritePos++] = info2; + tok->outBuf[tok->outWritePos++] = 2; + tok->outBuf[tok->outWritePos++] = val % 256; + tok->outBuf[tok->outWritePos++] = val / 256; + } + else { + PICODBG_WARN(("tok_putItem: output buffer too small")); + } + break; + default: + PICODBG_WARN(("tok_putItem: unknown command type")); + } + break; + case PICODATA_ITEM_TOKEN: + len = picoos_strlen((picoos_char*)str); + if (tok->outWritePos + 4 + len < OUT_BUF_SIZE) { + tok->outBuf[tok->outWritePos++] = itemType; + tok->outBuf[tok->outWritePos++] = info1; + tok->outBuf[tok->outWritePos++] = info2; + tok->outBuf[tok->outWritePos++] = len; + for (i=0; ioutBuf[tok->outWritePos++] = str[i]; + } + } + else { + PICODBG_WARN(("tok_putItem: output buffer too small")); + } + break; + default: + PICODBG_WARN(("tok_putItem: unknown item type")); + } + } +} + + +static void tok_putItem2 (picodata_ProcessingUnit this, tok_subobj_t * tok, + picoos_uint8 type, + picoos_uint8 info1, picoos_uint8 info2, + picoos_uint8 len, + picoos_uint8 data[]) +{ + picoos_int32 i; + + if (is_valid_itemtype(type)) { + tok->outBuf[tok->outWritePos++] = type; + tok->outBuf[tok->outWritePos++] = info1; + tok->outBuf[tok->outWritePos++] = info2; + tok->outBuf[tok->outWritePos++] = len; + for (i=0; ioutBuf[tok->outWritePos++] = data[i]; + } + } +} + + +static MarkupId tok_markupTagId (picoos_uchar tagId[]) +{ + if (picoos_strstr(tagId,(picoos_char *)"svox:") == (picoos_char *)tagId) { + tagId+=5; + } + if (tok_strEqual(tagId, TOK_MARKUP_KW_IGNORE)) { + return MIIgnore; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_SPEED)) { + return MISpeed; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_PITCH)) { + return MIPitch; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_VOLUME)) { + return MIVolume; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_SPEAKER)) { + return MISpeaker; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_VOICE)) { + return MIVoice; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_CONTEXT)) { + return MIPreprocContext; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_MARK)) { + return MIMarker; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_PLAY)) { + return MIPlay; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_USESIG)) { + return MIUseSig; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_GENFILE)) { + return MIGenFile; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_SENTENCE) || tok_strEqual(tagId, TOK_MARKUP_KW_S)) { + return MISentence; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_PARAGRAPH) || tok_strEqual(tagId, TOK_MARKUP_KW_P)) { + return MIParagraph; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_BREAK)) { + return MIBreak; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_SPELL)) { + return MISpell; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_PHONEME)) { + return MIPhoneme; + } else if (tok_strEqual(tagId, TOK_MARKUP_KW_ITEM)) { + return MIItem; + } else { + return MIDummyEnd; + } +} + + +extern void tok_checkLimits (picodata_ProcessingUnit this, picoos_uint32 * value, picoos_uint32 min, picoos_uint32 max, picoos_uchar valueType[]) +{ + if ((((*value) < min) || ((*value) > max))) { + picoos_emRaiseWarning(this->common->em, PICO_ERR_MARKUP_VALUE_OUT_OF_RANGE, (picoos_char*)"", (picoos_char*)"attempt to set illegal value %i for %s", *value, valueType); + if (((*value) < min)) { + (*value) = min; + } else if (((*value) > max)) { + (*value) = max; + } + } +} + + + +extern void tok_checkRealLimits (picodata_ProcessingUnit this, picoos_single * value, picoos_single min, picoos_single max, picoos_uchar valueType[]) +{ + if ((((*value) < min) || ((*value) > max))) { + picoos_emRaiseWarning(this->common->em, PICO_ERR_MARKUP_VALUE_OUT_OF_RANGE, (picoos_char*)"", (picoos_char*)"attempt to set illegal value %f for %s", *value, valueType); + if (((*value) < min)) { + (*value) = min; + } else if (((*value) > max)) { + (*value) = max; + } + } +} + + +#define VAL_STR_LEN 21 + +static void tok_interpretMarkup (picodata_ProcessingUnit this, tok_subobj_t * tok, picoos_bool isStartTag, MarkupId mId) +{ + picoos_bool done; + picoos_int32 ival; + picoos_uint32 uval; + picoos_int32 ival2; + picoos_uchar valStr[VAL_STR_LEN]; + picoos_uchar valStr2[VAL_STR_LEN]; + picoos_uchar valStr3[VAL_STR_LEN]; + picoos_int32 i2; + picoos_uint32 dur; + picoos_bool done1; + picoos_bool paramFound; + picoos_uint8 type, info1, info2; + picoos_uint8 data[256]; + picoos_int32 pos, n, len; + picoos_uchar part[10]; + + done = FALSE; + switch (mId) { + case MIIgnore: + if (isStartTag && tok_strEqual(tok->markupParams[0].paramId,(picoos_uchar*)"")) { + tok_startIgnore(tok); + done = TRUE; + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { + tok_endIgnore(tok); + done = TRUE; + } + break; + case MISpeed: + if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWLevel)) { + if (tok_isRelative(tok->markupParams[0].paramVal, & uval)) { + tok_checkLimits(this, & uval, PICO_SPEED_FACTOR_MIN, PICO_SPEED_FACTOR_MAX,(picoos_uchar*)"relative speed factor"); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPEED, PICODATA_ITEMINFO2_CMD_RELATIVE, uval, (picoos_uchar*)""); + } else { + uval = picoos_atoi((picoos_char*)tok->markupParams[0].paramVal); + tok_checkLimits(this, & uval, PICO_SPEED_MIN, PICO_SPEED_MAX,(picoos_uchar*)"speed"); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPEED, PICODATA_ITEMINFO2_CMD_ABSOLUTE, uval, (picoos_uchar*)""); + } + done = TRUE; + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPEED, PICODATA_ITEMINFO2_CMD_ABSOLUTE, PICO_SPEED_DEFAULT, (picoos_uchar*)""); + done = TRUE; + } + break; + case MIPitch: + if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWLevel)) { + if (tok_isRelative(tok->markupParams[0].paramVal, & uval)) { + tok_checkLimits(this, & uval,PICO_PITCH_FACTOR_MIN,PICO_PITCH_FACTOR_MAX, (picoos_uchar*)"relative pitch factor"); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PITCH, PICODATA_ITEMINFO2_CMD_RELATIVE, uval, (picoos_uchar*)""); + } else { + uval = picoos_atoi((picoos_char*)tok->markupParams[0].paramVal); + tok_checkLimits(this, & uval,PICO_PITCH_MIN,PICO_PITCH_MAX, (picoos_uchar*)"pitch"); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PITCH,PICODATA_ITEMINFO2_CMD_ABSOLUTE, uval, (picoos_uchar*)""); + } + done = TRUE; + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PITCH,PICODATA_ITEMINFO2_CMD_ABSOLUTE, PICO_PITCH_DEFAULT, (picoos_uchar*)""); + done = TRUE; + } + break; + case MIVolume: + if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWLevel)) { + if (tok_isRelative(tok->markupParams[0].paramVal, & uval)) { + tok_checkLimits(this, & uval, PICO_VOLUME_FACTOR_MIN, PICO_VOLUME_FACTOR_MAX, (picoos_uchar*)"relative volume factor"); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_VOLUME, PICODATA_ITEMINFO2_CMD_RELATIVE, uval, (picoos_uchar*)""); + } else { + uval = picoos_atoi((picoos_char*)tok->markupParams[0].paramVal); + tok_checkLimits(this, & uval, PICO_VOLUME_MIN, PICO_VOLUME_MAX, (picoos_uchar*)"volume"); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_VOLUME, PICODATA_ITEMINFO2_CMD_ABSOLUTE, uval, (picoos_uchar*)""); + } + done = TRUE; + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_VOLUME, PICODATA_ITEMINFO2_CMD_ABSOLUTE, PICO_VOLUME_DEFAULT, (picoos_uchar*)""); + done = TRUE; + } + break; + case MISpeaker: + if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWLevel)) { + if (tok_isRelative(tok->markupParams[0].paramVal, & uval)) { + tok_checkLimits(this, & uval, PICO_SPEAKER_FACTOR_MIN, PICO_SPEAKER_FACTOR_MAX, (picoos_uchar*)"relative speaker factor"); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPEAKER, PICODATA_ITEMINFO2_CMD_RELATIVE, uval, (picoos_uchar*)""); + } else { + uval = picoos_atoi((picoos_char*)tok->markupParams[0].paramVal); + tok_checkLimits(this, & uval, PICO_SPEAKER_MIN, PICO_SPEAKER_MAX, (picoos_uchar*)"volume"); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPEAKER, PICODATA_ITEMINFO2_CMD_ABSOLUTE, uval, (picoos_uchar*)""); + } + done = TRUE; + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPEAKER, PICODATA_ITEMINFO2_CMD_ABSOLUTE, PICO_SPEAKER_DEFAULT, (picoos_uchar*)""); + done = TRUE; + } + break; + + case MIVoice: + if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWName)) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_VOICE, PICODATA_ITEMINFO2_NA, 0, tok->markupParams[0].paramVal); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PROSDOMAIN, 0, 0, (picoos_uchar*)""); + done = TRUE; + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId,(picoos_uchar*)"")) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_VOICE, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PROSDOMAIN, 0, 0, (picoos_uchar*)""); + done = TRUE; + } + break; + case MIPreprocContext: + if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWName)) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_CONTEXT, PICODATA_ITEMINFO2_NA, 0, tok->markupParams[0].paramVal); + done = TRUE; + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId,(picoos_uchar*)"")) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_CONTEXT, PICODATA_ITEMINFO2_NA, 0, PICO_CONTEXT_DEFAULT); + done = TRUE; + } + break; + case MIMarker: + if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWName)) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_MARKER, PICODATA_ITEMINFO2_NA, 0, tok->markupParams[0].paramVal); + done = TRUE; + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId,(picoos_uchar*)"")) { + done = TRUE; + } + break; + case MISentence: + if (isStartTag) { + tok_getParamStrVal(tok->markupParams, KWProsDomain, (picoos_uchar*)valStr, & paramFound); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PROSDOMAIN, 2, 0, valStr); + done = TRUE; + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PROSDOMAIN, 2, 0, (picoos_uchar*)""); + done = TRUE; + } + break; + case MIParagraph: + if (isStartTag) { + tok_getParamStrVal(tok->markupParams, KWProsDomain, (picoos_uchar*)valStr, & paramFound); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PROSDOMAIN, 1, 0, valStr); + done = TRUE; + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SIL, PICODATA_ITEMINFO2_NA, PARAGRAPH_PAUSE_DUR, (picoos_uchar*)""); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PROSDOMAIN, 1, 0, (picoos_uchar*)""); + done = TRUE; + } + break; + case MIBreak: + if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWTime)) { + tok_getDur(tok->markupParams[0].paramVal, & dur, & done1); + tok_checkLimits (this, &dur, 0, 65535, (picoos_uchar*)"time"); + if (done1) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SIL, PICODATA_ITEMINFO2_NA, dur, (picoos_uchar*)""); + done = TRUE; + } + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { + done = TRUE; + } + break; + case MISpell: + if (isStartTag) { + if (tok_strEqual(tok->markupParams[0].paramId, KWMode)) { + if (tok_strEqual(tok->markupParams[0].paramVal, KWPB)) { + uval = SPELL_WITH_PHRASE_BREAK; + } else if (tok_strEqual(tok->markupParams[0].paramVal, KWSB)) { + uval = SPELL_WITH_SENTENCE_BREAK; + } else { + tok_getDur(tok->markupParams[0].paramVal, & uval, & done1); + tok_checkLimits (this, & uval, 0, 65535, (picoos_uchar*)"time"); + if (done1) { + done = TRUE; + } + } + } else { + uval = SPELL_WITH_PHRASE_BREAK; + } + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPELL, PICODATA_ITEMINFO2_CMD_START, uval, (picoos_uchar*)""); + done = TRUE; + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SPELL, PICODATA_ITEMINFO2_CMD_END, 0, (picoos_uchar*)""); + done = TRUE; + } + break; + case MIGenFile: + if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWFile)) { + if (tok->saveFile[0] != 0) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_UNSAVE, + picodata_getPuTypeFromExtension(tok->saveFile, /*input*/FALSE), 0, tok->saveFile); + tok->saveFile[0] = 0; + } + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_SAVE, + picodata_getPuTypeFromExtension(tok->markupParams[0].paramVal, /*input*/FALSE), 0, tok->markupParams[0].paramVal); + picoos_strcpy((picoos_char*)tok->saveFile, (picoos_char*)tok->markupParams[0].paramVal); + done = TRUE; + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { + if (tok->saveFile[0] != 0) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_UNSAVE, + picodata_getPuTypeFromExtension(tok->saveFile, /*input*/FALSE), 0, (picoos_uchar*)""); + tok->saveFile[0] = 0; + } + done = TRUE; + } + break; + case MIPlay: + if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWFile)) { + if (picoos_FileExists(this->common, (picoos_char*)tok->markupParams[0].paramVal)) { + tok_getParamIntVal(tok->markupParams,KWF0Beg,& ival,& paramFound); + tok_getParamIntVal(tok->markupParams,KWF0End,& ival2,& paramFound); + tok_getParamStrVal(tok->markupParams,KWAlphabet,valStr3,& paramFound); + tok_getParamPhonesStr(tok->markupParams,KWXFadeBeg,valStr3,valStr,VAL_STR_LEN,& paramFound); + tok_getParamPhonesStr(tok->markupParams,KWXFadeEnd,valStr3,valStr2,VAL_STR_LEN,& paramFound); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PLAY, + picodata_getPuTypeFromExtension(tok->markupParams[0].paramVal, /*input*/TRUE), 0, tok->markupParams[0].paramVal); + tok_startIgnore(tok); + } else { + if (tok->ignLevel > 0) { + tok_startIgnore(tok); + } else { + picoos_emRaiseWarning(this->common->em, PICO_EXC_CANT_OPEN_FILE, (picoos_char*)"", (picoos_char*)"file '%s' not found; synthesizing enclosed text instead\n", tok->markupParams[0].paramVal); + } + } + done = TRUE; + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { + tok_endIgnore(tok); + done = TRUE; + } + break; + case MIUseSig: + if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWFile)) { + if (picoos_FileExists(this->common, (picoos_char*)tok->markupParams[0].paramVal)) { + tok_getParamIntVal(tok->markupParams,KWF0Beg,& ival,& paramFound); + tok_getParamIntVal(tok->markupParams,KWF0End,& ival2,& paramFound); + tok_getParamStrVal(tok->markupParams,KWAlphabet,valStr3, & paramFound); + tok_getParamPhonesStr(tok->markupParams,KWXFadeBeg,valStr3,valStr,VAL_STR_LEN,& paramFound); + tok_getParamPhonesStr(tok->markupParams,KWXFadeEnd,valStr3,valStr2,VAL_STR_LEN,& paramFound); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PLAY, + picodata_getPuTypeFromExtension(tok->markupParams[0].paramVal, /*input*/TRUE), 0, tok->markupParams[0].paramVal); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_IGNSIG, PICODATA_ITEMINFO2_CMD_START, 0, (picoos_uchar*)""); + } else { + if (tok->ignLevel <= 0) { + picoos_emRaiseWarning(this->common->em, PICO_EXC_CANT_OPEN_FILE, (picoos_char*)"", (picoos_char*)"file '%s' not found; synthesizing enclosed text instead", tok->markupParams[0].paramVal); + } + } + done = TRUE; + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_IGNSIG, PICODATA_ITEMINFO2_CMD_END, 0, (picoos_uchar*)""); + done = TRUE; + } + break; + case MIPhoneme: + i2 = 0; + if (isStartTag) { + if (tok_strEqual(tok->markupParams[0].paramId, KWAlphabet) && tok_strEqual(tok->markupParams[1].paramId, KWPH)) { + if (tok_strEqual(tok->markupParams[2].paramId, KWOrthMode) + && tok_strEqual(tok->markupParams[2].paramVal, KWIgnorePunct)) { + i2 = 1; + } + if (picodata_mapPAStrToPAIds(tok->transducer, this->common, tok->xsampa_parser, tok->svoxpa_parser, tok->xsampa2svoxpa_mapper, tok->markupParams[1].paramVal, tok->markupParams[0].paramVal, tok->phonemes, sizeof(tok->phonemes)-1) == PICO_OK) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PHONEME, + PICODATA_ITEMINFO2_CMD_START, i2, tok->phonemes); + done = TRUE; + } else { + PICODBG_WARN(("cannot map phonetic string '%s'; synthesizeing text instead", tok->markupParams[1].paramVal)); + picoos_emRaiseWarning(this->common->em, PICO_ERR_MARKUP_VALUE_OUT_OF_RANGE,(picoos_char*)"", (picoos_char*)"cannot map phonetic string '%s'; synthesizeing text instead", tok->markupParams[1].paramVal); + done = TRUE; + } + } else if (tok_strEqual(tok->markupParams[0].paramId, KWPH)) { + if (tok_strEqual(tok->markupParams[1].paramId, KWOrthMode) + && tok_strEqual(tok->markupParams[1].paramVal, KWIgnorePunct)) { + i2 = 1; + } + if (picodata_mapPAStrToPAIds(tok->transducer, this->common, tok->xsampa_parser, tok->svoxpa_parser, tok->xsampa2svoxpa_mapper, tok->markupParams[0].paramVal, PICODATA_XSAMPA, tok->phonemes, sizeof(tok->phonemes)) == PICO_OK) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PHONEME, + PICODATA_ITEMINFO2_CMD_START, i2, tok->phonemes); + done = TRUE; + } + else { + PICODBG_WARN(("cannot map phonetic string '%s'; synthesizeing text instead", tok->markupParams[1].paramVal)); + picoos_emRaiseWarning(this->common->em, PICO_ERR_MARKUP_VALUE_OUT_OF_RANGE,(picoos_char*)"", (picoos_char*)"cannot map phonetic string '%s'; synthesizing text instead", tok->markupParams[0].paramVal); + done = TRUE; + } + } + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId, (picoos_uchar*)"")) { + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_PHONEME, + PICODATA_ITEMINFO2_CMD_END, i2, (picoos_uchar*)""); + done = TRUE; + } + break; + case MIItem: + if (isStartTag && tok_strEqual(tok->markupParams[0].paramId, KWType) && + tok_strEqual(tok->markupParams[1].paramId, KWInfo1)&& + tok_strEqual(tok->markupParams[2].paramId, KWInfo2)&& + tok_strEqual(tok->markupParams[3].paramId, KWDATA)) { + picoos_int32 len2, n2; + type = picoos_atoi(tok->markupParams[0].paramVal); + info1 = picoos_atoi(tok->markupParams[1].paramVal); + info2 = picoos_atoi(tok->markupParams[2].paramVal); + n = 0; n2 = 0; + len2 = (picoos_int32)picoos_strlen(tok->markupParams[3].paramVal); + while (nmarkupParams[3].paramVal[n] != 0) && (tok->markupParams[3].paramVal[n] <= 32)) { + n++; + } + tok->markupParams[3].paramVal[n2] = tok->markupParams[3].paramVal[n]; + n++; + n2++; + } + if (is_valid_itemtype(type)) { + done = TRUE; + len = 0; + pos = 0; + picoos_get_sep_part_str(tok->markupParams[3].paramVal, picoos_strlen(tok->markupParams[3].paramVal), + &pos, ',', part, 10, &done1); + while (done && done1) { + n = picoos_atoi(part); + if ((n>=0) && (n<256) && (len<256)) { + data[len++] = n; + } + else { + done = FALSE; + } + picoos_get_sep_part_str(tok->markupParams[3].paramVal, picoos_strlen(tok->markupParams[3].paramVal), + &pos, ',', part, 10, &done1); + } + if (done) { + tok_putItem2(this, tok, type, info1, info2, len, data); + } + } + else { + done = FALSE; + } + } else if (!isStartTag && tok_strEqual(tok->markupParams[0].paramId,(picoos_uchar*)"")) { + done = TRUE; + } + break; + default: + break; + } + if (!done) { + tok->markupTagErr = MEInterprete; + } + if (isStartTag) { + tok->markupLevel[mId]++; + } else if ((tok->markupLevel[mId] > 0)) { + tok->markupLevel[mId]--; + } +} + + +static picoos_bool tok_attrChar (picoos_uchar ch, picoos_bool first) +{ + return ((((ch >= (picoos_uchar)'A') && (ch <= (picoos_uchar)'Z')) || + ((ch >= (picoos_uchar)'a') && (ch <= (picoos_uchar)'z'))) || + ( !(first) && ((ch >= (picoos_uchar)'0') && (ch <= (picoos_uchar)'9')))); +} + + + +static picoos_bool tok_idChar (picoos_uchar ch, picoos_bool first) +{ + return tok_attrChar(ch, first) || ( !(first) && (ch == (picoos_uchar)':')); +} + + +static void tok_setIsFileAttr (picoos_uchar name[], picoos_bool * isFile) +{ + (*isFile) = tok_strEqual(name, KWFile); +} + +/* *****************************************************************************/ + +static void tok_putToSimpleToken (picodata_ProcessingUnit this, tok_subobj_t * tok, picoos_uchar str[], pico_tokenType type, pico_tokenSubType subtype) +{ + int i, len; + + if (str[0] != 0) { + len = picoos_strlen((picoos_char*)str); + for (i = 0; i < len; i++) { + if (tok->tokenPos >= IN_BUF_SIZE) { + picoos_emRaiseWarning(this->common->em, PICO_ERR_INTERNAL_LIMIT, (picoos_char*)"", (picoos_char*)"simple token too long; forced treatment"); + tok_treatSimpleToken(this, tok); + } + tok->tokenStr[tok->tokenPos] = str[i]; + tok->tokenPos++; + } + } + tok->tokenType = type; + tok->tokenSubType = subtype; +} + + +static void tok_putToMarkup (picodata_ProcessingUnit this, tok_subobj_t * tok, picoos_uchar str[]) +{ + picoos_int32 i, len; + picoos_uint8 ok; + + tok->markupTagErr = MENone; + len = picoos_strlen((picoos_char*)str); + for (i = 0; i< len; i++) { + if (tok->markupPos >= (MARKUP_STRING_BUF_SIZE - 1)) { + if ((tok->markupPos == (MARKUP_STRING_BUF_SIZE - 1)) && (tok_markupTagId(tok->markupTagName) != MIDummyEnd)) { + picoos_emRaiseWarning(this->common->em, PICO_ERR_INTERNAL_LIMIT ,(picoos_char*)"", (picoos_char*)"markup tag too long"); + } + tok->markupState = MSErrorTooLong; + } else if ((str[i] == (picoos_uchar)' ') && ((tok->markupState == MSExpectingmarkupTagName) || (tok->markupState == MSGotmarkupTagName) || (tok->markupState == MSGotAttrName) || (tok->markupState == MSGotEqual) || (tok->markupState == MSGotAttrValue))) { + } else if ((str[i] == (picoos_uchar)'>') && ((tok->markupState == MSGotmarkupTagName) || (tok->markupState == MSInmarkupTagName) || (tok->markupState == MSGotAttrValue))) { + tok->markupState = MSGotEnd; + } else if ((str[i] == (picoos_uchar)'/') && ((tok->markupState == MSGotmarkupTagName) || (tok->markupState == MSInmarkupTagName) || (tok->markupState == MSGotAttrValue))) { + if (tok->markupTagType == MTEnd) { + tok->markupTagErr = MEUnexpectedChar; + tok->markupState = MSError; + } else { + tok->markupTagType = MTEmpty; + tok->markupState = MSGotEndSlash; + } + } else { + switch (tok->markupState) { + case MSNotInMarkup: + if (str[i] == (picoos_uchar)'<') { + tok_clearMarkupParams(tok->markupParams); + tok->nrMarkupParams = 0; + tok->strPos = 0; + tok->markupTagType = MTStart; + tok->markupState = MSGotStart; + } else { + tok->markupTagErr = MEMissingStart; + tok->markupState = MSError; + } + break; + case MSGotStart: + if (str[i] == (picoos_uchar)'/') { + tok->markupTagType = MTEnd; + tok->markupState = MSExpectingmarkupTagName; + } else if (str[i] == (picoos_uchar)' ') { + tok->markupState = MSExpectingmarkupTagName; + } else if (tok_idChar(str[i],TRUE)) { + tok->markupTagType = MTStart; + tok->markupTagName[tok->strPos] = str[i]; + tok->strPos++; + tok->markupTagName[tok->strPos] = 0; + tok->markupState = MSInmarkupTagName; + } else { + tok->markupTagErr = MEUnexpectedChar; + tok->markupState = MSError; + } + break; + case MSInmarkupTagName: case MSExpectingmarkupTagName: + if (tok_idChar(str[i],tok->markupState == MSExpectingmarkupTagName)) { + tok->markupTagName[tok->strPos] = str[i]; + tok->strPos++; + tok->markupTagName[(tok->strPos)] = 0; + tok->markupState = MSInmarkupTagName; + } else if ((tok->markupState == MSInmarkupTagName) && (str[i] == (picoos_uchar)' ')) { + tok->markupState = MSGotmarkupTagName; + picobase_lowercase_utf8_str(tok->markupTagName, (picoos_char*)tok->markupTagName, IN_BUF_SIZE, &ok); + tok->strPos = 0; + } else { + tok->markupTagErr = MEIdent; + tok->markupState = MSError; + } + break; + case MSGotmarkupTagName: case MSGotAttrValue: + if (tok_attrChar(str[i], TRUE)) { + if (tok->markupTagType == MTEnd) { + tok->markupTagErr = MEUnexpectedChar; + tok->markupState = MSError; + } else { + if (tok->nrMarkupParams < MAX_NR_MARKUP_PARAMS) { + tok->markupParams[tok->nrMarkupParams].paramId[tok->strPos] = str[i]; + tok->strPos++; + tok->markupParams[tok->nrMarkupParams].paramId[tok->strPos] = 0; + } else { + picoos_emRaiseWarning(this->common->em, PICO_ERR_INTERNAL_LIMIT ,(picoos_char*)"", (picoos_char*)"too many attributes in markup; ignoring"); + } + tok->markupState = MSInAttrName; + } + } else { + tok->markupTagErr = MEUnexpectedChar; + tok->markupState = MSError; + } + break; + case MSInAttrName: + if (tok_attrChar(str[i], FALSE)) { + if (tok->nrMarkupParams < MAX_NR_MARKUP_PARAMS) { + tok->markupParams[tok->nrMarkupParams].paramId[tok->strPos] = str[i]; + tok->strPos++; + tok->markupParams[tok->nrMarkupParams].paramId[tok->strPos] = 0; + } + tok->markupState = MSInAttrName; + } else if (str[i] == (picoos_uchar)' ') { + picobase_lowercase_utf8_str(tok->markupParams[tok->nrMarkupParams].paramId, (picoos_char*)tok->markupParams[tok->nrMarkupParams].paramId, IN_BUF_SIZE, &ok); + tok_setIsFileAttr(tok->markupParams[tok->nrMarkupParams].paramId, & tok->isFileAttr); + tok->markupState = MSGotAttrName; + } else if (str[i] == (picoos_uchar)'=') { + picobase_lowercase_utf8_str(tok->markupParams[tok->nrMarkupParams].paramId, (picoos_char*)tok->markupParams[tok->nrMarkupParams].paramId, IN_BUF_SIZE, &ok); + tok_setIsFileAttr(tok->markupParams[tok->nrMarkupParams].paramId, & tok->isFileAttr); + tok->markupState = MSGotEqual; + } else { + tok->markupTagErr = MEMissingEqual; + tok->markupState = MSError; + } + break; + case MSGotAttrName: + if (str[i] == (picoos_uchar)'=') { + tok->markupState = MSGotEqual; + } else { + tok->markupTagErr = MEMissingEqual; + tok->markupState = MSError; + } + break; + case MSGotEqual: + if ((str[i] == (picoos_uchar)'"') || (str[i] == (picoos_uchar)'\'')) { + tok->strDelim = str[i]; + tok->strPos = 0; + tok->markupState = MSInAttrValue; + } else { + tok->markupTagErr = MEMissingQuote; + tok->markupState = MSError; + } + break; + case MSInAttrValue: + if (!(tok->isFileAttr) && (str[i] == (picoos_uchar)'\\')) { + tok->markupState = MSInAttrValueEscaped; + } else if (str[i] == tok->strDelim) { + if (tok->nrMarkupParams < MAX_NR_MARKUP_PARAMS) { + tok->nrMarkupParams++; + } + tok->strPos = 0; + tok->markupState = MSGotAttrValue; + } else { + if (tok->nrMarkupParams < MAX_NR_MARKUP_PARAMS) { + tok->markupParams[tok->nrMarkupParams].paramVal[tok->strPos] = str[i]; + tok->strPos++; + tok->markupParams[tok->nrMarkupParams].paramVal[tok->strPos] = 0; + } + tok->markupState = MSInAttrValue; + } + break; + case MSInAttrValueEscaped: + if (tok->nrMarkupParams < MAX_NR_MARKUP_PARAMS) { + tok->markupParams[tok->nrMarkupParams].paramVal[tok->strPos] = str[i]; + tok->strPos++; + tok->markupParams[tok->nrMarkupParams].paramVal[tok->strPos] = 0; + } + tok->markupState = MSInAttrValue; + break; + case MSGotEndSlash: + if (str[i] == (picoos_uchar)'>') { + tok->markupState = MSGotEnd; + } else { + tok->markupTagErr = MEUnexpectedChar; + tok->markupState = MSError; + } + break; + default: + tok->markupTagErr = MEUnexpectedChar; + tok->markupState = MSError; + break; + } + } + tok->markupStr[tok->markupPos] = str[i]; + tok->markupPos++; + tok->markupStr[tok->markupPos] = 0; + } + /* + PICODBG_DEBUG(("putToMarkup %s", tok->markupStr)); + */ +} + +/* *****************************************************************************/ + +static void tok_treatMarkupAsSimpleToken (picodata_ProcessingUnit this, tok_subobj_t * tok) +{ + picoos_int32 i; + + tok->utfpos = 0; + tok->utflen = 0; + tok->markupState = MSNotInMarkup; + for (i = 0; i < tok->markupPos; i++) { + tok_treatChar(this, tok, tok->markupStr[i], FALSE); + } + tok->markupPos = 0; + tok->strPos = 0; +} + + +static void tok_treatMarkup (picodata_ProcessingUnit this, tok_subobj_t * tok) +{ + MarkupId mId; + + if (tok_markupTagId(tok->markupTagName) != MIDummyEnd) { + if (tok->markupTagErr == MENone) { + tok->markupState = MSNotInMarkup; + if ((tok->tokenType != PICODATA_ITEMINFO1_TOKTYPE_SPACE) && (tok->tokenType != PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED)) { + tok_treatSimpleToken(this, tok); + } + tok_putToSimpleToken(this, tok, (picoos_uchar*)" ", PICODATA_ITEMINFO1_TOKTYPE_SPACE, -1); + mId = tok_markupTagId(tok->markupTagName); + if ((tok->markupTagType == MTStart) || (tok->markupTagType == MTEmpty)) { + tok_interpretMarkup(this, tok, TRUE, mId); + } + if (((tok->markupTagType == MTEnd) || (tok->markupTagType == MTEmpty))) { + tok_clearMarkupParams(tok->markupParams); + tok->nrMarkupParams = 0; + tok_interpretMarkup(this, tok, FALSE,mId); + } + } + if (tok->markupTagErr != MENone) { + if (!tok->aborted) { + picoos_emRaiseWarning(this->common->em, PICO_ERR_INVALID_MARKUP_TAG, (picoos_char*)"", (picoos_char*)"syntax error in markup token '%s'",tok->markupStr); + } + tok_treatMarkupAsSimpleToken(this, tok); + } + } else { + tok_treatMarkupAsSimpleToken(this, tok); + } + tok->markupState = MSNotInMarkup; + tok->markupPos = 0; + tok->strPos = 0; +} + + + +static void tok_treatChar (picodata_ProcessingUnit this, tok_subobj_t * tok, picoos_uchar ch, picoos_bool markupHandling) +{ + picoos_int32 id; + picoos_uint8 uval8; + pico_tokenType type = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; + pico_tokenSubType subtype = -1; + picoos_bool dummy; + + if (ch == NULLC) { + tok_treatSimpleToken(this, tok); + tok_putItem(this, tok, PICODATA_ITEM_CMD, PICODATA_ITEMINFO1_CMD_FLUSH, PICODATA_ITEMINFO2_NA, 0, (picoos_uchar*)""); + } + else { + switch (tok_putToUtf(tok, ch)) { + case UTF_CHAR_MALFORMED: + tok->utfpos = 0; + tok->utflen = 0; + break; + case UTF_CHAR_INCOMPLETE: + break; + case UTF_CHAR_COMPLETE: + markupHandling = (markupHandling && (tok->markupHandlingMode == MARKUP_HANDLING_ENABLED)); + id = picoktab_graphOffset(tok->graphTab, tok->utf); + if (id > 0) { + if (picoktab_getIntPropTokenType(tok->graphTab, id, &uval8)) { + type = (pico_tokenType)uval8; + if (type == PICODATA_ITEMINFO1_TOKTYPE_LETTERV) { + type = PICODATA_ITEMINFO1_TOKTYPE_LETTER; + } + } + dummy = picoktab_getIntPropTokenSubType(tok->graphTab, id, &subtype); + } else if (ch <= (picoos_uchar)' ') { + type = PICODATA_ITEMINFO1_TOKTYPE_SPACE; + subtype = -1; + } else { + type = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; + subtype = -1; + } + if ((ch > (picoos_uchar)' ')) { + tok->nrEOL = 0; + } else if ((ch == EOL)) { + tok->nrEOL++; + } + if (markupHandling && (tok->markupState != MSNotInMarkup)) { + tok_putToMarkup(this, tok, tok->utf); + if (tok->markupState >= MSError) { + tok_treatMarkupAsSimpleToken(this, tok); + } else if (tok->markupState == MSGotEnd) { + tok_treatMarkup(this, tok); + } + } else if ((markupHandling && (ch == (picoos_uchar)'<'))) { + tok_putToMarkup(this, tok, tok->utf); + } else if (type != PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED) { + if ((type != tok->tokenType) || (type == PICODATA_ITEMINFO1_TOKTYPE_CHAR) || (subtype != tok->tokenSubType)) { + tok_treatSimpleToken(this, tok); + } else if ((ch == EOL) && (tok->nrEOL == 2)) { + tok_treatSimpleToken(this, tok); + tok_putToSimpleToken(this, tok, (picoos_uchar*)".", PICODATA_ITEMINFO1_TOKTYPE_CHAR, -1); + tok_treatSimpleToken(this, tok); + } + tok_putToSimpleToken(this, tok, tok->utf, type, subtype); + } else { + tok_treatSimpleToken(this, tok); + } + tok->utfpos = 0; + tok->utflen = 0; + break; + } + } +} + + +static void tok_treatSimpleToken (picodata_ProcessingUnit this, tok_subobj_t * tok) +{ + if (tok->tokenPos < IN_BUF_SIZE) { + tok->tokenStr[tok->tokenPos] = 0; + } + if (tok->markupState != MSNotInMarkup) { + if (!(tok->aborted) && (tok->markupState >= MSGotmarkupTagName) && (tok_markupTagId(tok->markupTagName) != MIDummyEnd)) { + picoos_emRaiseWarning(this->common->em, PICO_ERR_INVALID_MARKUP_TAG, (picoos_char*)"", (picoos_char*)"unfinished markup tag '%s'",tok->markupStr); + } + tok_treatMarkupAsSimpleToken(this, tok); + tok_treatSimpleToken(this, tok); + } else if ((tok->tokenPos > 0) && ((tok->ignLevel <= 0) || (tok->tokenType == PICODATA_ITEMINFO1_TOKTYPE_SPACE))) { + tok_putItem(this, tok, PICODATA_ITEM_TOKEN, tok->tokenType, (picoos_uint8)tok->tokenSubType, 0, tok->tokenStr); + } + tok->tokenPos = 0; + tok->tokenType = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; + tok->tokenSubType = -1; +} + +/* *****************************************************************************/ + +static pico_status_t tokReset(register picodata_ProcessingUnit this) +{ + tok_subobj_t * tok; + MarkupId mId; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + tok = (tok_subobj_t *) this->subObj; + + tok->ignLevel = 0; + + tok->utfpos = 0; + tok->utflen = 0; + + tok_clearMarkupParams(tok->markupParams); + tok->nrMarkupParams = 0; + tok->markupState = MSNotInMarkup; + tok->markupPos = 0; + for (mId = MIDummyStart; mId <= MIDummyEnd; mId++) { + tok->markupLevel[mId] = 0; + } + tok->markupTagName[0] = 0; + tok->markupTagType = MTNone; + tok->markupTagErr = MENone; + + tok->strPos = 0; + tok->strDelim = 0; + tok->isFileAttr = FALSE; + + tok->tokenType = PICODATA_ITEMINFO1_TOKTYPE_UNDEFINED; + tok->tokenSubType = -1; + tok->tokenPos = 0; + + tok->nrEOL = 0; + + + tok->markupHandlingMode = TRUE; + tok->aborted = FALSE; + + tok->start = TRUE; + + tok->outReadPos = 0; + tok->outWritePos = 0; + + tok->saveFile[0] = 0; + + + tok->graphTab = picoktab_getGraphs(this->voice->kbArray[PICOKNOW_KBID_TAB_GRAPHS]); + + tok->xsampa_parser = picokfst_getFST(this->voice->kbArray[PICOKNOW_KBID_FST_XSAMPA_PARSE]); + PICODBG_TRACE(("got xsampa_parser @ %i",tok->xsampa_parser)); + + tok->svoxpa_parser = picokfst_getFST(this->voice->kbArray[PICOKNOW_KBID_FST_SVOXPA_PARSE]); + PICODBG_TRACE(("got svoxpa_parser @ %i",tok->svoxpa_parser)); + + tok->xsampa2svoxpa_mapper = picokfst_getFST(this->voice->kbArray[PICOKNOW_KBID_FST_XSAMPA2SVOXPA]); + PICODBG_TRACE(("got xsampa2svoxpa_mapper @ %i",tok->xsampa2svoxpa_mapper)); + + + + return PICO_OK; +} + +static pico_status_t tokInitialize(register picodata_ProcessingUnit this) +{ +/* + + tok_subobj_t * tok; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + tok = (tok_subobj_t *) this->subObj; +*/ + return tokReset(this); +} + + +static pico_status_t tokTerminate(register picodata_ProcessingUnit this) +{ + return PICO_OK; +} + +static picodata_step_result_t tokStep(register picodata_ProcessingUnit this, picoos_int16 mode, picoos_uint16 * numBytesOutput); + +static pico_status_t tokSubObjDeallocate(register picodata_ProcessingUnit this, + picoos_MemoryManager mm) +{ + + if (NULL != this) { + picoos_deallocate(this->common->mm, (void *) &this->subObj); + } + mm = mm; /* avoid warning "var not used in this function"*/ + return PICO_OK; +} + +picodata_ProcessingUnit picotok_newTokenizeUnit(picoos_MemoryManager mm, picoos_Common common, + picodata_CharBuffer cbIn, picodata_CharBuffer cbOut, + picorsrc_Voice voice) +{ + tok_subobj_t * tok; + picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, cbOut, voice); + if (this == NULL) { + return NULL; + } + this->initialize = tokInitialize; + PICODBG_DEBUG(("set this->step to tokStep")); + this->step = tokStep; + this->terminate = tokTerminate; + this->subDeallocate = tokSubObjDeallocate; + this->subObj = picoos_allocate(mm, sizeof(tok_subobj_t)); + if (this->subObj == NULL) { + picoos_deallocate(mm, (void *)&this); + return NULL; + } + tok = (tok_subobj_t *) this->subObj; + tok->transducer = picotrns_newSimpleTransducer(mm, common, 10*(PICOTRNS_MAX_NUM_POSSYM+2)); + if (NULL == tok->transducer) { + tokSubObjDeallocate(this,mm); + picoos_deallocate(mm, (void *)&this); + return NULL; + } + tokInitialize(this); + return this; +} + +/** + * fill up internal buffer, try to locate token, write token to output + */ +picodata_step_result_t tokStep(register picodata_ProcessingUnit this, + picoos_int16 mode, picoos_uint16 * numBytesOutput) +{ + register tok_subobj_t * tok; + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + tok = (tok_subobj_t *) this->subObj; + + mode = mode; /* avoid warning "var not used in this function"*/ + + *numBytesOutput = 0; + while (1) { /* exit via return */ + picoos_int16 ch; + + if ((tok->outWritePos - tok->outReadPos) > 0) { + if (picodata_cbPutItem(this->cbOut, &tok->outBuf[tok->outReadPos], tok->outWritePos - tok->outReadPos, numBytesOutput) == PICO_OK) { + PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], + (picoos_uint8 *)"tok:", &tok->outBuf[tok->outReadPos], tok->outWritePos - tok->outReadPos); + tok->outReadPos += *numBytesOutput; + if (tok->outWritePos == tok->outReadPos) { + tok->outWritePos = 0; + tok->outReadPos = 0; + } + } + else { + return PICODATA_PU_OUT_FULL; + } + + } + else if (PICO_EOF != (ch = picodata_cbGetCh(this->cbIn))) { + PICODBG_DEBUG(("read in %c", (picoos_char) ch)); + tok_treatChar(this, tok, (picoos_uchar) ch, /*markupHandling*/TRUE); + } + else { + return PICODATA_PU_IDLE; + } + } +} + +#ifdef __cplusplus +} +#endif + +/* end */ diff --git a/pico/lib/picotok.h b/pico/lib/picotok.h new file mode 100644 index 0000000..b602408 --- /dev/null +++ b/pico/lib/picotok.h @@ -0,0 +1,115 @@ +/* + * 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 picotok.h + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + + +/** @addtogroup picotok +itemtype, iteminfo1, iteminfo2, content -> TYPE(INFO1,INFO2)content +in the following + +input +===== + +- UTF8 text + +limitations: currently only german umlauts in addition to ASCII + + +minimal input size (before processing starts) +================== + +processing (ie. tokenization) starts when +- 'PICO_EOF' char received (which happens whenever the cbIn buffer is empty) +- tok-internal buffer is full + + +items output +============ + +processing the character stream can result in one of the +following items: +-> WORDGRAPH(NA,NA)graph <- mapped to lower case; incl. 1-2 digit nrs (0-99) +-> OTHER(NA,NA)string <- skip or spell +-> PUNC(PUNCtype,PUNCsubtype) +-> CMD(CMDtype,CMDsubtype)args + +with +- PUNCtype %d + PICODATA_ITEMINFO1_PUNC_SENTEND + PICODATA_ITEMINFO1_PUNC_PHRASEEND +- PUNCsubtype %d + PICODATA_ITEMINFO2_PUNC_SENT_T + PICODATA_ITEMINFO2_PUNC_SENT_Q + PICODATA_ITEMINFO2_PUNC_SENT_E + PICODATA_ITEMINFO2_PUNC_PHRASE + (used later: PICODATA_ITEMINFO2_PUNC_PHRASE_FORCED) +- CMDtype %d + PICODATA_ITEMINFO1_CMD_FLUSH (no args) + ? PICODATA_ITEMINFO1_CMD_PLAY ? (not yet) +- CMDsubtype %d + PICODATA_ITEMINFO2_NA + ? PICODATA_ITEMINFO2_CMD_PLAY_G2P ? (not yet) +- graph, len>0, utf8 graphemes, %s +- string, len>0, can be any string with printable ascii characters, %s + + +other limitations +================= + +- item size: header plus len=256 (valid for Pico in general) + */ + + +#ifndef PICOTOK_H_ +#define PICOTOK_H_ + +#include "picoos.h" +#include "picodata.h" +#include "picorsrc.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + + +picodata_ProcessingUnit picotok_newTokenizeUnit( + picoos_MemoryManager mm, + picoos_Common common, + picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, + picorsrc_Voice voice); + +#define PICOTOK_OUTBUF_SIZE 256 + +#ifdef __cplusplus +} +#endif + + +#endif /*PICOTOK_H_*/ diff --git a/pico/lib/picotrns.c b/pico/lib/picotrns.c new file mode 100644 index 0000000..2d16340 --- /dev/null +++ b/pico/lib/picotrns.c @@ -0,0 +1,745 @@ +/* + * 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 picotrns.c + * + * fst processing + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#include "picoos.h" +#include "picodbg.h" +/* #include "picodata.h" */ +/* #include "picoknow.h" */ +#include "picoktab.h" +#include "picokfst.h" +#include "picotrns.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + + +picoos_uint8 picotrns_unplane(picoos_int16 symIn, picoos_uint8 * plane) { + if (symIn < 0) { + (*plane) = 0; + return (picoos_uint8) symIn; + } else { + (*plane) = symIn >> 8; + return (picoos_uint8) (symIn & 0xFF); + } +} + +#if defined(PICO_DEBUG) + +void PICOTRNS_PRINTSYM1(picoknow_KnowledgeBase kbdbg, picoos_int16 insym, picoos_uint8 phonemic) +{ +#include "picokdbg.h" + picoos_int16 sym; + picoos_uint8 plane; + picokdbg_Dbg dbg = (NULL == kbdbg) ? NULL : picokdbg_getDbg(kbdbg); + sym = picotrns_unplane(insym, &plane); + switch (plane) { + case PICOKFST_PLANE_PHONEMES: /* phones */ + if ((NULL == dbg) || !phonemic) { + PICODBG_INFO_MSG((" %c", sym)); + } else { + PICODBG_INFO_MSG((" %s", picokdbg_getPhoneSym(dbg, (picoos_uint8) sym))); + } + break; + case PICOKFST_PLANE_ACCENTS: /* accents */ + PICODBG_INFO_MSG((" {A%c}", sym)); + break; + case PICOKFST_PLANE_XSAMPA: /* xsampa symbols */ + PICODBG_INFO_MSG((" {XS:(%i)}", sym)); + break; + case PICOKFST_PLANE_POS: /* part of speech */ + PICODBG_INFO_MSG((" {P:%d}", sym)); + break; + case PICOKFST_PLANE_PB_STRENGTHS: /* phrases */ + if (sym == 48) { + PICODBG_INFO_MSG((" {WB}", sym)); + } else if (sym == 115) { + PICODBG_INFO_MSG((" {P0}", sym)); + } else { + PICODBG_INFO_MSG((" {P%c}", sym)); + } + break; + case PICOKFST_PLANE_INTERN: /* intern */ + PICODBG_INFO_MSG((" [%c]", sym)); + break; + } +} + +void PICOTRNS_PRINTSYM(picoknow_KnowledgeBase kbdbg, picoos_int16 insym) +{ + PICOTRNS_PRINTSYM1(kbdbg,insym,1); +} + +void PICOTRNS_PRINTSYMSEQ1(picoknow_KnowledgeBase kbdbg, const picotrns_possym_t seq[], const picoos_uint16 seqLen, + picoos_uint8 phonemic) { + picoos_uint16 i; + for (i=0; i= maxOutSeqLen) { + return PICO_EXC_BUF_OVERFLOW; + } + /* let j skip consonant cluster */ + accent = 0; + accentpos = 0; + while ((j < inSeqLen) && !picoktab_isSyllCarrier(phones,(picoos_uint8)inSeq[j].sym)) { + if ((inSeq[j].sym == picoktab_getPrimstressID(phones)) + || (inSeq[j].sym == picoktab_getPrimstressID(phones))) { + PICODBG_TRACE(("j skipping stress symbol inSeq[%i].sym = %c", j, inSeq[j].sym)); + accent = inSeq[j].sym; + accentpos = j; + } else { + PICODBG_TRACE(("j skipping consonant inSeq[%i].sym = %c", j, inSeq[j].sym)); + } + j++; + } + if (j < inSeqLen) { /* j is at the start of a new vowel */ + /* copy consonant cluster (moving i) to output, insert syll separator if between vowels */ + while (i < j-1) { + if ((accent > 0) && (i == accentpos)) { + PICODBG_TRACE(("skipping inSeq[%i].sym = %c (stress)", i, inSeq[i].sym)); + i++; + } else { + PICODBG_TRACE(("copying inSeq[%i].sym = %c (consonant) into output buffer", i, inSeq[i].sym)); + outSeq[out++] = inSeq[i++]; + } + } + if (vowelFound) { /* we're between vowels */ + PICODBG_TRACE(("inserting syllable separator into output buffer")); + insertSym(outSeq,out++,picoktab_getSyllboundID(phones)); + if (accent > 0) { + insertSym(outSeq,out++,accent); + } + numInserted++; + } + if ((accent > 0) && (i == accentpos)) { + PICODBG_TRACE(("skipping inSeq[%i].sym = %c (stress)", i, inSeq[i].sym)); + i++; + } else { + PICODBG_TRACE(("copying inSeq[%i].sym = %c (consonant) into output buffer", i, inSeq[i].sym)); + outSeq[out++] = inSeq[i++]; + } + vowelFound = TRUE; + /* now copy vowel cluster */ + while ((i < inSeqLen) && picoktab_isSyllCarrier(phones,(picoos_uint8)inSeq[i].sym)) { + PICODBG_TRACE(("copying inSeq[%i].sym = %c (vowel) into output buffer", i, inSeq[i].sym)); + outSeq[out++] = inSeq[i++]; + } + j = i; + } else { /* j is at end of word or end of input */ + while (i < j) { + PICODBG_TRACE(("copying inSeq[%i].sym = %c (consonant or stress) into output buffer", i, inSeq[i].sym)); + outSeq[out++] = inSeq[i++]; + } + } + *outSeqLen = out; + } + PICODBG_ASSERT((out == inSeqLen + numInserted)); + + return PICO_OK; +} + + +/* ******** +CT+: full transduction procedure **********/ + + +/* Gets next acceptable alternative for output symbol '*outSym' at current recursion position + starting from previous alternative in 'altDesc'; possibly uses input symbol + given by 'inSeq'/'inSeq'; returns whether alterative was found in '*found'; + if '*found', the other output values ('*outRefPos', '*endFSTstate', '*nextInPos'*) + return the characteristics for next recursion step; + if '*found' is false, the output values are undefined. */ + +static void GetNextAlternative (picokfst_FST fst, picotrns_AltDesc altDesc, + const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen, + picokfst_symid_t * outSym, picoos_int32 * outRefPos, + picokfst_state_t * endFSTState, picoos_int32 * nextInPos, picoos_bool * found) +{ + + picoos_bool inSymFound; + picoos_bool pairFound; + picokfst_class_t pairClass; + picoos_bool inEpsTransFound; + picokfst_symid_t inSym; + + (*found) = 0; + do { + switch (altDesc->altState) { + case 0: /* before pair search */ + if (altDesc->inPos < inSeqLen) { + inSym = inSeq[altDesc->inPos].sym; + if (inSym == PICOKFST_SYMID_EPS) { + /* very special case: input epsilon simply produces eps in output + without fst state change */ + (*found) = 1; + (*outSym) = PICOKFST_SYMID_EPS; + (*outRefPos) = inSeq[altDesc->inPos].pos; + (*endFSTState) = altDesc->startFSTState; + (*nextInPos) = altDesc->inPos + 1; + altDesc->altState = 2; + } else { + /* start search for alternatives using input symbol */ + picokfst_kfstStartPairSearch(fst,inSeq[altDesc->inPos].sym,& inSymFound,& altDesc->searchState); + if (!inSymFound) { + altDesc->altState = 2; + PICODBG_INFO_CTX(); + PICODBG_INFO_MSG((" didnt find symbol ")); + PICOTRNS_PRINTSYM(NULL, inSeq[altDesc->inPos].sym); + PICODBG_INFO_MSG(("\n")); + + } else { + altDesc->altState = 1; + } + } + } else { + altDesc->altState = 2; + } + break; + case 1: /* within pair search */ + picokfst_kfstGetNextPair(fst,& altDesc->searchState,& pairFound,& (*outSym),& pairClass); + if (pairFound) { + picokfst_kfstGetTrans(fst,altDesc->startFSTState,pairClass,& (*endFSTState)); + if ((*endFSTState) > 0) { + (*found) = 1; + (*outRefPos) = inSeq[altDesc->inPos].pos; + (*nextInPos) = altDesc->inPos + 1; + } + } else { + /* no more pair found */ + altDesc->altState = 2; + } + break; + case 2: /* before inEps trans search */ + picokfst_kfstStartInEpsTransSearch(fst,altDesc->startFSTState,& inEpsTransFound,& altDesc->searchState); + if (inEpsTransFound) { + altDesc->altState = 3; + } else { + altDesc->altState = 4; + } + break; + case 3: /* within inEps trans search */ + picokfst_kfstGetNextInEpsTrans(fst,& altDesc->searchState,& inEpsTransFound,& (*outSym),& (*endFSTState)); + if (inEpsTransFound) { + (*found) = 1; + (*outRefPos) = PICOTRNS_POS_INSERT; + (*nextInPos) = altDesc->inPos; + } else { + altDesc->altState = 4; + } + break; + case 4: /* no more alternatives */ + break; + } + } while (! ((*found) || (altDesc->altState == 4)) ); /* i.e., until (*found) || (altState == 4) */ +} + + + +/* Transfers current alternatives path stored in 'altDesc' with current path length 'pathLen' + into 'outSeq'/'outSeqLen'. The number of solutions is incremented. */ + +static void NoteSolution (picoos_uint32 * nrSol, picotrns_printSolutionFct printSolution, + picotrns_altDesc_t altDesc[], picoos_uint16 pathLen, + picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen) +{ + register picotrns_AltDesc ap; + picoos_uint32 i; + + (*nrSol)++; + (*outSeqLen) = 0; + for (i = 0; i < pathLen; i++) { + if (i < maxOutSeqLen) { + ap = &altDesc[i]; + outSeq[i].sym = ap->altOutSym; + outSeq[i].pos = ap->altOutRefPos; + (*outSeqLen)++; + } + } + if (pathLen > maxOutSeqLen) { + PICODBG_WARN(("**** output symbol array too small to hold full solution\n")); + } + if (printSolution != NULL) { + printSolution(outSeq,(*outSeqLen)); + } +} + + + +/* * + general scheme to get all solutions ("position" refers to abstract backtracking recursion depth, + which in the current solution is equal to the output symbol position): + + "set position to first position"; + "initialize alternatives in first position"; + REPEAT + IF "current state in current position is a solution" THEN + "note solution"; + END; + "get first or next acceptable alternative in current position"; + IF "acceptable alternative found" THEN + "note alternative"; + "go to next position"; + "initialize alternatives in that position"; + ELSE + "step back to previous position"; + END; + UNTIL "current position is before first position" +***/ + + +/* Initializes transduction state for further use in repeated application + of 'TransductionStep'. */ + +static void StartTransduction (struct picotrns_transductionState * transductionState) +{ + (*transductionState).phase = 0; +} + + + +/* Performs one step in the transduction of 'inSeqLen' input symbols with corresponding + reference positions in 'inSeq'. '*transductionState' must have been + initialized by 'StartTransduction'. Repeat calls to this procedure until '*finished' returns true. + The output is returned in 'outSeqLen' symbols and reference positions in 'outSeq'. + The output reference positions refer to the corresponding input reference positions. + Inserted output symbols receive the reference position -1. If several solutions are possible, + only the last found solution is returned. + 'altDesc' is a temporary workspace which should be at least one cell longer than 'outSeq'. + 'firstSolOnly' determines whether only the first solution should be found or if + the search should go on to find all solutions (mainly for testing purposes). + + NOTE: current version written for use in single repetitive steps; + could be simplified if full transduction can be done as an atomic operation */ + +static void TransductionStep (picokfst_FST fst, struct picotrns_transductionState * transductionState, + picotrns_altDesc_t altDesc[], picoos_uint16 maxAltDescLen, + picoos_bool firstSolOnly, picotrns_printSolutionFct printSolution, + const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen, + picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen, + picoos_bool * finished) +{ + register picotrns_AltDesc ap; + picoos_int32 i; + picokfst_state_t endFSTState; + picoos_int32 nextInPos; + picoos_bool found; + picokfst_symid_t outSym; + picoos_int32 outRefPos; + picoos_int32 tmpRecPos; + + (*finished) = 0; + tmpRecPos = (*transductionState).recPos; + switch ((*transductionState).phase) { + case 0: /* before initialization */ + (*transductionState).nrSol = 0; + + /* check for initial solution (empty strings are always accepted) */ + if (inSeqLen == 0) { + NoteSolution(& (*transductionState).nrSol,printSolution,altDesc,0,outSeq,outSeqLen,maxOutSeqLen); + } + + /* initialize first recursion position */ + tmpRecPos = 0; + ap = & altDesc[0]; + ap->startFSTState = 1; + ap->inPos = 0; + ap->altState = 0; + (*transductionState).phase = 1; + break; + + case 1: /* before regular recursion step */ + if ((tmpRecPos < 0) || (firstSolOnly && ((*transductionState).nrSol > 0))) { + /* end reached */ + (*transductionState).phase = 2; + } else { + /* not finished; do regular step */ + + /* get first or next acceptable alternative in current position */ + GetNextAlternative(fst,& altDesc[tmpRecPos],inSeq,inSeqLen,& outSym,& outRefPos,& endFSTState,& nextInPos,& found); + if (found) { + /* note alternative in current position */ + ap = & altDesc[tmpRecPos]; + ap->altOutSym = outSym; + ap->altOutRefPos = outRefPos; + + /* check for solution after found alternative */ + if ((nextInPos == inSeqLen) && picokfst_kfstIsAcceptingState(fst,endFSTState)) { + NoteSolution(& (*transductionState).nrSol,printSolution,altDesc,tmpRecPos+1, + outSeq,outSeqLen,maxOutSeqLen); + } + + /* go to next position if possible, start search for follower alternative symbols */ + if (tmpRecPos < maxAltDescLen-1) { + /* got to next position */ + tmpRecPos = tmpRecPos + 1; + + /* initialize alternatives in new position */ + ap = & altDesc[tmpRecPos]; + ap->startFSTState = endFSTState; + ap->inPos = nextInPos; + ap->altState = 0; + + } else { + /* do not go on due to limited path but still treat alternatives in current position */ + PICODBG_WARN(("--- transduction path too long; may fail to find solution\n")); + } + } else { /* no more acceptable alternative found in current position */ + /* backtrack to previous recursion */ + tmpRecPos = tmpRecPos - 1; + } + } + break; + + case 2: /* before finish */ + if ((*transductionState).nrSol == 0) { + PICODBG_WARN(("--- no transduction solution found, using input as output\n")); + i = 0; + while ((i < inSeqLen) && (i < maxOutSeqLen)) { + outSeq[i].sym = inSeq[i].sym; + outSeq[i].pos = inSeq[i].pos; + i++; + } + (*outSeqLen) = i; + } else if ((*transductionState).nrSol > 1) { + PICODBG_WARN(("--- more than one transducer solutions found\n")); + } + (*transductionState).phase = 3; + break; + + case 3: /* after finish */ + (*finished) = 1; + break; + } + (*transductionState).recPos = tmpRecPos; +} + + + +/* see description in header */ +pico_status_t picotrns_transduce (picokfst_FST fst, picoos_bool firstSolOnly, + picotrns_printSolutionFct printSolution, + const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen, + picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen, + picotrns_AltDesc altDescBuf, picoos_uint16 maxAltDescLen, + picoos_uint32 *nrSteps) +{ + struct picotrns_transductionState transductionState; + picoos_bool finished; + +#if defined(PICO_DEBUG) + { + picoos_uint16 i; + + PICODBG_INFO_CTX(); + PICODBG_INFO_MSG(("got input: ")); + for (i=0; ipossymBuf = transducer->possymBufA; + transducer->possymBufTmp = transducer->possymBufB; + transducer->possymReadPos = 0; + transducer->possymWritePos = 0; + return PICO_OK; +} +/** creates a SimpleTranducer with a working buffer of given size + * + * @param mm MemoryManager handle + * @param common Common handle + * @param maxAltDescLen maximal size for working buffer (in bytes) + * @return handle to new SimpleTransducer or NULL if error + */ +picotrns_SimpleTransducer picotrns_newSimpleTransducer(picoos_MemoryManager mm, + picoos_Common common, + picoos_uint16 maxAltDescLen) +{ + picotrns_SimpleTransducer this; + this = picoos_allocate(mm, sizeof(picotrns_simple_transducer_t)); + if (this == NULL) { + picoos_deallocate(mm, (void *)&this); + picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); + return NULL; + } + + /* allocate working buffer */ + this->altDescBuf = picotrns_allocate_alt_desc_buf(mm, maxAltDescLen, &this->maxAltDescLen); + if (this->altDescBuf == NULL) { + picoos_deallocate(mm, (void *)&this); + picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); + return NULL; + } + this->common = common; + picotrns_stInitialize(this); + return this; +} +/** disposes a SimpleTransducer + * + * @param this + * @param mm + * @return PICO_OK + */ +pico_status_t picotrns_disposeSimpleTransducer(picotrns_SimpleTransducer * this, + picoos_MemoryManager mm) +{ + if (NULL != (*this)) { + picotrns_deallocate_alt_desc_buf(mm,&(*this)->altDescBuf); + picoos_deallocate(mm, (void *) this); + (*this) = NULL; + } + return PICO_OK; +} + +/** transduces the contents previously inserted via @ref picotrns_newSimpleTransducer and @ref + * picotrns_disposeSimpleTransducer. + * + * @param this + * @param fst + * @return + */ +pico_status_t picotrns_stTransduce(picotrns_SimpleTransducer this, picokfst_FST fst) +{ + picoos_uint16 outSeqLen; + picoos_uint32 nrSteps; + pico_status_t status; + + status = picotrns_transduce(fst,TRUE,NULL, + this->possymBuf, this->possymWritePos, + this->possymBufTmp,&outSeqLen, PICOTRNS_MAX_NUM_POSSYM, + this->altDescBuf,this->maxAltDescLen,&nrSteps); + if (PICO_OK != status) { + return status; + } + return picotrns_eliminate_epsilons(this->possymBufTmp,outSeqLen,this->possymBuf,&this->possymWritePos,PICOTRNS_MAX_NUM_POSSYM); +} + +/** + * Add chars from NULLC-terminated string \c inStr, shifted to plane \c plane, to internal input buffer of + * \c transducer. + * + * @param this is an initialized picotrns_SimpleTransducer + * @param inStr NULLC-terminated byte sequence + * @param plane + * @return PICO_OK, if all bytes fit into buffer, or PICO_EXC_BUF_OVERFLOW otherwise + */ +pico_status_t picotrns_stAddWithPlane(picotrns_SimpleTransducer this, picoos_char * inStr, picoos_uint8 plane) +{ + while ((*inStr) && (this->possymWritePos < PICOTRNS_MAX_NUM_POSSYM)) { + this->possymBuf[this->possymWritePos].pos = PICOTRNS_POS_INSERT; + this->possymBuf[this->possymWritePos].sym = (plane << 8) + (*inStr); + PICODBG_DEBUG(("inserting pos/sym = %i/'%c' at pos %i", + this->possymBuf[this->possymWritePos].pos, + this->possymBuf[this->possymWritePos].sym, + this->possymWritePos)); + this->possymWritePos++; + inStr++; + } + if (!(*inStr)) { + return PICO_OK; + } else { + return PICO_EXC_BUF_OVERFLOW; + } +} + +pico_status_t picotrns_stGetSymSequence( + picotrns_SimpleTransducer this, + picoos_uint8 * outputSymIds, + picoos_uint32 maxOutputSymIds) +{ + picoos_uint8 plane; + picoos_uint32 outputCount = 0; + while ((this->possymReadPos < this->possymWritePos) && (outputCount < maxOutputSymIds)) { + *outputSymIds++ = picotrns_unplane(this->possymBuf[this->possymReadPos++].sym, &plane); + outputCount++; + } + *outputSymIds = NULLC; + if (outputCount <= maxOutputSymIds) { + return PICO_OK; + } else { + return PICO_EXC_BUF_OVERFLOW; + } +} + +#ifdef __cplusplus +} +#endif + +/* end picotrns.c */ diff --git a/pico/lib/picotrns.h b/pico/lib/picotrns.h new file mode 100644 index 0000000..f535ce0 --- /dev/null +++ b/pico/lib/picotrns.h @@ -0,0 +1,191 @@ +/* + * 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 picotrns.h + * + * fst processing + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +/** @addtogroup picotrns + * + * Conventions: + * + * - The input to the transducer is a list of pos/sym pairs, where pos are arbitrary position markers + * - All positions are allowed on input (in particular all those coming as an output of a previous transduction) + * - A phone sequence to be transduced has to begin with PICOKNOW_PHON_START_ID and end with PICOKNOW_PHON_TERM_ID + * These special symbols are kept in the transduction output (as first and last symbol) + * - Symbols inserted by the transduction process allways get their position marker pos=PICOTRNS_POS_INSERT + * - The order of positions on output must be the same as that on input, i.e. apart from inserted pairs, the + * output position sequence must be a sub-sequence of the input position sequence. + * - Inserted symbols are allways preceded by a positioned pos/sym pair, e.g. + * if the sequence pos1/sym1, pos2/sym2 should be tranduced to x/sym3, y/sym4, z/sym5, then x must be pos1 or pos2 + * and not PICOTRNS_POS_INSERT + * + * For lingware developers: Insertions are always interpreted "to the right" + * - E.g.: The original sequence is phon1 , command , phon2 + * - The input to the transducer is then pos1/phon1 , pos2/phon2 + * - The output is pos1/phon1' -1/phon_ins pos2/phon2' [assuming -1 is the special insertion pos] + * - Then the new sequence will be recomposed as phon1' , phon_ins , command , phon2' [note position of command!] + * - To overwrite this behaviour, rules must be formulated such that the transduction output is + * pos1/phon1' pos2/phon_ins -1/phon2' + */ +#ifndef PICOTRNS_H_ +#define PICOTRNS_H_ + +#include "picoos.h" +#include "picokfst.h" +#include "picoktab.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +#define PICOTRNS_MAX_NUM_POSSYM 255 + +#define PICOTRNS_POS_INSERT (picoos_int16) -1 /* position returned by transducer to mark symbols inserted by the transducer */ +#define PICOTRNS_POS_INVALID (picoos_int16) -2 /* value to mark an invalid (e.g. uninitiated) position */ +#define PICOTRNS_POS_IGNORE (picoos_int16) -3 /* value to mark a pos/sym pair to be ignored (e.g. start/term symbols only used by the transducer) */ + + +typedef struct picotrns_possym { + picoos_int16 pos; + picoos_int16 sym; +} picotrns_possym_t; + +picoos_uint8 picotrns_unplane(picoos_int16 symIn, picoos_uint8 * plane); + + +#if defined(PICO_DEBUG) + +void PICOTRNS_PRINTSYM(picoknow_KnowledgeBase kbdbg, picoos_int16 insym); + +void PICOTRNS_PRINTSYMSEQ(picoknow_KnowledgeBase kbdbg, const picotrns_possym_t seq[], const picoos_uint16 seqLen); + +void picotrns_printSolution(const picotrns_possym_t outSeq[], const picoos_uint16 outSeqLen); + +#else +#define PICOTRNS_PRINTSYM(x,y) +#define PICOTRNS_PRINTSYMSEQ(x,y,z) +#define picotrns_printSolution NULL +#endif + + +typedef struct picotrns_altDesc * picotrns_AltDesc; + + +picotrns_AltDesc picotrns_allocate_alt_desc_buf(picoos_MemoryManager mm, picoos_uint32 maxByteSize, picoos_uint16 * numAltDescs); + +void picotrns_deallocate_alt_desc_buf(picoos_MemoryManager mm, picotrns_AltDesc * altDescBuf); + + +/* type of function for printing transduction solutions; + only for testing purposes in transduction mode where all solutions + are produced */ +typedef void picotrns_printSolutionFct(const picotrns_possym_t outSeq[], const picoos_uint16 outSeqLen); + + + +/** overall transduction; transduces 'inSeq' with 'inSeqLen' elements + to '*outSeqLen' elements in 'outSeq'; + * + * @param fst the finite-state transducer used for transduction + * @param firstSolOnly determines whether only the first solution (usually) + or all solutions should be produced (for testing); only the last found + solution is returned in 'outSeq'; + * @param printSolution if not NULL, every found solution is displayed using + the given function + * @param inSeq the input sequence + * @param inSeqLen the input sequence length + * @retval outSeq the output sequence + * @retval outSeqLen the output sequence length + * @param maxOutSeqLen must provide the maximum length of 'outSeq' + * @param altDescBuf must provide a working array of length 'maxAltDescLen' + * @param maxAltDescLen should be chosen at least 'maxOutSeqLen' + 1 + * @retval nrSteps returns the overall internal number of iterative steps done + * @return status of the transduction: PICO_OK, if transduction successful + @note if 'outSeq' or 'altDesc' are too small to hold a solution, + an error occurs and the input is simply transfered to the output + (up to maximum possible length) + */ +extern pico_status_t picotrns_transduce (picokfst_FST fst, picoos_bool firstSolOnly, + picotrns_printSolutionFct printSolution, + const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen, + picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen, + picotrns_AltDesc altDescBuf, picoos_uint16 maxAltDescLen, + picoos_uint32 *nrSteps); + + + +/* transduce 'inSeq' into 'outSeq' 'inSeq' has to be terminated with the id for symbol '#'. 'outSeq' is terminated in the same way. */ +/* +pico_status_t picotrns_transduce_sequence(picokfst_FST fst, const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen, + picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen); +*/ + +/* copy elements from inSeq to outSeq, ignoring elements with epsilon symbol */ +pico_status_t picotrns_eliminate_epsilons(const picotrns_possym_t inSeq[], picoos_uint16 inSeqLen, + picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen); + +/* copy elements from inSeq to outSeq, inserting syllable separators in some trivial way. + * inSeq is assumed to be at most, outSeq at least of size PICOTRNS_MAX_NUM_POSSYM */ +pico_status_t picotrns_trivial_syllabify(picoktab_Phones phones, + const picotrns_possym_t inSeq[], const picoos_uint16 inSeqLen, + picotrns_possym_t outSeq[], picoos_uint16 * outSeqLen, picoos_uint16 maxOutSeqLen); + + +/** object : SimpleTransducer + * shortcut : st + * + */ +typedef struct picotrns_simple_transducer * picotrns_SimpleTransducer; + +picotrns_SimpleTransducer picotrns_newSimpleTransducer(picoos_MemoryManager mm, + picoos_Common common, + picoos_uint16 maxAltDescLen); + +pico_status_t picotrns_disposeSimpleTransducer(picotrns_SimpleTransducer * this, + picoos_MemoryManager mm); + +pico_status_t picotrns_stInitialize(picotrns_SimpleTransducer transducer); + +pico_status_t picotrns_stAddWithPlane(picotrns_SimpleTransducer this, picoos_char * inStr, picoos_uint8 plane); + +pico_status_t picotrns_stTransduce(picotrns_SimpleTransducer this, picokfst_FST fst); + +pico_status_t picotrns_stGetSymSequence( + picotrns_SimpleTransducer this, + picoos_uint8 * outputSymIds, + picoos_uint32 maxOutputSymIds); + + + + + +#ifdef __cplusplus +} +#endif + +#endif /*PICOTRNS_H_*/ diff --git a/pico/lib/picowa.c b/pico/lib/picowa.c new file mode 100644 index 0000000..3e793c9 --- /dev/null +++ b/pico/lib/picowa.c @@ -0,0 +1,578 @@ +/* + * 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 picowa.c + * + * word analysis PU - lexicon lookup and POS prediction + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#include "picoos.h" +#include "picodbg.h" +#include "picodata.h" +#include "picowa.h" +#include "picoklex.h" +#include "picokdt.h" +#include "picoktab.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/* PU waStep states */ +#define WA_STEPSTATE_COLLECT 0 +#define WA_STEPSTATE_PROCESS 1 +#define WA_STEPSTATE_FEED 2 + + +/* subobject : WordAnaUnit + * shortcut : wa + * context size : one item + */ +typedef struct wa_subobj { + picoos_uint8 procState; /* for next processing step decision */ + + /* one item only */ + picoos_uint8 inBuf[PICOWA_MAXITEMSIZE]; /* internal input buffer */ + picoos_uint16 inBufSize; /* actually allocated size */ + picoos_uint16 inLen; /* length of item in inBuf, 0 for empty buf */ + + picoos_uint8 outBuf[PICOWA_MAXITEMSIZE]; /* internal output buffer */ + picoos_uint16 outBufSize; /* actually allocated size */ + picoos_uint16 outLen; /* length of item in outBuf, 0 for empty buf */ + + /* lex knowledge base */ + picoklex_Lex lex; + + /* ulex knowledge bases */ + picoos_uint8 numUlex; + picoklex_Lex ulex[PICOKNOW_MAX_NUM_ULEX]; + + /* tab knowledge base */ + picoktab_Pos tabpos; + + /* dtposp knowledge base */ + picokdt_DtPosP dtposp; +} wa_subobj_t; + + +static pico_status_t waInitialize(register picodata_ProcessingUnit this) { + picoos_uint8 i; + picoklex_Lex ulex; + wa_subobj_t * wa; + + picoknow_kb_id_t ulexKbIds[PICOKNOW_MAX_NUM_ULEX] = PICOKNOW_KBID_ULEX_ARRAY; + + PICODBG_DEBUG(("calling")); + + if (NULL == this || NULL == this->subObj) { + return (picodata_step_result_t) picoos_emRaiseException(this->common->em, + PICO_ERR_NULLPTR_ACCESS, NULL, NULL); + } + wa = (wa_subobj_t *) this->subObj; + wa->procState = WA_STEPSTATE_COLLECT; + wa->inBufSize = PICOWA_MAXITEMSIZE; + wa->inLen = 0; + wa->outBufSize = PICOWA_MAXITEMSIZE; + wa->outLen = 0; + + /* kb lex */ + wa->lex = picoklex_getLex(this->voice->kbArray[PICOKNOW_KBID_LEX_MAIN]); + if (wa->lex == NULL) { + return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + PICODBG_DEBUG(("got lex")); + + /* kb ulex[] */ + wa->numUlex = 0; + for (i = 0; ivoice->kbArray[ulexKbIds[i]]); + if (NULL != ulex) { + wa->ulex[wa->numUlex++] = ulex; + } + } + PICODBG_DEBUG(("got %i user lexica", wa->numUlex)); + + /* kb tabpos */ + wa->tabpos = + picoktab_getPos(this->voice->kbArray[PICOKNOW_KBID_TAB_POS]); + if (wa->tabpos == NULL) { + return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + PICODBG_DEBUG(("got tabpos")); + + /* kb dtposp */ + wa->dtposp = picokdt_getDtPosP(this->voice->kbArray[PICOKNOW_KBID_DT_POSP]); + if (wa->dtposp == NULL) { + return picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + } + PICODBG_DEBUG(("got dtposp")); + return PICO_OK; +} + +static picodata_step_result_t waStep(register picodata_ProcessingUnit this, + picoos_int16 mode, + picoos_uint16 *numBytesOutput); + +static pico_status_t waTerminate(register picodata_ProcessingUnit this) { + return PICO_OK; +} + +static pico_status_t waSubObjDeallocate(register picodata_ProcessingUnit this, + picoos_MemoryManager mm) { + if (NULL != this) { + picoos_deallocate(this->common->mm, (void *) &this->subObj); + } + mm = mm; /* avoid warning "var not used in this function"*/ + return PICO_OK; +} + + +picodata_ProcessingUnit picowa_newWordAnaUnit(picoos_MemoryManager mm, + picoos_Common common, + picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, + picorsrc_Voice voice) { + picodata_ProcessingUnit this; + + this = picodata_newProcessingUnit(mm, common, cbIn, cbOut, voice); + if (this == NULL) { + return NULL; + } + + this->initialize = waInitialize; + PICODBG_DEBUG(("set this->step to waStep")); + this->step = waStep; + this->terminate = waTerminate; + this->subDeallocate = waSubObjDeallocate; + this->subObj = picoos_allocate(mm, sizeof(wa_subobj_t)); + if (this->subObj == NULL) { + picoos_deallocate(mm, (void *)&this); + picoos_emRaiseException(common->em, PICO_EXC_OUT_OF_MEM, NULL, NULL); + return NULL; + } + + waInitialize(this); + return this; +} + +/* ***********************************************************************/ +/* WORDGRAPH proc functions */ +/* ***********************************************************************/ + +static picoos_uint8 waClassifyPos(register picodata_ProcessingUnit this, + register wa_subobj_t *wa, + const picoos_uint8 *graph, + const picoos_uint16 graphlen) { + picokdt_classify_result_t dtres; + picoos_uint8 specchar; + picoos_uint16 i; + + PICODBG_DEBUG(("graphlen %d", graphlen)); + + /* check existence of special char (e.g. hyphen) in graph: + for now, check existence of hard-coded ascii hyphen, + ie. preproc needs to match all UTF8 hyphens to the ascii + hyphen. */ + /* @todo : consider specifying special char(s) in lingware. */ + specchar = FALSE; + i = 0; + while ((i < graphlen) && (!specchar)) { + if (graph[i++] == '-') { + specchar = TRUE; + } + } + + /* construct input vector, which is set in dtposp */ + if (!picokdt_dtPosPconstructInVec(wa->dtposp, graph, graphlen, specchar)) { + /* error constructing invec */ + PICODBG_WARN(("problem with invec")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, NULL, NULL); + return PICODATA_ITEMINFO1_ERR; + } + + /* classify */ + if (!picokdt_dtPosPclassify(wa->dtposp)) { + /* error doing classification */ + PICODBG_WARN(("problem classifying")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, + NULL, NULL); + return PICODATA_ITEMINFO1_ERR; + } + + /* decompose */ + if (!picokdt_dtPosPdecomposeOutClass(wa->dtposp, &dtres)) { + /* error decomposing */ + PICODBG_WARN(("problem decomposing")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_OUTVECTOR, + NULL, NULL); + return PICODATA_ITEMINFO1_ERR; + } + + if (dtres.set) { + PICODBG_DEBUG(("class %d", dtres.class)); + return (picoos_uint8)dtres.class; + } else { + PICODBG_WARN(("result not set")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, + NULL, NULL); + return PICODATA_ITEMINFO1_ERR; + } +} + + +static pico_status_t waProcessWordgraph(register picodata_ProcessingUnit this, + register wa_subobj_t *wa /*inout*/, + picodata_itemhead_t *head /*inout*/, + const picoos_uint8 *content) { + pico_status_t status; + picoklex_lexl_result_t lexres; + picoos_uint8 posbuf[PICOKTAB_MAXNRPOS_IN_COMB]; + picoos_uint8 i; + picoos_uint8 foundIndex; + picoos_bool found; + + + PICODBG_DEBUG(("type %c, len %d", head->type, head->len)); + + /* do lookup + if no entry found: + do POS prediction: -> WORDGRAPH(POSes,NA)graph + else: + if incl-phone: + N entries possible -> WORDINDEX(POSes,NA)POS1|ind1...POSN|indN + (N in {1,...,PICOKLEX_MAX_NRRES}, now up to 4) + else: + no phone, one entry -> WORDGRAPH(POS,NA)graph + */ + + found = FALSE; + i = 0; + while (!found && (i < wa->numUlex)) { + found = picoklex_lexLookup(wa->ulex[i], content, head->len, &lexres); + i++; + } + /* note that if found, i will be incremented nevertheless, so i >= 1 */ + if (found) { + foundIndex = i; + } else { + foundIndex = 0; + } + if (!found && !picoklex_lexLookup(wa->lex, content, head->len, &lexres)) { + /* no lex entry found, WORDGRAPH(POS,NA)graph */ + if (PICO_OK == picodata_copy_item(wa->inBuf, wa->inLen, + wa->outBuf, wa->outBufSize, + &wa->outLen)) { + wa->inLen = 0; + /* predict and modify pos in info1 */ + if (PICO_OK != picodata_set_iteminfo1(wa->outBuf, wa->outLen, + waClassifyPos(this, wa, content, head->len))) { + return picoos_emRaiseException(this->common->em, + PICO_EXC_BUF_OVERFLOW,NULL,NULL); + } + } + + } else { /* at least one entry found */ + PICODBG_DEBUG(("at least one entry found in lexicon %i",foundIndex)); + if (lexres.phonfound) { /* incl. ind-phone and possibly multi-ent. */ + if (lexres.nrres > PICOKLEX_MAX_NRRES) { + /* not possible with system lexicon, needs to be + ensured for user lex too */ + picoos_emRaiseWarning(this->common->em, PICO_WARN_FALLBACK,NULL, + (picoos_char *)"using %d lexicon lookup results", + PICOKLEX_MAX_NRRES); + lexres.nrres = PICOKLEX_MAX_NRRES; + } + head->type = PICODATA_ITEM_WORDINDEX; + if (lexres.nrres == 1) { + head->info1 = lexres.posind[0]; + } else { + /* more than one result, POSgroup info needs to be + determined for later POS disambiguation */ + for (i = 0; i < lexres.nrres; i++) { + posbuf[i] = lexres.posind[i * PICOKLEX_POSIND_SIZE]; + } + head->info1 = picoktab_getPosGroup(wa->tabpos, posbuf, + lexres.nrres); + } + head->info2 = foundIndex; + head->len = lexres.posindlen; + if ((status = picodata_put_itemparts(head, lexres.posind, + lexres.posindlen, + wa->outBuf, wa->outBufSize, + &wa->outLen)) == PICO_OK) { + wa->inLen = 0; + } else { + return picoos_emRaiseException(this->common->em, status, + NULL, NULL); + } + + } else { /* no phone, :G2P, one entry: WORDGRAPH(POS,NA)graph */ + if (PICO_OK == picodata_copy_item(wa->inBuf, wa->inLen, + wa->outBuf, wa->outBufSize, + &wa->outLen)) { + wa->inLen = 0; + /* set lex pos in info1 */ + if (PICO_OK != picodata_set_iteminfo1(wa->outBuf, wa->outLen, + lexres.posind[0])) { + return picoos_emRaiseException(this->common->em, + PICO_EXC_BUF_OVERFLOW, + NULL, NULL); + } + } + } + } + return PICO_OK; +} + + +/* ***********************************************************************/ +/* waStep function */ +/* ***********************************************************************/ + +/* + collect into internal buffer, process, and then feed to output buffer + + init state: COLLECT ext ext + state transitions: in IN OUTout + COLLECT | getOneItem ->-1 +1 0 0 | (ATOMIC) -> PROCESS (got item) + COLLECT | getOneItem -> 0 0 0 0 | IDLE (got no item) + + PROCESS | procOneItem -> 0 -1 +1 0 | (ATOMIC) -> FEED (proc'ed item) + PROCESS | procOneItem -> 0 -1 0 0 | BUSY -> COLLECT (item skipped) + + FEED | putOneItem -> 0 0 -1 +1 | BUSY -> COLLECT (put item) + FEED | putOneItem -> 0 0 1 0 | OUT_FULL (put no item) +*/ + +static picodata_step_result_t waStep(register picodata_ProcessingUnit this, + picoos_int16 mode, + picoos_uint16 * numBytesOutput) { + register wa_subobj_t *wa; + pico_status_t rv = PICO_OK; + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + wa = (wa_subobj_t *) this->subObj; + mode = mode; /* avoid warning "var not used in this function"*/ + *numBytesOutput = 0; + while (1) { /* exit via return */ + PICODBG_DEBUG(("doing state %i, inLen: %d, outLen: %d", + wa->procState, wa->inLen, wa->outLen)); + + switch (wa->procState) { + /* collect state: get item from charBuf and store in + * internal inBuf + */ + case WA_STEPSTATE_COLLECT: + if (wa->inLen == 0) { /* is input buffer empty? */ + picoos_uint16 blen; + /* try to get one item */ + rv = picodata_cbGetItem(this->cbIn, wa->inBuf, + wa->inBufSize, &blen); + PICODBG_DEBUG(("after getting item, status: %d", rv)); + if (PICO_OK == rv) { + /* we now have one item */ + wa->inLen = blen; + wa->procState = WA_STEPSTATE_PROCESS; + /* uncomment next line to split into two steps */ + /* return PICODATA_PU_ATOMIC; */ + } else if (PICO_EOF == rv) { + /* there was no item in the char buffer */ + return PICODATA_PU_IDLE; + } else if ((PICO_EXC_BUF_UNDERFLOW == rv) + || (PICO_EXC_BUF_OVERFLOW == rv)) { + PICODBG_ERROR(("problem getting item")); + picoos_emRaiseException(this->common->em, rv, + NULL, NULL); + return PICODATA_PU_ERROR; + } else { + PICODBG_ERROR(("problem getting item, unhandled")); + picoos_emRaiseException(this->common->em, rv, + NULL, NULL); + return PICODATA_PU_ERROR; + } + } else { /* there already is an item in the input buffer */ + PICODBG_WARN(("item already in input buffer")); + picoos_emRaiseWarning(this->common->em, + PICO_WARN_PU_IRREG_ITEM, NULL, NULL); + wa->procState = WA_STEPSTATE_PROCESS; + /* uncomment next to split into two steps */ + /* return PICODATA_PU_ATOMIC; */ + } + break; + + + /* process state: process item in internal inBuf and put + * result in internal outBuf + */ + case WA_STEPSTATE_PROCESS: + + /* ensure there is an item in inBuf and it is valid */ + if ((wa->inLen > 0) && picodata_is_valid_item(wa->inBuf, + wa->inLen)) { + picodata_itemhead_t ihead; + picoos_uint8 *icontent; + pico_status_t rvP = PICO_OK; + + rv = picodata_get_iteminfo(wa->inBuf, wa->inLen, &ihead, + &icontent); + if (PICO_OK == rv) { + + switch (ihead.type) { + case PICODATA_ITEM_WORDGRAPH: + + if (0 < ihead.len) { + rvP = waProcessWordgraph(this, wa, &ihead, + icontent); + } else { + /* else ignore empty WORDGRAPH */ + wa->inLen = 0; + wa->procState = WA_STEPSTATE_COLLECT; + return PICODATA_PU_BUSY; + } + break; + case PICODATA_ITEM_OTHER: + /* skip item */ + rvP = PICO_WARN_PU_DISCARD_BUF; + break; + default: + /* copy item unmodified */ + rvP = picodata_copy_item(wa->inBuf, + wa->inLen, wa->outBuf, + wa->outBufSize, &wa->outLen); + break; + } + + if (PICO_OK == rvP) { + wa->inLen = 0; + wa->procState = WA_STEPSTATE_FEED; + /* uncomment next to split into two steps */ + /* return PICODATA_PU_ATOMIC; */ + } else if (PICO_WARN_PU_DISCARD_BUF == rvP) { + /* discard input buffer and get a new item */ + PICODBG_INFO(("skipping OTHER item")); +/* picoos_emRaiseWarning(this->common->em, + PICO_WARN_PU_DISCARD_BUF, NULL, NULL); +*/ + wa->inLen = 0; + wa->procState = WA_STEPSTATE_COLLECT; + return PICODATA_PU_BUSY; + } else { + /* PICO_EXC_BUF_OVERFLOW <- overflow in outbuf + PICO_ERR_OTHER <- no valid item in inbuf + or return from processWordgraph + */ + PICODBG_ERROR(("problem processing item", rvP)); + picoos_emRaiseException(this->common->em, rvP, + NULL, NULL); + return PICODATA_PU_ERROR; + } + + } else { /* could not get iteminfo */ + /* PICO_EXC_BUF_OVERFLOW <- overflow in outbuf + PICO_ERR_OTHER <- no valid item in inbuf + */ + PICODBG_ERROR(("problem getting item info, " + "discard buffer content")); + wa->inLen = 0; + wa->procState = WA_STEPSTATE_COLLECT; + picoos_emRaiseException(this->common->em, rv, + NULL, NULL); + return PICODATA_PU_ERROR; + } + + } else if (wa->inLen == 0) { /* no item in inBuf */ + PICODBG_INFO(("no item in inBuf")); + /* wa->inLen = 0;*/ + wa->procState = WA_STEPSTATE_COLLECT; + return PICODATA_PU_BUSY; + + } else { /* no valid item in inBuf */ + /* bad state/item, discard buffer content */ + PICODBG_WARN(("no valid item, discard buffer content")); + picoos_emRaiseWarning(this->common->em, + PICO_WARN_PU_IRREG_ITEM, NULL, NULL); + picoos_emRaiseWarning(this->common->em, + PICO_WARN_PU_DISCARD_BUF, NULL, NULL); + wa->inLen = 0; + wa->procState = WA_STEPSTATE_COLLECT; + return PICODATA_PU_BUSY; + } + break; + + + /* feed state: copy item in internal outBuf to output charBuf */ + case WA_STEPSTATE_FEED: + + /* check that item fits in cb should not be needed */ + rv = picodata_cbPutItem(this->cbOut, wa->outBuf, + wa->outLen, numBytesOutput); + + PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], + (picoos_uint8 *)"wana: ", wa->outBuf, + wa->outLen); + + PICODBG_DEBUG(("put item, status: %d", rv)); + if (PICO_OK == rv) { + wa->outLen = 0; + wa->procState = WA_STEPSTATE_COLLECT; + return PICODATA_PU_BUSY; + } else if (PICO_EXC_BUF_OVERFLOW == rv) { + PICODBG_INFO(("feeding, overflow, PICODATA_PU_OUT_FULL")); + return PICODATA_PU_OUT_FULL; + } else if ((PICO_EXC_BUF_UNDERFLOW == rv) + || (PICO_ERR_OTHER == rv)) { + PICODBG_WARN(("feeding problem, discarding item")); + wa->outLen = 0; + wa->procState = WA_STEPSTATE_COLLECT; + picoos_emRaiseWarning(this->common->em, rv, NULL,NULL); + return PICODATA_PU_BUSY; + } + break; + + default: + break; + + } /* switch */ + + } /* while */ + + /* should be never reached */ + PICODBG_ERROR(("reached end of function")); + picoos_emRaiseException(this->common->em, PICO_ERR_OTHER, NULL, NULL); + return PICODATA_PU_ERROR; +} + +#ifdef __cplusplus +} +#endif + + +/* end */ diff --git a/pico/lib/picowa.h b/pico/lib/picowa.h new file mode 100644 index 0000000..d7fbcd3 --- /dev/null +++ b/pico/lib/picowa.h @@ -0,0 +1,135 @@ +/* + * 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 picowa.h + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + + +/** + * @addtogroup picowa + * ---------------------------------------------------\n + * Pico Word Analysis \n + * ---------------------------------------------------\n +itemtype, iteminfo1, iteminfo2, content -> TYPE(INFO1,INFO2)content +in the following + +items input\n +=========== + +processed by wa: +- WORDGRAPH(NA,NA)graph +- OTHER(NA,NA)string + +unprocessed: +- all other item types are forwarded through the PU without modification: + - PUNC + - CMD + + +minimal input size (before processing starts)\n +================== + +processing (ie. lex lookup and POS prediction) is possible with +- one item + + +items processed and output\n +========================== + +processing an input WORDGRAPH results in one of the following items: +- WORDGRAPH(POSes,NA)graph + - graph not in lex, POSes determined with dtree, or + - graph in lex - single entry without phone (:G2P), POSes from lex +- WORDINDEX(POSes,NA)pos1|ind1...posN|indN + - graph in lex - {1,4} entries with phone, pos1...posN from lex, + {1,4} lexentries indices in content, POSes combined with map table + in klex + +processing an input OTHER results in the item being skipped (in the +future this can be extended to e.g. spelling) + +see picotok.h for PUNC and CMD + +- POSes %d + - is the superset of all single POS and POS combinations defined + in the lingware as unique symbol +- graph, len>0, utf8 graphemes, %s +- pos1|ind1, pos2|ind2, ..., posN|indN + - pos? are the single, unambiguous POS only, one byte %d + - ind? are the lexentry indices, three bytes %d %d %d + + +lexicon (system lexicon, but must also be ensured for user lexica)\n +======= + +- POS GRAPH PHON, all mandatory, but + - * PHON can be an empty string -> no pronunciation in the resulting TTS output + - * PHON can be :G2P -> use G2P later to add pronunciation +- (POS,GRAPH) is a uniq key (only one entry allowed) +- (GRAPH) is almost a uniq key (2-4 entries with the same GRAPH, and + differing POS and differing PHON possible) + - for one graph we can have 2-4 solutions from the lex which all + need to be passed on the the next PU + - in this case GRAPH, POS, and PHON all must be available in lex + - in this case for each entry only a non-ambiguous, unique POS ID + is possible) + +other limitations\n +================= + +- item size: header plus len=256 (valid for Pico in general) +- wa uses one item context only -> internal buffer set to 256+4 + */ + + +#ifndef PICOWA_H_ +#define PICOWA_H_ + +#include "picoos.h" +#include "picodata.h" +#include "picorsrc.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + + +/* maximum length of an item incl. head for input and output buffers */ +#define PICOWA_MAXITEMSIZE 260 + + +picodata_ProcessingUnit picowa_newWordAnaUnit( + picoos_MemoryManager mm, + picoos_Common common, + picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, + picorsrc_Voice voice); + +#ifdef __cplusplus +} +#endif + +#endif /*PICOWA_H_*/ diff --git a/pico/res/layout/main.xml b/pico/res/layout/main.xml new file mode 100755 index 0000000..7a7828e --- /dev/null +++ b/pico/res/layout/main.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/pico/res/values/strings.xml b/pico/res/values/strings.xml new file mode 100755 index 0000000..527b049 --- /dev/null +++ b/pico/res/values/strings.xml @@ -0,0 +1,22 @@ + + + + + Pico TTS + diff --git a/pico/src/com/svox/pico/CheckVoiceData.java b/pico/src/com/svox/pico/CheckVoiceData.java new file mode 100755 index 0000000..66e6833 --- /dev/null +++ b/pico/src/com/svox/pico/CheckVoiceData.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * 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. + */ + +package com.svox.pico; + +import java.io.File; + +import android.app.Activity; +import android.os.Bundle; +import android.speech.tts.TextToSpeech; + +/* + * Checks if the voice data for the SVOX Pico Engine is present on the + * sd card. + */ +public class CheckVoiceData extends Activity { + private final static String dataDir = "/sdcard/svox/"; + + private final static String[] datafiles = { + "de-DE_gl0_sg.bin", "de-DE_ta.bin", "en-GB_kh0_sg.bin", "en-GB_ta.bin", + "en-US_lh0_sg.bin", "en-US_ta.bin", "es-ES_ta.bin", "es-ES_zl0_sg.bin", + "fr-FR_nk0_sg.bin", "fr-FR_ta.bin", "it-IT_cm0_sg.bin", "it-IT_ta.bin" + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setResult(TextToSpeech.Engine.CHECK_VOICE_DATA_PASS); + + // Make sure the SD card is accessible + if (!new File("/sdcard/").canRead()) { + setResult(TextToSpeech.Engine.CHECK_VOICE_DATA_MISSING_DATA_NO_SDCARD); + } + + // Check for files + for (int i = 0; i < datafiles.length; i++) { + File tempFile = new File(dataDir + datafiles[i]); + if (!tempFile.exists()) { + setResult(TextToSpeech.Engine.CHECK_VOICE_DATA_MISSING_DATA); + } + } + + finish(); + } + +} diff --git a/pico/src/com/svox/pico/DownloadVoiceData.java b/pico/src/com/svox/pico/DownloadVoiceData.java new file mode 100755 index 0000000..02638bb --- /dev/null +++ b/pico/src/com/svox/pico/DownloadVoiceData.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * 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. + */ +package com.svox.pico; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; + +/* + * Downloads the voice data for the SVOX Pico Engine by getting the language + * pack from the Android Market. + */ +public class DownloadVoiceData extends Activity { + private final static String MARKET_URI = "market://search?q=pname:com.svox.langpack.installer"; + + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Uri marketUri = Uri.parse(MARKET_URI); + Intent marketIntent = new Intent(Intent.ACTION_VIEW, marketUri); + startActivityForResult(marketIntent, 0); + finish(); + } +} diff --git a/pico/src/com/svox/pico/Pico.java b/pico/src/com/svox/pico/Pico.java new file mode 100755 index 0000000..b8ab7d1 --- /dev/null +++ b/pico/src/com/svox/pico/Pico.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * 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. + */ +package com.svox.pico; + +import android.app.Activity; +import android.os.Bundle; + +/* + * The Java portion of this TTS plugin engine app does nothing. + * This activity is only here so that the native code can be + * wrapped up inside an apk file. + * + * The file path structure convention is that the native library + * implementing TTS must be a file placed here: + * /data/data//lib/libtts.so + * Example: + * /data/data/com.svox.pico/lib/libttspico.so + */ + +public class Pico extends Activity { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // The Java portion of this does nothing. + // This activity is only here so that everything + // can be wrapped up inside an apk file. + finish(); + } +} diff --git a/pico/tts/com_svox_picottsengine.cpp b/pico/tts/com_svox_picottsengine.cpp new file mode 100644 index 0000000..3e29695 --- /dev/null +++ b/pico/tts/com_svox_picottsengine.cpp @@ -0,0 +1,1039 @@ +/* + * 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. + * + * History: + * 2009-05-18 -- initial version + * 2009-06-04 -- updated for new TtsEngine interface + * + */ + +#include +#include + +#define LOG_TAG "SVOX Pico Engine" + +#include +#include +#include +#include +#include + +using namespace android; + +/* adaptation layer defines */ +#define PICO_MEM_SIZE 2500000 +#define PICO_MIN_RATE 20 +/* speaking rate */ +#define PICO_DEF_RATE 100 +#define PICO_MAX_RATE 500 +#define PICO_MIN_PITCH 50 +/* speaking pitch */ +#define PICO_DEF_PITCH 100 +#define PICO_MAX_PITCH 200 +#define PICO_MIN_VOLUME 0 +/* speaking volume */ +#define PICO_DEF_VOLUME 250 +#define PICO_MAX_VOLUME 500 +/* string constants */ +#define MAX_OUTBUF_SIZE 128 +const char* PICO_LINGWARE_PATH = "/sdcard/svox/"; +const char* PICO_VOICE_NAME = "PicoVoice"; +const char* PICO_SPEED_OPEN_TAG = ""; +const char* PICO_SPEED_CLOSE_TAG = ""; +const char* PICO_PITCH_OPEN_TAG = ""; +const char* PICO_PITCH_CLOSE_TAG = ""; +const char* PICO_VOLUME_OPEN_TAG = ""; +const char* PICO_VOLUME_CLOSE_TAG = ""; +const char* PICO_PHONEME_OPEN_TAG = ""; + +/* supported voices */ +const char* picoSupportedLangIso3[] = { "eng", "eng", "deu", "spa", "fra", "ita" }; +const char* picoSupportedCountryIso3[] = { "USA", "GBR", "DEU", "ESP", "FRA", "ITA" }; +const char* picoSupportedLang[] = { "en-rUS", "en-rGB", "de-rDE", "es-rES", "fr-rFR", "it-rIT" }; +const char* picoInternalLang[] = { "en-US", "en-GB", "de-DE", "es-ES", "fr-FR", "it-IT" }; +const char* picoInternalTaLingware[] = { "en-US_ta.bin", "en-GB_ta.bin", "de-DE_ta.bin", "es-ES_ta.bin", "fr-FR_ta.bin", "it-IT_ta.bin" }; +const char* picoInternalSgLingware[] = { "en-US_lh0_sg.bin", "en-GB_kh0_sg.bin", "de-DE_gl0_sg.bin", "es-ES_zl0_sg.bin", "fr-FR_nk0_sg.bin", "it-IT_cm0_sg.bin" }; +const char* picoInternalUtppLingware[] = { "en-US_utpp.bin", "en-GB_utpp.bin", "de-DE_utpp.bin", "es-ES_utpp.bin", "fr-FR_utpp.bin", "it-IT_utpp.bin" }; +const int picoNumSupportedLang = 6; + +/* supported properties */ +const char* picoSupportedProperties[] = { "language", "rate", "pitch", "volume" }; +const int picoNumSupportedProperties = 4; + + +/* adapation layer global variables */ +synthDoneCB_t* picoSynthDoneCBPtr; +void* picoMemArea = NULL; +pico_System picoSystem = NULL; +pico_Resource picoTaResource = NULL; +pico_Resource picoSgResource = NULL; +pico_Resource picoUtppResource = NULL; +pico_Engine picoEngine = NULL; +pico_Char* picoTaFileName = NULL; +pico_Char* picoSgFileName = NULL; +pico_Char* picoUtppFileName = NULL; +pico_Char* picoTaResourceName = NULL; +pico_Char* picoSgResourceName = NULL; +pico_Char* picoUtppResourceName = NULL; +int picoSynthAbort = 0; +char* picoProp_currLang = NULL; /* current language */ +int picoProp_currRate = PICO_DEF_RATE; /* current rate */ +int picoProp_currPitch = PICO_DEF_PITCH; /* current pitch */ +int picoProp_currVolume = PICO_DEF_VOLUME; /* current volume */ + + + +/* internal helper functions */ + +/** checkForLanguage + * Check if the requested language is among the supported languages. + * @language - the language to check, either in xx or xx-rYY format + * return index of the language, or -1 if not supported. +*/ +static int checkForLanguage( const char * language ) +{ + int found = -1; /* language not found */ + + /* Verify that the requested locale is a locale that we support. */ + for (int i = 0; i < picoNumSupportedLang; i++) + { + if (strcmp(language, picoSupportedLang[i]) == 0) + { + found = i; + break; + } + }; + if (found < 0) + { + /* We didn't find an exact match; it may have been specified with only the first 2 characters. + This could overmatch ISO 639-3 language codes. */ + for (int i = 0; i < picoNumSupportedLang; i++) + { + if (strncmp(language, picoSupportedLang[i], 2) == 0) + { + found = i; + break; + } + } + if (found < 0) + { + LOGE("TtsEngine::set language called with unsupported language"); + } + }; + return found; +} + + +/** cleanResources + * Unloads any loaded Pico resources. +*/ +static void cleanResources( void ) +{ + if (picoEngine) + { + pico_disposeEngine( picoSystem, &picoEngine ); + pico_releaseVoiceDefinition(picoSystem, (pico_Char*)PICO_VOICE_NAME); + picoEngine = NULL; + } + if (picoUtppResource) + { + pico_unloadResource( picoSystem, &picoUtppResource ); + picoUtppResource = NULL; + } + if (picoTaResource) + { + pico_unloadResource( picoSystem, &picoTaResource ); + picoTaResource = NULL; + } + if (picoSgResource) + { + pico_unloadResource( picoSystem, &picoSgResource ); + picoSgResource = NULL; + } +} + + +/** cleanFiles + * Frees any memory allocated for file and resource strings. +*/ +static void cleanFiles( void ) +{ + if (picoProp_currLang) + { + free(picoProp_currLang); + picoProp_currLang = NULL; + } + + if (picoTaFileName) + { + free(picoTaFileName); + picoTaFileName = NULL; + } + + if (picoSgFileName) + { + free(picoSgFileName); + picoSgFileName = NULL; + } + + if (picoUtppFileName) + { + free(picoUtppFileName); + picoUtppFileName = NULL; + } + + if (picoTaResourceName) + { + free(picoTaResourceName); + picoTaResourceName = NULL; + } + + if (picoSgResourceName) + { + free(picoSgResourceName); + picoSgResourceName = NULL; + } + + if (picoUtppResourceName) + { + free(picoUtppResourceName); + picoUtppResourceName = NULL; + } +} + +/** doLanguageSwitchFromLangIndex + * Switch to requested language. If language is already loaded it returns + * immediately, if another language is loaded this will first be unloaded + * and the new one then loaded. If no language is loaded the requested will be loaded. + * @langIndex - the index of the language to load, which is guaranteed to be supported. + * return TTS_SUCCESS or TTS_FAILURE + */ +static tts_result doLanguageSwitchFromLangIndex(int langIndex) +{ + // if we already have a loaded language, check if it's the same one as requested + if (picoProp_currLang && (strcmp(picoProp_currLang, picoSupportedLang[langIndex]) == 0)) + { + LOGI("Language already loaded (%s == %s)", picoProp_currLang, picoSupportedLang[langIndex]); + return TTS_SUCCESS; + } + + // not the same language, unload the current one first + cleanResources(); + + // allocate memory for file and resource names + cleanFiles(); + picoProp_currLang = (char*)malloc(10); + picoTaFileName = (pico_Char*)malloc(PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE); + picoSgFileName = (pico_Char*)malloc(PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE); + picoUtppFileName = (pico_Char*)malloc(PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE); + picoTaResourceName = (pico_Char*)malloc(PICO_MAX_RESOURCE_NAME_SIZE); + picoSgResourceName = (pico_Char*)malloc(PICO_MAX_RESOURCE_NAME_SIZE); + picoUtppResourceName = (pico_Char*)malloc(PICO_MAX_RESOURCE_NAME_SIZE); + + // set path and file names for resource files + strcpy((char*)picoTaFileName, PICO_LINGWARE_PATH); + strcat((char*)picoTaFileName, (const char*)picoInternalTaLingware[langIndex]); + strcpy((char*)picoSgFileName, PICO_LINGWARE_PATH); + strcat((char*)picoSgFileName, (const char*)picoInternalSgLingware[langIndex]); + strcpy((char*)picoUtppFileName, PICO_LINGWARE_PATH); + strcat((char*)picoUtppFileName, (const char*)picoInternalUtppLingware[langIndex]); + + // load text analysis Lingware resource file + int ret = pico_loadResource(picoSystem, picoTaFileName, &picoTaResource); + if (PICO_OK != ret) + { + LOGE("Failed to load textana resource for %s [%d]", picoSupportedLang[langIndex], ret); + cleanResources(); + cleanFiles(); + return TTS_FAILURE; + } + + // load signal generation Lingware resource file + ret = pico_loadResource(picoSystem, picoSgFileName, &picoSgResource); + if (PICO_OK != ret) + { + LOGE("Failed to load siggen resource for %s [%d]", picoSupportedLang[langIndex], ret); + cleanResources(); + cleanFiles(); + return TTS_FAILURE; + } + + // Load utpp Lingware resource file if exists - NOTE: this file is optional + // and is currently not used. Loading is only attempted for future compatibility. + // If this file is not present the loading will still succeed. + ret = pico_loadResource(picoSystem, picoUtppFileName, &picoUtppResource); + if (PICO_OK != ret && ret != PICO_EXC_CANT_OPEN_FILE) + { + LOGE("Failed to load utpp resource for %s [%d]", picoSupportedLang[langIndex], ret); + cleanResources(); + cleanFiles(); + return TTS_FAILURE; + } + + // Get text analysis resource name + ret = pico_getResourceName(picoSystem, picoTaResource, (char*)picoTaResourceName); + if (PICO_OK != ret) + { + LOGE("Failed to get textana resource name for %s [%d]", picoSupportedLang[langIndex], ret); + cleanResources(); + cleanFiles(); + return TTS_FAILURE; + } + + // Get signal generation resource name + ret = pico_getResourceName(picoSystem, picoSgResource, (char*)picoSgResourceName); + if (PICO_OK == ret && picoUtppResource != NULL) + { + // Get utpp resource name - optional: see note above + ret = pico_getResourceName(picoSystem, picoUtppResource, (char*)picoUtppResourceName); + if (PICO_OK != ret) + { + LOGE("Failed to get utpp resource name for %s [%d]", picoSupportedLang[langIndex], ret); + cleanResources(); + cleanFiles(); + return TTS_FAILURE; + } + } + if (PICO_OK != ret) + { + LOGE("Failed to get siggen resource name for %s [%d]", picoSupportedLang[langIndex], ret); + cleanResources(); + cleanFiles(); + return TTS_FAILURE; + } + + // create a voice definition + ret = pico_createVoiceDefinition(picoSystem, (const pico_Char*)PICO_VOICE_NAME); + if (PICO_OK != ret) + { + LOGE("Failed to create voice for %s [%d]", picoSupportedLang[langIndex], ret); + cleanResources(); + cleanFiles(); + return TTS_FAILURE; + } + + // add text analysis resource to voice + ret = pico_addResourceToVoiceDefinition(picoSystem, (const pico_Char*)PICO_VOICE_NAME, picoTaResourceName); + if (PICO_OK != ret) + { + LOGE("Failed to add textana resource to voice for %s [%d]", picoSupportedLang[langIndex], ret); + cleanResources(); + cleanFiles(); + return TTS_FAILURE; + } + + // add signal generation resource to voice + ret = pico_addResourceToVoiceDefinition(picoSystem, (const pico_Char*)PICO_VOICE_NAME, picoSgResourceName); + if (PICO_OK == ret && picoUtppResource != NULL) + { + // add utpp resource to voice - optional: see note above + ret = pico_addResourceToVoiceDefinition(picoSystem, (const pico_Char*)PICO_VOICE_NAME, picoUtppResourceName); + if (PICO_OK != ret) + { + LOGE("Failed to add utpp resource to voice for %s [%d]", picoSupportedLang[langIndex], ret); + cleanResources(); + cleanFiles(); + return TTS_FAILURE; + } + } + + if (PICO_OK != ret) + { + LOGE("Failed to add siggen resource to voice for %s [%d]", picoSupportedLang[langIndex], ret); + cleanResources(); + cleanFiles(); + return TTS_FAILURE; + } + + ret = pico_newEngine(picoSystem, (const pico_Char*)PICO_VOICE_NAME, &picoEngine); + if (PICO_OK != ret) + { + LOGE("Failed to create engine for %s [%d]", picoSupportedLang[langIndex], ret); + cleanResources(); + cleanFiles(); + return TTS_FAILURE; + } + + strcpy(picoProp_currLang, picoSupportedLang[langIndex]); + + LOGI("loaded %s successfully", picoProp_currLang); + + return TTS_SUCCESS; +} + +/** doLanguageSwitch + * Switch to requested language. If language is already loaded it returns + * immediately, if another language is loaded this will first be unloaded + * and the new one then loaded. If no language is loaded the requested will be loaded. + * @language - the language to check, either in xx or xx-rYY format (i.e "en" or "en-rUS") + * return TTS_SUCCESS or TTS_FAILURE +*/ +static tts_result doLanguageSwitch(const char* language) +{ + // load new language + int langIndex = checkForLanguage(language); + if (langIndex < 0) + { + LOGE("Tried to swith to non-supported language %s", language); + return TTS_FAILURE; + } + LOGI("Found supported language %s", picoSupportedLang[langIndex]); + + return doLanguageSwitchFromLangIndex( langIndex ); +} + +/** doAddProperties + * Add , and tags to text, if the properties have been set to non-default values, + * and return the new string. The calling function is responsible for freeing the returned string. + * @str - text to apply tags to + * return new string with tags applied +*/ +static char* doAddProperties(const char* str) +{ + char* data = NULL; + int haspitch = 0, hasspeed = 0, hasvol = 0; + int textlen = strlen(str) + 1; + + if (picoProp_currPitch != PICO_DEF_PITCH) /* non-default pitch */ + { + textlen += strlen(PICO_PITCH_OPEN_TAG) + 5; + textlen += strlen(PICO_PITCH_CLOSE_TAG); + haspitch = 1; + } + if (picoProp_currRate != PICO_DEF_RATE) /* non-default rate */ + { + textlen += strlen(PICO_SPEED_OPEN_TAG) + 5; + textlen += strlen(PICO_SPEED_CLOSE_TAG); + hasspeed = 1; + } + if (picoProp_currVolume != PICO_DEF_VOLUME) /* non-default volume */ + { + textlen += strlen(PICO_VOLUME_OPEN_TAG) + 5; + textlen += strlen(PICO_VOLUME_CLOSE_TAG); + hasvol = 1; + } + + data = (char*)malloc(textlen); + if (!data) + { + return NULL; + } + memset(data, 0, textlen); /* clear it */ + if (haspitch) + { + char* tmp = (char*)malloc(strlen(PICO_PITCH_OPEN_TAG) + strlen(PICO_PITCH_CLOSE_TAG) + 5); + sprintf(tmp, PICO_PITCH_OPEN_TAG, picoProp_currPitch); + strcat(data, tmp); + free(tmp); + } + + if (hasspeed) + { + char* tmp = (char*)malloc(strlen(PICO_SPEED_OPEN_TAG) + strlen(PICO_SPEED_CLOSE_TAG) + 5); + sprintf(tmp, PICO_SPEED_OPEN_TAG, picoProp_currRate); + strcat(data, tmp); + free(tmp); + } + + if (hasvol) + { + char* tmp = (char*)malloc(strlen(PICO_VOLUME_OPEN_TAG) + strlen(PICO_VOLUME_CLOSE_TAG) + 5); + sprintf(tmp, PICO_VOLUME_OPEN_TAG, picoProp_currVolume); + strcat(data, tmp); + free(tmp); + } + + strcat(data, str); + + if (hasvol) + { + strcat(data, PICO_VOLUME_CLOSE_TAG); + } + + if (hasspeed) + { + strcat(data, PICO_SPEED_CLOSE_TAG); + } + + if (haspitch) + { + strcat(data, PICO_PITCH_CLOSE_TAG); + } + + return data; +} + + +/* API function implementations */ + +/** init + * Allocates Pico memory block and initializes Pico system. + * synthDoneCBPtr - Pointer to callback function which will receive generated samples + * return tts_result +*/ +tts_result TtsEngine::init( synthDoneCB_t synthDoneCBPtr ) +{ + if (synthDoneCBPtr == NULL) + { + LOGE("Callback pointer is NULL"); + return TTS_FAILURE; + } + + picoMemArea = malloc(PICO_MEM_SIZE); + if (!picoMemArea) + { + LOGE("Failed to allocate memory for Pico system"); + return TTS_FAILURE; + } + + pico_Status ret = pico_initialize(picoMemArea, PICO_MEM_SIZE, &picoSystem); + if (PICO_OK != ret) + { + LOGE("Failed to initialize Pico system"); + free(picoMemArea); + picoMemArea = NULL; + return TTS_FAILURE; + } + + picoSynthDoneCBPtr = synthDoneCBPtr; + return TTS_SUCCESS; +} + + +/** shutdown + * Unloads all Pico resources; terminates Pico system and frees Pico memory block. + * return tts_result +*/ +tts_result TtsEngine::shutdown( void ) +{ + cleanResources(); + + if (picoSystem) + { + pico_terminate(&picoSystem); + picoSystem = NULL; + } + if (picoMemArea) + { + free(picoMemArea); + picoMemArea = NULL; + } + + cleanFiles(); + + return TTS_SUCCESS; +} + +/** loadLanguage + * Load a new language. + * @value - language string in xx or xx-rYY format (i.e. "en" or "en-rUS") + * @size - size of value + * return tts_result +*/ +tts_result TtsEngine::loadLanguage( const char * value, const size_t size ) +{ + return setProperty("language", value, size); +} + +/** setLanguage + * Load a new language. + * @lang - string with ISO 3 letter language code. + * @country - string with ISO 3 letter country code . + * @variant - string with language variant for that language and country pair. + * return tts_result + */ +tts_result TtsEngine::setLanguage(const char *lang, const char *country, const char *variant) { + if (lang == NULL) { + LOGE("TtsEngine::setLanguage called with NULL language"); + return TTS_FAILURE; + } + + // we look for a match on the language first + // then we look for a match on the country. + // if no match on the language: + // return an error + // if match on the language, but no match on the country: + // load the language found for the language match + // if match on the language, and match on the country: + // load the language found for the country match + + // find a match on the language + int langIndex = -1; + for (int i = 0; i < picoNumSupportedLang; i++) + { + if (strcmp(lang, picoSupportedLangIso3[i]) == 0) { + langIndex = i; + break; + } + } + if (langIndex < 0) { + // language isn't supported + LOGE("TtsEngine::setLanguage called with unsupported language"); + return TTS_FAILURE; + } + + // find a match on the country + if (country != NULL) { + int countryIndex = -1; + for (int i = langIndex; i < picoNumSupportedLang; i++) { + if ((strcmp(lang, picoSupportedLangIso3[i]) == 0) + && (strcmp(country, picoSupportedCountryIso3[i]) == 0)) { + countryIndex = i; + break; + } + } + + if (countryIndex < 0) { + // we didn't find a match on the country, but we had a match on the language, + // use that language + LOGI("TtsEngine::setLanguage found matching language(%s) but not matching country(%s).", + lang, country); + } else { + // we have a match on the language and the country + langIndex = countryIndex; + } + } + + return doLanguageSwitchFromLangIndex( langIndex ); +} + + +/** getLanguage + * Get the currently loaded language - if any. + * @value - buffer which will receive value + * @iosize - size of value - if value is too small to contain the return string, this will contain the actual size needed + * return tts_result +*/ +tts_result TtsEngine::getLanguage( char * value, size_t * iosize ) +{ + return getProperty("language", value, iosize); +} + + +/** setProperty + * Set property. The supported properties are: language, rate, pitch and volume. + * @property - name of property to set + * @value - value to set + * @size - size of value + * return tts_result +*/ +tts_result TtsEngine::setProperty( const char * property, const char * value, const size_t size ) +{ + /* Sanity check */ + if (property == NULL) + { + LOGE("setProperty called with property NULL"); + return TTS_PROPERTY_UNSUPPORTED; + } + + if (value == NULL) + { + LOGE("setProperty called with value NULL"); + return TTS_VALUE_INVALID; + } + + if (strncmp(property, "language", 8) == 0) + { + // verify it's in correct format + if (strlen(value) != 2 && strlen(value) != 6) + { + LOGE("change language called with incorrect format"); + return TTS_VALUE_INVALID; + } + + // try to switch to specified language + if (doLanguageSwitch(value) == TTS_FAILURE) + { + LOGE("failed to load language"); + return TTS_FAILURE; + } + else + { + return TTS_SUCCESS; + } + } + else if (strncmp(property, "rate", 4) == 0) + { + int rate = atoi(value); + if (rate < PICO_MIN_RATE) rate = PICO_MIN_RATE; + if (rate > PICO_MAX_RATE) rate = PICO_MAX_RATE; + picoProp_currRate = rate; + return TTS_SUCCESS; + } + else if (strncmp(property, "pitch", 5) == 0) + { + int pitch = atoi(value); + if (pitch < PICO_MIN_PITCH) pitch = PICO_MIN_PITCH; + if (pitch > PICO_MAX_PITCH) pitch = PICO_MAX_PITCH; + picoProp_currPitch = pitch; + return TTS_SUCCESS; + } + else if (strncmp(property, "volume", 6) == 0) + { + int volume = atoi(value); + if (volume < PICO_MIN_VOLUME) volume = PICO_MIN_VOLUME; + if (volume > PICO_MAX_VOLUME) volume = PICO_MAX_VOLUME; + picoProp_currVolume = volume; + return TTS_SUCCESS; + } + + return TTS_PROPERTY_UNSUPPORTED; +} + + +/** getProperty + * Get the property. Supported properties are: language, rate, pitch and volume. + * @property - name of property to get + * @value - buffer which will receive value of property + * @iosize - size of value - if size is too small on return this will contain actual size needed + * return tts_result +*/ +tts_result TtsEngine::getProperty(const char *property, char *value, size_t* iosize) +{ + /* sanity check */ + if (property == NULL) + { + LOGE("getProperty called with property NULL"); + return TTS_PROPERTY_UNSUPPORTED; + } + + if (value == NULL) + { + LOGE("getProperty called with value NULL"); + return TTS_VALUE_INVALID; + } + + if (strncmp(property, "language", 8) == 0) + { + if (picoProp_currLang == NULL) + { + strcpy(value, ""); + } + else + { + if (*iosize < strlen(picoProp_currLang)+1) + { + *iosize = strlen(picoProp_currLang) + 1; + return TTS_PROPERTY_SIZE_TOO_SMALL; + } + strcpy(value, picoProp_currLang); + } + return TTS_SUCCESS; + } + else if (strncmp(property, "rate", 4) == 0) + { + char tmprate[4]; + sprintf(tmprate, "%d", picoProp_currRate); + if (*iosize < strlen(tmprate)+1) + { + *iosize = strlen(tmprate) + 1; + return TTS_PROPERTY_SIZE_TOO_SMALL; + } + strcpy(value, tmprate); + return TTS_SUCCESS; + } + else if (strncmp(property, "pitch", 5) == 0) + { + char tmppitch[4]; + sprintf(tmppitch, "%d", picoProp_currPitch); + if (*iosize < strlen(tmppitch)+1) + { + *iosize = strlen(tmppitch) + 1; + return TTS_PROPERTY_SIZE_TOO_SMALL; + } + strcpy(value, tmppitch); + return TTS_SUCCESS; + } + else if (strncmp(property, "volume", 6) == 0) + { + char tmpvol[4]; + sprintf(tmpvol, "%d", picoProp_currVolume); + if (*iosize < strlen(tmpvol)+1) + { + *iosize = strlen(tmpvol) + 1; + return TTS_PROPERTY_SIZE_TOO_SMALL; + } + strcpy(value, tmpvol); + return TTS_SUCCESS; + } + else + { + LOGE("Unsupported property"); + return TTS_PROPERTY_UNSUPPORTED; + } +} + + +/** synthesizeText + * Synthesizes a text string. + * @text - text to synthesize + * @buffer - buffer which will receive generated samples + * @bufferSize - size of buffer + * @userdata - pointer to user data which will be passed back to callback function + * return tts_result +*/ +tts_result TtsEngine::synthesizeText(const char *text, int8_t *buffer, size_t bufferSize, void *userdata) +{ + pico_Char* inp = NULL; + pico_Char* local_text = NULL; + short outbuf[MAX_OUTBUF_SIZE/2]; + pico_Int16 bytes_sent, bytes_recv, text_remaining, out_data_type; + pico_Status ret; + picoSynthAbort = 0; + + if (text == NULL) + { + LOGE("synthesizeText called with NULL string"); + return TTS_FAILURE; + } + + if (buffer == NULL) + { + LOGE("synthesizeText called with NULL buffer"); + return TTS_FAILURE; + } + + /* Add property tags to the string - if any. */ + local_text = (pico_Char*)doAddProperties(text); + if (!local_text) + { + LOGE("Failed to allocate memory for text string"); + return TTS_FAILURE; + } + + text_remaining = strlen((const char*)local_text) + 1; + + inp = (pico_Char*)local_text; + + size_t bufused = 0; + + /* synthesis loop */ + while (text_remaining) + { + if (picoSynthAbort) + { + ret = pico_resetEngine(picoEngine); + break; + } + + /* Feed the text into the engine. */ + ret = pico_putTextUtf8(picoEngine, inp, text_remaining, &bytes_sent); + if (ret != PICO_OK) + { + LOGE("Error synthesizing string '%s': [%d]", text, ret); + if (local_text) free(local_text); + return TTS_FAILURE; + } + + text_remaining -= bytes_sent; + inp += bytes_sent; + do + { + if (picoSynthAbort) + { + break; + } + /* Retrieve the samples and add them to the buffer. */ + ret = pico_getData(picoEngine, (void*)outbuf, MAX_OUTBUF_SIZE, &bytes_recv, &out_data_type); + if (bytes_recv) + { + if ((bufused + bytes_recv) <= bufferSize) + { + memcpy(buffer+bufused, (int8_t*)outbuf, bytes_recv); + bufused += bytes_recv; + } + else + { + /* The buffer filled; pass this on to the callback function. */ + int cbret = picoSynthDoneCBPtr(userdata, 16000, AudioSystem::PCM_16_BIT, 1, buffer, bufused, TTS_SYNTH_PENDING); + if (cbret == TTS_CALLBACK_HALT) + { + LOGI("Halt requested by caller. Halting."); + picoSynthAbort = 1; + break; + } + bufused = 0; + memcpy(buffer, (int8_t*)outbuf, bytes_recv); + bufused += bytes_recv; + } + } + } while (PICO_STEP_BUSY == ret); + + /* The synthesis is finished; notify the caller and pass the remaining samples. + Use 16 KHz, 16-bit samples. */ + if (!picoSynthAbort) + { + picoSynthDoneCBPtr( userdata, 16000, AudioSystem::PCM_16_BIT, 1, buffer, bufused, TTS_SYNTH_DONE); + } + picoSynthAbort = 0; + + if (ret != PICO_STEP_IDLE) + { + LOGE("Error occurred during synthesis [%d]", ret); + if (local_text) free(local_text); + return TTS_FAILURE; + } + } + + if (local_text) free(local_text); + return TTS_SUCCESS; +} + + +/** synthesizeIpa + * Synthesizes a phonetic string in IPA format. + * @ipa - phonetic string to synthesize + * @buffer - buffer which will receive generated samples + * @bufferSize - size of buffer + * @userdata - pointer to user data which will be passed back to callback function + * return tts_result +*/ +tts_result TtsEngine::synthesizeIpa( const char * ipa, int8_t * buffer, size_t bufferSize, void * userdata ) +{ + pico_Char* inp = NULL; + pico_Char* local_text = NULL; + short outbuf[MAX_OUTBUF_SIZE/2]; + pico_Int16 bytes_sent, bytes_recv, text_remaining, out_data_type; + pico_Status ret; + + picoSynthAbort = 0; + if (ipa == NULL) + { + LOGE("synthesizeIpa called with NULL string"); + return TTS_FAILURE; + } + + if (buffer == NULL) + { + LOGE("synthesizeIpa called with NULL buffer"); + return TTS_FAILURE; + } + + /* Append phoneme tag. %%% + */ + + /* Add property tags to the string - if any. */ + local_text = (pico_Char*)doAddProperties( ipa ); + if (!local_text) + { + LOGE("Failed to allocate memory for text string"); + return TTS_FAILURE; + } + + text_remaining = strlen((const char*)local_text) + 1; + + inp = (pico_Char*)local_text; + + size_t bufused = 0; + + /* synthesis loop */ + while (text_remaining) + { + if (picoSynthAbort) + { + ret = pico_resetEngine( picoEngine ); + break; + } + + /* Feed the text into the engine. */ + ret = pico_putTextUtf8( picoEngine, inp, text_remaining, &bytes_sent ); + if (ret != PICO_OK) + { + LOGE("Error synthesizing string '%s': [%d]", ipa, ret); + if (local_text) free(local_text); + return TTS_FAILURE; + } + + /* Process the remaining string. */ + text_remaining -= bytes_sent; + inp += bytes_sent; + do + { + if (picoSynthAbort) + { + break; + } + /* Retrieve the samples and add them to the buffer. */ + ret = pico_getData( picoEngine, (void*)outbuf, MAX_OUTBUF_SIZE, &bytes_recv, &out_data_type ); + if (bytes_recv) + { + if ((bufused + bytes_recv) <= bufferSize) + { + memcpy(buffer+bufused, (int8_t*)outbuf, bytes_recv); + bufused += bytes_recv; + } + else + { + /* The buffer filled; pass this on to the callback function. */ + int cbret = picoSynthDoneCBPtr(userdata, 16000, AudioSystem::PCM_16_BIT, 1, buffer, bufused, TTS_SYNTH_PENDING); + if (cbret == TTS_CALLBACK_HALT) + { + LOGI("Halt requested by caller. Halting."); + picoSynthAbort = 1; + break; + } + bufused = 0; + memcpy(buffer, (int8_t*)outbuf, bytes_recv); + bufused += bytes_recv; + } + } + } while (PICO_STEP_BUSY == ret); + + /* The synthesis is finished; notify the caller and pass the remaining samples. + Use 16 KHz, 16-bit samples. */ + if (!picoSynthAbort) + { + picoSynthDoneCBPtr( userdata, 16000, AudioSystem::PCM_16_BIT, 1, buffer, bufused, TTS_SYNTH_DONE ); + } + picoSynthAbort = 0; /* succeeded */ + + if (ret != PICO_STEP_IDLE) + { + LOGE("Error occurred during synthesis [%d]", ret); + if (local_text) free(local_text); + return TTS_FAILURE; + } + } + + if (local_text) + free(local_text); + return TTS_SUCCESS; /* succeeded */ +} + + +/** stop + * Aborts the running synthesis. + * return tts_result +*/ +tts_result TtsEngine::stop() +{ + picoSynthAbort = 1; + return TTS_SUCCESS; +} + + +#ifdef __cplusplus +extern "C" { +#endif + +TtsEngine* getTtsEngine() +{ + return new TtsEngine(); +} + +#ifdef __cplusplus +} +#endif + diff --git a/res/layout/main.xml b/res/layout/main.xml deleted file mode 100755 index 7a7828e..0000000 --- a/res/layout/main.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - diff --git a/res/values/strings.xml b/res/values/strings.xml deleted file mode 100755 index 527b049..0000000 --- a/res/values/strings.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Pico TTS - diff --git a/src/com/svox/pico/CheckVoiceData.java b/src/com/svox/pico/CheckVoiceData.java deleted file mode 100755 index 66e6833..0000000 --- a/src/com/svox/pico/CheckVoiceData.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * 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. - */ - -package com.svox.pico; - -import java.io.File; - -import android.app.Activity; -import android.os.Bundle; -import android.speech.tts.TextToSpeech; - -/* - * Checks if the voice data for the SVOX Pico Engine is present on the - * sd card. - */ -public class CheckVoiceData extends Activity { - private final static String dataDir = "/sdcard/svox/"; - - private final static String[] datafiles = { - "de-DE_gl0_sg.bin", "de-DE_ta.bin", "en-GB_kh0_sg.bin", "en-GB_ta.bin", - "en-US_lh0_sg.bin", "en-US_ta.bin", "es-ES_ta.bin", "es-ES_zl0_sg.bin", - "fr-FR_nk0_sg.bin", "fr-FR_ta.bin", "it-IT_cm0_sg.bin", "it-IT_ta.bin" - }; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setResult(TextToSpeech.Engine.CHECK_VOICE_DATA_PASS); - - // Make sure the SD card is accessible - if (!new File("/sdcard/").canRead()) { - setResult(TextToSpeech.Engine.CHECK_VOICE_DATA_MISSING_DATA_NO_SDCARD); - } - - // Check for files - for (int i = 0; i < datafiles.length; i++) { - File tempFile = new File(dataDir + datafiles[i]); - if (!tempFile.exists()) { - setResult(TextToSpeech.Engine.CHECK_VOICE_DATA_MISSING_DATA); - } - } - - finish(); - } - -} diff --git a/src/com/svox/pico/DownloadVoiceData.java b/src/com/svox/pico/DownloadVoiceData.java deleted file mode 100755 index 02638bb..0000000 --- a/src/com/svox/pico/DownloadVoiceData.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * 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. - */ -package com.svox.pico; - -import android.app.Activity; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; - -/* - * Downloads the voice data for the SVOX Pico Engine by getting the language - * pack from the Android Market. - */ -public class DownloadVoiceData extends Activity { - private final static String MARKET_URI = "market://search?q=pname:com.svox.langpack.installer"; - - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Uri marketUri = Uri.parse(MARKET_URI); - Intent marketIntent = new Intent(Intent.ACTION_VIEW, marketUri); - startActivityForResult(marketIntent, 0); - finish(); - } -} diff --git a/src/com/svox/pico/Pico.java b/src/com/svox/pico/Pico.java deleted file mode 100755 index b8ab7d1..0000000 --- a/src/com/svox/pico/Pico.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * 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. - */ -package com.svox.pico; - -import android.app.Activity; -import android.os.Bundle; - -/* - * The Java portion of this TTS plugin engine app does nothing. - * This activity is only here so that the native code can be - * wrapped up inside an apk file. - * - * The file path structure convention is that the native library - * implementing TTS must be a file placed here: - * /data/data//lib/libtts.so - * Example: - * /data/data/com.svox.pico/lib/libttspico.so - */ - -public class Pico extends Activity { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - // The Java portion of this does nothing. - // This activity is only here so that everything - // can be wrapped up inside an apk file. - finish(); - } -} diff --git a/tts/com_svox_picottsengine.cpp b/tts/com_svox_picottsengine.cpp deleted file mode 100644 index 3e29695..0000000 --- a/tts/com_svox_picottsengine.cpp +++ /dev/null @@ -1,1039 +0,0 @@ -/* - * 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. - * - * History: - * 2009-05-18 -- initial version - * 2009-06-04 -- updated for new TtsEngine interface - * - */ - -#include -#include - -#define LOG_TAG "SVOX Pico Engine" - -#include -#include -#include -#include -#include - -using namespace android; - -/* adaptation layer defines */ -#define PICO_MEM_SIZE 2500000 -#define PICO_MIN_RATE 20 -/* speaking rate */ -#define PICO_DEF_RATE 100 -#define PICO_MAX_RATE 500 -#define PICO_MIN_PITCH 50 -/* speaking pitch */ -#define PICO_DEF_PITCH 100 -#define PICO_MAX_PITCH 200 -#define PICO_MIN_VOLUME 0 -/* speaking volume */ -#define PICO_DEF_VOLUME 250 -#define PICO_MAX_VOLUME 500 -/* string constants */ -#define MAX_OUTBUF_SIZE 128 -const char* PICO_LINGWARE_PATH = "/sdcard/svox/"; -const char* PICO_VOICE_NAME = "PicoVoice"; -const char* PICO_SPEED_OPEN_TAG = ""; -const char* PICO_SPEED_CLOSE_TAG = ""; -const char* PICO_PITCH_OPEN_TAG = ""; -const char* PICO_PITCH_CLOSE_TAG = ""; -const char* PICO_VOLUME_OPEN_TAG = ""; -const char* PICO_VOLUME_CLOSE_TAG = ""; -const char* PICO_PHONEME_OPEN_TAG = ""; - -/* supported voices */ -const char* picoSupportedLangIso3[] = { "eng", "eng", "deu", "spa", "fra", "ita" }; -const char* picoSupportedCountryIso3[] = { "USA", "GBR", "DEU", "ESP", "FRA", "ITA" }; -const char* picoSupportedLang[] = { "en-rUS", "en-rGB", "de-rDE", "es-rES", "fr-rFR", "it-rIT" }; -const char* picoInternalLang[] = { "en-US", "en-GB", "de-DE", "es-ES", "fr-FR", "it-IT" }; -const char* picoInternalTaLingware[] = { "en-US_ta.bin", "en-GB_ta.bin", "de-DE_ta.bin", "es-ES_ta.bin", "fr-FR_ta.bin", "it-IT_ta.bin" }; -const char* picoInternalSgLingware[] = { "en-US_lh0_sg.bin", "en-GB_kh0_sg.bin", "de-DE_gl0_sg.bin", "es-ES_zl0_sg.bin", "fr-FR_nk0_sg.bin", "it-IT_cm0_sg.bin" }; -const char* picoInternalUtppLingware[] = { "en-US_utpp.bin", "en-GB_utpp.bin", "de-DE_utpp.bin", "es-ES_utpp.bin", "fr-FR_utpp.bin", "it-IT_utpp.bin" }; -const int picoNumSupportedLang = 6; - -/* supported properties */ -const char* picoSupportedProperties[] = { "language", "rate", "pitch", "volume" }; -const int picoNumSupportedProperties = 4; - - -/* adapation layer global variables */ -synthDoneCB_t* picoSynthDoneCBPtr; -void* picoMemArea = NULL; -pico_System picoSystem = NULL; -pico_Resource picoTaResource = NULL; -pico_Resource picoSgResource = NULL; -pico_Resource picoUtppResource = NULL; -pico_Engine picoEngine = NULL; -pico_Char* picoTaFileName = NULL; -pico_Char* picoSgFileName = NULL; -pico_Char* picoUtppFileName = NULL; -pico_Char* picoTaResourceName = NULL; -pico_Char* picoSgResourceName = NULL; -pico_Char* picoUtppResourceName = NULL; -int picoSynthAbort = 0; -char* picoProp_currLang = NULL; /* current language */ -int picoProp_currRate = PICO_DEF_RATE; /* current rate */ -int picoProp_currPitch = PICO_DEF_PITCH; /* current pitch */ -int picoProp_currVolume = PICO_DEF_VOLUME; /* current volume */ - - - -/* internal helper functions */ - -/** checkForLanguage - * Check if the requested language is among the supported languages. - * @language - the language to check, either in xx or xx-rYY format - * return index of the language, or -1 if not supported. -*/ -static int checkForLanguage( const char * language ) -{ - int found = -1; /* language not found */ - - /* Verify that the requested locale is a locale that we support. */ - for (int i = 0; i < picoNumSupportedLang; i++) - { - if (strcmp(language, picoSupportedLang[i]) == 0) - { - found = i; - break; - } - }; - if (found < 0) - { - /* We didn't find an exact match; it may have been specified with only the first 2 characters. - This could overmatch ISO 639-3 language codes. */ - for (int i = 0; i < picoNumSupportedLang; i++) - { - if (strncmp(language, picoSupportedLang[i], 2) == 0) - { - found = i; - break; - } - } - if (found < 0) - { - LOGE("TtsEngine::set language called with unsupported language"); - } - }; - return found; -} - - -/** cleanResources - * Unloads any loaded Pico resources. -*/ -static void cleanResources( void ) -{ - if (picoEngine) - { - pico_disposeEngine( picoSystem, &picoEngine ); - pico_releaseVoiceDefinition(picoSystem, (pico_Char*)PICO_VOICE_NAME); - picoEngine = NULL; - } - if (picoUtppResource) - { - pico_unloadResource( picoSystem, &picoUtppResource ); - picoUtppResource = NULL; - } - if (picoTaResource) - { - pico_unloadResource( picoSystem, &picoTaResource ); - picoTaResource = NULL; - } - if (picoSgResource) - { - pico_unloadResource( picoSystem, &picoSgResource ); - picoSgResource = NULL; - } -} - - -/** cleanFiles - * Frees any memory allocated for file and resource strings. -*/ -static void cleanFiles( void ) -{ - if (picoProp_currLang) - { - free(picoProp_currLang); - picoProp_currLang = NULL; - } - - if (picoTaFileName) - { - free(picoTaFileName); - picoTaFileName = NULL; - } - - if (picoSgFileName) - { - free(picoSgFileName); - picoSgFileName = NULL; - } - - if (picoUtppFileName) - { - free(picoUtppFileName); - picoUtppFileName = NULL; - } - - if (picoTaResourceName) - { - free(picoTaResourceName); - picoTaResourceName = NULL; - } - - if (picoSgResourceName) - { - free(picoSgResourceName); - picoSgResourceName = NULL; - } - - if (picoUtppResourceName) - { - free(picoUtppResourceName); - picoUtppResourceName = NULL; - } -} - -/** doLanguageSwitchFromLangIndex - * Switch to requested language. If language is already loaded it returns - * immediately, if another language is loaded this will first be unloaded - * and the new one then loaded. If no language is loaded the requested will be loaded. - * @langIndex - the index of the language to load, which is guaranteed to be supported. - * return TTS_SUCCESS or TTS_FAILURE - */ -static tts_result doLanguageSwitchFromLangIndex(int langIndex) -{ - // if we already have a loaded language, check if it's the same one as requested - if (picoProp_currLang && (strcmp(picoProp_currLang, picoSupportedLang[langIndex]) == 0)) - { - LOGI("Language already loaded (%s == %s)", picoProp_currLang, picoSupportedLang[langIndex]); - return TTS_SUCCESS; - } - - // not the same language, unload the current one first - cleanResources(); - - // allocate memory for file and resource names - cleanFiles(); - picoProp_currLang = (char*)malloc(10); - picoTaFileName = (pico_Char*)malloc(PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE); - picoSgFileName = (pico_Char*)malloc(PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE); - picoUtppFileName = (pico_Char*)malloc(PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE); - picoTaResourceName = (pico_Char*)malloc(PICO_MAX_RESOURCE_NAME_SIZE); - picoSgResourceName = (pico_Char*)malloc(PICO_MAX_RESOURCE_NAME_SIZE); - picoUtppResourceName = (pico_Char*)malloc(PICO_MAX_RESOURCE_NAME_SIZE); - - // set path and file names for resource files - strcpy((char*)picoTaFileName, PICO_LINGWARE_PATH); - strcat((char*)picoTaFileName, (const char*)picoInternalTaLingware[langIndex]); - strcpy((char*)picoSgFileName, PICO_LINGWARE_PATH); - strcat((char*)picoSgFileName, (const char*)picoInternalSgLingware[langIndex]); - strcpy((char*)picoUtppFileName, PICO_LINGWARE_PATH); - strcat((char*)picoUtppFileName, (const char*)picoInternalUtppLingware[langIndex]); - - // load text analysis Lingware resource file - int ret = pico_loadResource(picoSystem, picoTaFileName, &picoTaResource); - if (PICO_OK != ret) - { - LOGE("Failed to load textana resource for %s [%d]", picoSupportedLang[langIndex], ret); - cleanResources(); - cleanFiles(); - return TTS_FAILURE; - } - - // load signal generation Lingware resource file - ret = pico_loadResource(picoSystem, picoSgFileName, &picoSgResource); - if (PICO_OK != ret) - { - LOGE("Failed to load siggen resource for %s [%d]", picoSupportedLang[langIndex], ret); - cleanResources(); - cleanFiles(); - return TTS_FAILURE; - } - - // Load utpp Lingware resource file if exists - NOTE: this file is optional - // and is currently not used. Loading is only attempted for future compatibility. - // If this file is not present the loading will still succeed. - ret = pico_loadResource(picoSystem, picoUtppFileName, &picoUtppResource); - if (PICO_OK != ret && ret != PICO_EXC_CANT_OPEN_FILE) - { - LOGE("Failed to load utpp resource for %s [%d]", picoSupportedLang[langIndex], ret); - cleanResources(); - cleanFiles(); - return TTS_FAILURE; - } - - // Get text analysis resource name - ret = pico_getResourceName(picoSystem, picoTaResource, (char*)picoTaResourceName); - if (PICO_OK != ret) - { - LOGE("Failed to get textana resource name for %s [%d]", picoSupportedLang[langIndex], ret); - cleanResources(); - cleanFiles(); - return TTS_FAILURE; - } - - // Get signal generation resource name - ret = pico_getResourceName(picoSystem, picoSgResource, (char*)picoSgResourceName); - if (PICO_OK == ret && picoUtppResource != NULL) - { - // Get utpp resource name - optional: see note above - ret = pico_getResourceName(picoSystem, picoUtppResource, (char*)picoUtppResourceName); - if (PICO_OK != ret) - { - LOGE("Failed to get utpp resource name for %s [%d]", picoSupportedLang[langIndex], ret); - cleanResources(); - cleanFiles(); - return TTS_FAILURE; - } - } - if (PICO_OK != ret) - { - LOGE("Failed to get siggen resource name for %s [%d]", picoSupportedLang[langIndex], ret); - cleanResources(); - cleanFiles(); - return TTS_FAILURE; - } - - // create a voice definition - ret = pico_createVoiceDefinition(picoSystem, (const pico_Char*)PICO_VOICE_NAME); - if (PICO_OK != ret) - { - LOGE("Failed to create voice for %s [%d]", picoSupportedLang[langIndex], ret); - cleanResources(); - cleanFiles(); - return TTS_FAILURE; - } - - // add text analysis resource to voice - ret = pico_addResourceToVoiceDefinition(picoSystem, (const pico_Char*)PICO_VOICE_NAME, picoTaResourceName); - if (PICO_OK != ret) - { - LOGE("Failed to add textana resource to voice for %s [%d]", picoSupportedLang[langIndex], ret); - cleanResources(); - cleanFiles(); - return TTS_FAILURE; - } - - // add signal generation resource to voice - ret = pico_addResourceToVoiceDefinition(picoSystem, (const pico_Char*)PICO_VOICE_NAME, picoSgResourceName); - if (PICO_OK == ret && picoUtppResource != NULL) - { - // add utpp resource to voice - optional: see note above - ret = pico_addResourceToVoiceDefinition(picoSystem, (const pico_Char*)PICO_VOICE_NAME, picoUtppResourceName); - if (PICO_OK != ret) - { - LOGE("Failed to add utpp resource to voice for %s [%d]", picoSupportedLang[langIndex], ret); - cleanResources(); - cleanFiles(); - return TTS_FAILURE; - } - } - - if (PICO_OK != ret) - { - LOGE("Failed to add siggen resource to voice for %s [%d]", picoSupportedLang[langIndex], ret); - cleanResources(); - cleanFiles(); - return TTS_FAILURE; - } - - ret = pico_newEngine(picoSystem, (const pico_Char*)PICO_VOICE_NAME, &picoEngine); - if (PICO_OK != ret) - { - LOGE("Failed to create engine for %s [%d]", picoSupportedLang[langIndex], ret); - cleanResources(); - cleanFiles(); - return TTS_FAILURE; - } - - strcpy(picoProp_currLang, picoSupportedLang[langIndex]); - - LOGI("loaded %s successfully", picoProp_currLang); - - return TTS_SUCCESS; -} - -/** doLanguageSwitch - * Switch to requested language. If language is already loaded it returns - * immediately, if another language is loaded this will first be unloaded - * and the new one then loaded. If no language is loaded the requested will be loaded. - * @language - the language to check, either in xx or xx-rYY format (i.e "en" or "en-rUS") - * return TTS_SUCCESS or TTS_FAILURE -*/ -static tts_result doLanguageSwitch(const char* language) -{ - // load new language - int langIndex = checkForLanguage(language); - if (langIndex < 0) - { - LOGE("Tried to swith to non-supported language %s", language); - return TTS_FAILURE; - } - LOGI("Found supported language %s", picoSupportedLang[langIndex]); - - return doLanguageSwitchFromLangIndex( langIndex ); -} - -/** doAddProperties - * Add , and tags to text, if the properties have been set to non-default values, - * and return the new string. The calling function is responsible for freeing the returned string. - * @str - text to apply tags to - * return new string with tags applied -*/ -static char* doAddProperties(const char* str) -{ - char* data = NULL; - int haspitch = 0, hasspeed = 0, hasvol = 0; - int textlen = strlen(str) + 1; - - if (picoProp_currPitch != PICO_DEF_PITCH) /* non-default pitch */ - { - textlen += strlen(PICO_PITCH_OPEN_TAG) + 5; - textlen += strlen(PICO_PITCH_CLOSE_TAG); - haspitch = 1; - } - if (picoProp_currRate != PICO_DEF_RATE) /* non-default rate */ - { - textlen += strlen(PICO_SPEED_OPEN_TAG) + 5; - textlen += strlen(PICO_SPEED_CLOSE_TAG); - hasspeed = 1; - } - if (picoProp_currVolume != PICO_DEF_VOLUME) /* non-default volume */ - { - textlen += strlen(PICO_VOLUME_OPEN_TAG) + 5; - textlen += strlen(PICO_VOLUME_CLOSE_TAG); - hasvol = 1; - } - - data = (char*)malloc(textlen); - if (!data) - { - return NULL; - } - memset(data, 0, textlen); /* clear it */ - if (haspitch) - { - char* tmp = (char*)malloc(strlen(PICO_PITCH_OPEN_TAG) + strlen(PICO_PITCH_CLOSE_TAG) + 5); - sprintf(tmp, PICO_PITCH_OPEN_TAG, picoProp_currPitch); - strcat(data, tmp); - free(tmp); - } - - if (hasspeed) - { - char* tmp = (char*)malloc(strlen(PICO_SPEED_OPEN_TAG) + strlen(PICO_SPEED_CLOSE_TAG) + 5); - sprintf(tmp, PICO_SPEED_OPEN_TAG, picoProp_currRate); - strcat(data, tmp); - free(tmp); - } - - if (hasvol) - { - char* tmp = (char*)malloc(strlen(PICO_VOLUME_OPEN_TAG) + strlen(PICO_VOLUME_CLOSE_TAG) + 5); - sprintf(tmp, PICO_VOLUME_OPEN_TAG, picoProp_currVolume); - strcat(data, tmp); - free(tmp); - } - - strcat(data, str); - - if (hasvol) - { - strcat(data, PICO_VOLUME_CLOSE_TAG); - } - - if (hasspeed) - { - strcat(data, PICO_SPEED_CLOSE_TAG); - } - - if (haspitch) - { - strcat(data, PICO_PITCH_CLOSE_TAG); - } - - return data; -} - - -/* API function implementations */ - -/** init - * Allocates Pico memory block and initializes Pico system. - * synthDoneCBPtr - Pointer to callback function which will receive generated samples - * return tts_result -*/ -tts_result TtsEngine::init( synthDoneCB_t synthDoneCBPtr ) -{ - if (synthDoneCBPtr == NULL) - { - LOGE("Callback pointer is NULL"); - return TTS_FAILURE; - } - - picoMemArea = malloc(PICO_MEM_SIZE); - if (!picoMemArea) - { - LOGE("Failed to allocate memory for Pico system"); - return TTS_FAILURE; - } - - pico_Status ret = pico_initialize(picoMemArea, PICO_MEM_SIZE, &picoSystem); - if (PICO_OK != ret) - { - LOGE("Failed to initialize Pico system"); - free(picoMemArea); - picoMemArea = NULL; - return TTS_FAILURE; - } - - picoSynthDoneCBPtr = synthDoneCBPtr; - return TTS_SUCCESS; -} - - -/** shutdown - * Unloads all Pico resources; terminates Pico system and frees Pico memory block. - * return tts_result -*/ -tts_result TtsEngine::shutdown( void ) -{ - cleanResources(); - - if (picoSystem) - { - pico_terminate(&picoSystem); - picoSystem = NULL; - } - if (picoMemArea) - { - free(picoMemArea); - picoMemArea = NULL; - } - - cleanFiles(); - - return TTS_SUCCESS; -} - -/** loadLanguage - * Load a new language. - * @value - language string in xx or xx-rYY format (i.e. "en" or "en-rUS") - * @size - size of value - * return tts_result -*/ -tts_result TtsEngine::loadLanguage( const char * value, const size_t size ) -{ - return setProperty("language", value, size); -} - -/** setLanguage - * Load a new language. - * @lang - string with ISO 3 letter language code. - * @country - string with ISO 3 letter country code . - * @variant - string with language variant for that language and country pair. - * return tts_result - */ -tts_result TtsEngine::setLanguage(const char *lang, const char *country, const char *variant) { - if (lang == NULL) { - LOGE("TtsEngine::setLanguage called with NULL language"); - return TTS_FAILURE; - } - - // we look for a match on the language first - // then we look for a match on the country. - // if no match on the language: - // return an error - // if match on the language, but no match on the country: - // load the language found for the language match - // if match on the language, and match on the country: - // load the language found for the country match - - // find a match on the language - int langIndex = -1; - for (int i = 0; i < picoNumSupportedLang; i++) - { - if (strcmp(lang, picoSupportedLangIso3[i]) == 0) { - langIndex = i; - break; - } - } - if (langIndex < 0) { - // language isn't supported - LOGE("TtsEngine::setLanguage called with unsupported language"); - return TTS_FAILURE; - } - - // find a match on the country - if (country != NULL) { - int countryIndex = -1; - for (int i = langIndex; i < picoNumSupportedLang; i++) { - if ((strcmp(lang, picoSupportedLangIso3[i]) == 0) - && (strcmp(country, picoSupportedCountryIso3[i]) == 0)) { - countryIndex = i; - break; - } - } - - if (countryIndex < 0) { - // we didn't find a match on the country, but we had a match on the language, - // use that language - LOGI("TtsEngine::setLanguage found matching language(%s) but not matching country(%s).", - lang, country); - } else { - // we have a match on the language and the country - langIndex = countryIndex; - } - } - - return doLanguageSwitchFromLangIndex( langIndex ); -} - - -/** getLanguage - * Get the currently loaded language - if any. - * @value - buffer which will receive value - * @iosize - size of value - if value is too small to contain the return string, this will contain the actual size needed - * return tts_result -*/ -tts_result TtsEngine::getLanguage( char * value, size_t * iosize ) -{ - return getProperty("language", value, iosize); -} - - -/** setProperty - * Set property. The supported properties are: language, rate, pitch and volume. - * @property - name of property to set - * @value - value to set - * @size - size of value - * return tts_result -*/ -tts_result TtsEngine::setProperty( const char * property, const char * value, const size_t size ) -{ - /* Sanity check */ - if (property == NULL) - { - LOGE("setProperty called with property NULL"); - return TTS_PROPERTY_UNSUPPORTED; - } - - if (value == NULL) - { - LOGE("setProperty called with value NULL"); - return TTS_VALUE_INVALID; - } - - if (strncmp(property, "language", 8) == 0) - { - // verify it's in correct format - if (strlen(value) != 2 && strlen(value) != 6) - { - LOGE("change language called with incorrect format"); - return TTS_VALUE_INVALID; - } - - // try to switch to specified language - if (doLanguageSwitch(value) == TTS_FAILURE) - { - LOGE("failed to load language"); - return TTS_FAILURE; - } - else - { - return TTS_SUCCESS; - } - } - else if (strncmp(property, "rate", 4) == 0) - { - int rate = atoi(value); - if (rate < PICO_MIN_RATE) rate = PICO_MIN_RATE; - if (rate > PICO_MAX_RATE) rate = PICO_MAX_RATE; - picoProp_currRate = rate; - return TTS_SUCCESS; - } - else if (strncmp(property, "pitch", 5) == 0) - { - int pitch = atoi(value); - if (pitch < PICO_MIN_PITCH) pitch = PICO_MIN_PITCH; - if (pitch > PICO_MAX_PITCH) pitch = PICO_MAX_PITCH; - picoProp_currPitch = pitch; - return TTS_SUCCESS; - } - else if (strncmp(property, "volume", 6) == 0) - { - int volume = atoi(value); - if (volume < PICO_MIN_VOLUME) volume = PICO_MIN_VOLUME; - if (volume > PICO_MAX_VOLUME) volume = PICO_MAX_VOLUME; - picoProp_currVolume = volume; - return TTS_SUCCESS; - } - - return TTS_PROPERTY_UNSUPPORTED; -} - - -/** getProperty - * Get the property. Supported properties are: language, rate, pitch and volume. - * @property - name of property to get - * @value - buffer which will receive value of property - * @iosize - size of value - if size is too small on return this will contain actual size needed - * return tts_result -*/ -tts_result TtsEngine::getProperty(const char *property, char *value, size_t* iosize) -{ - /* sanity check */ - if (property == NULL) - { - LOGE("getProperty called with property NULL"); - return TTS_PROPERTY_UNSUPPORTED; - } - - if (value == NULL) - { - LOGE("getProperty called with value NULL"); - return TTS_VALUE_INVALID; - } - - if (strncmp(property, "language", 8) == 0) - { - if (picoProp_currLang == NULL) - { - strcpy(value, ""); - } - else - { - if (*iosize < strlen(picoProp_currLang)+1) - { - *iosize = strlen(picoProp_currLang) + 1; - return TTS_PROPERTY_SIZE_TOO_SMALL; - } - strcpy(value, picoProp_currLang); - } - return TTS_SUCCESS; - } - else if (strncmp(property, "rate", 4) == 0) - { - char tmprate[4]; - sprintf(tmprate, "%d", picoProp_currRate); - if (*iosize < strlen(tmprate)+1) - { - *iosize = strlen(tmprate) + 1; - return TTS_PROPERTY_SIZE_TOO_SMALL; - } - strcpy(value, tmprate); - return TTS_SUCCESS; - } - else if (strncmp(property, "pitch", 5) == 0) - { - char tmppitch[4]; - sprintf(tmppitch, "%d", picoProp_currPitch); - if (*iosize < strlen(tmppitch)+1) - { - *iosize = strlen(tmppitch) + 1; - return TTS_PROPERTY_SIZE_TOO_SMALL; - } - strcpy(value, tmppitch); - return TTS_SUCCESS; - } - else if (strncmp(property, "volume", 6) == 0) - { - char tmpvol[4]; - sprintf(tmpvol, "%d", picoProp_currVolume); - if (*iosize < strlen(tmpvol)+1) - { - *iosize = strlen(tmpvol) + 1; - return TTS_PROPERTY_SIZE_TOO_SMALL; - } - strcpy(value, tmpvol); - return TTS_SUCCESS; - } - else - { - LOGE("Unsupported property"); - return TTS_PROPERTY_UNSUPPORTED; - } -} - - -/** synthesizeText - * Synthesizes a text string. - * @text - text to synthesize - * @buffer - buffer which will receive generated samples - * @bufferSize - size of buffer - * @userdata - pointer to user data which will be passed back to callback function - * return tts_result -*/ -tts_result TtsEngine::synthesizeText(const char *text, int8_t *buffer, size_t bufferSize, void *userdata) -{ - pico_Char* inp = NULL; - pico_Char* local_text = NULL; - short outbuf[MAX_OUTBUF_SIZE/2]; - pico_Int16 bytes_sent, bytes_recv, text_remaining, out_data_type; - pico_Status ret; - picoSynthAbort = 0; - - if (text == NULL) - { - LOGE("synthesizeText called with NULL string"); - return TTS_FAILURE; - } - - if (buffer == NULL) - { - LOGE("synthesizeText called with NULL buffer"); - return TTS_FAILURE; - } - - /* Add property tags to the string - if any. */ - local_text = (pico_Char*)doAddProperties(text); - if (!local_text) - { - LOGE("Failed to allocate memory for text string"); - return TTS_FAILURE; - } - - text_remaining = strlen((const char*)local_text) + 1; - - inp = (pico_Char*)local_text; - - size_t bufused = 0; - - /* synthesis loop */ - while (text_remaining) - { - if (picoSynthAbort) - { - ret = pico_resetEngine(picoEngine); - break; - } - - /* Feed the text into the engine. */ - ret = pico_putTextUtf8(picoEngine, inp, text_remaining, &bytes_sent); - if (ret != PICO_OK) - { - LOGE("Error synthesizing string '%s': [%d]", text, ret); - if (local_text) free(local_text); - return TTS_FAILURE; - } - - text_remaining -= bytes_sent; - inp += bytes_sent; - do - { - if (picoSynthAbort) - { - break; - } - /* Retrieve the samples and add them to the buffer. */ - ret = pico_getData(picoEngine, (void*)outbuf, MAX_OUTBUF_SIZE, &bytes_recv, &out_data_type); - if (bytes_recv) - { - if ((bufused + bytes_recv) <= bufferSize) - { - memcpy(buffer+bufused, (int8_t*)outbuf, bytes_recv); - bufused += bytes_recv; - } - else - { - /* The buffer filled; pass this on to the callback function. */ - int cbret = picoSynthDoneCBPtr(userdata, 16000, AudioSystem::PCM_16_BIT, 1, buffer, bufused, TTS_SYNTH_PENDING); - if (cbret == TTS_CALLBACK_HALT) - { - LOGI("Halt requested by caller. Halting."); - picoSynthAbort = 1; - break; - } - bufused = 0; - memcpy(buffer, (int8_t*)outbuf, bytes_recv); - bufused += bytes_recv; - } - } - } while (PICO_STEP_BUSY == ret); - - /* The synthesis is finished; notify the caller and pass the remaining samples. - Use 16 KHz, 16-bit samples. */ - if (!picoSynthAbort) - { - picoSynthDoneCBPtr( userdata, 16000, AudioSystem::PCM_16_BIT, 1, buffer, bufused, TTS_SYNTH_DONE); - } - picoSynthAbort = 0; - - if (ret != PICO_STEP_IDLE) - { - LOGE("Error occurred during synthesis [%d]", ret); - if (local_text) free(local_text); - return TTS_FAILURE; - } - } - - if (local_text) free(local_text); - return TTS_SUCCESS; -} - - -/** synthesizeIpa - * Synthesizes a phonetic string in IPA format. - * @ipa - phonetic string to synthesize - * @buffer - buffer which will receive generated samples - * @bufferSize - size of buffer - * @userdata - pointer to user data which will be passed back to callback function - * return tts_result -*/ -tts_result TtsEngine::synthesizeIpa( const char * ipa, int8_t * buffer, size_t bufferSize, void * userdata ) -{ - pico_Char* inp = NULL; - pico_Char* local_text = NULL; - short outbuf[MAX_OUTBUF_SIZE/2]; - pico_Int16 bytes_sent, bytes_recv, text_remaining, out_data_type; - pico_Status ret; - - picoSynthAbort = 0; - if (ipa == NULL) - { - LOGE("synthesizeIpa called with NULL string"); - return TTS_FAILURE; - } - - if (buffer == NULL) - { - LOGE("synthesizeIpa called with NULL buffer"); - return TTS_FAILURE; - } - - /* Append phoneme tag. %%% - */ - - /* Add property tags to the string - if any. */ - local_text = (pico_Char*)doAddProperties( ipa ); - if (!local_text) - { - LOGE("Failed to allocate memory for text string"); - return TTS_FAILURE; - } - - text_remaining = strlen((const char*)local_text) + 1; - - inp = (pico_Char*)local_text; - - size_t bufused = 0; - - /* synthesis loop */ - while (text_remaining) - { - if (picoSynthAbort) - { - ret = pico_resetEngine( picoEngine ); - break; - } - - /* Feed the text into the engine. */ - ret = pico_putTextUtf8( picoEngine, inp, text_remaining, &bytes_sent ); - if (ret != PICO_OK) - { - LOGE("Error synthesizing string '%s': [%d]", ipa, ret); - if (local_text) free(local_text); - return TTS_FAILURE; - } - - /* Process the remaining string. */ - text_remaining -= bytes_sent; - inp += bytes_sent; - do - { - if (picoSynthAbort) - { - break; - } - /* Retrieve the samples and add them to the buffer. */ - ret = pico_getData( picoEngine, (void*)outbuf, MAX_OUTBUF_SIZE, &bytes_recv, &out_data_type ); - if (bytes_recv) - { - if ((bufused + bytes_recv) <= bufferSize) - { - memcpy(buffer+bufused, (int8_t*)outbuf, bytes_recv); - bufused += bytes_recv; - } - else - { - /* The buffer filled; pass this on to the callback function. */ - int cbret = picoSynthDoneCBPtr(userdata, 16000, AudioSystem::PCM_16_BIT, 1, buffer, bufused, TTS_SYNTH_PENDING); - if (cbret == TTS_CALLBACK_HALT) - { - LOGI("Halt requested by caller. Halting."); - picoSynthAbort = 1; - break; - } - bufused = 0; - memcpy(buffer, (int8_t*)outbuf, bytes_recv); - bufused += bytes_recv; - } - } - } while (PICO_STEP_BUSY == ret); - - /* The synthesis is finished; notify the caller and pass the remaining samples. - Use 16 KHz, 16-bit samples. */ - if (!picoSynthAbort) - { - picoSynthDoneCBPtr( userdata, 16000, AudioSystem::PCM_16_BIT, 1, buffer, bufused, TTS_SYNTH_DONE ); - } - picoSynthAbort = 0; /* succeeded */ - - if (ret != PICO_STEP_IDLE) - { - LOGE("Error occurred during synthesis [%d]", ret); - if (local_text) free(local_text); - return TTS_FAILURE; - } - } - - if (local_text) - free(local_text); - return TTS_SUCCESS; /* succeeded */ -} - - -/** stop - * Aborts the running synthesis. - * return tts_result -*/ -tts_result TtsEngine::stop() -{ - picoSynthAbort = 1; - return TTS_SUCCESS; -} - - -#ifdef __cplusplus -extern "C" { -#endif - -TtsEngine* getTtsEngine() -{ - return new TtsEngine(); -} - -#ifdef __cplusplus -} -#endif - -- cgit v1.1