diff options
Diffstat (limited to 'lib/picodata.c')
-rw-r--r-- | lib/picodata.c | 1152 |
1 files changed, 1152 insertions, 0 deletions
diff --git a/lib/picodata.c b/lib/picodata.c new file mode 100644 index 0000000..244e4b6 --- /dev/null +++ b/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; i<head->len; 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; i<head->len; 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 */ |