picodata.c revision e9f72c8954f29f10cb4feb16d328a1b5c1fd7169
1/*
2 * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16/**
17 * @file picodata.c
18 *
19 * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland
20 * All rights reserved.
21 *
22 * History:
23 * - 2009-04-20 -- initial version
24 *
25 */
26
27#include "picodefs.h"
28#include "picoos.h"
29#include "picodbg.h"
30#include "picorsrc.h"
31#include "picotrns.h"
32#include "picodata.h"
33
34#ifdef __cplusplus
35extern "C" {
36#endif
37#if 0
38}
39#endif
40
41/* we output coefficients as fixed point values */
42#define PICOCEP_OUT_DATA_FORMAT PICODATA_ITEMINFO1_FRAME_PAR_DATA_FORMAT_FIXED
43
44/* ***************************************************************
45 *                   CharBuffer                                  *
46 *****************************************************************/
47
48/*
49 * method signatures
50 */
51typedef pico_status_t (* picodata_cbPutItemMethod) (register picodata_CharBuffer this,
52        const picoos_uint8 *buf, const picoos_uint16 blenmax,
53        picoos_uint16 *blen);
54
55typedef pico_status_t (* picodata_cbGetItemMethod) (register picodata_CharBuffer this,
56        picoos_uint8 *buf, const picoos_uint16 blenmax,
57        picoos_uint16 *blen, const picoos_uint8 issd);
58
59typedef pico_status_t (* picodata_cbSubResetMethod) (register picodata_CharBuffer this);
60typedef pico_status_t (* picodata_cbSubDeallocateMethod) (register picodata_CharBuffer this, picoos_MemoryManager mm);
61
62typedef struct picodata_char_buffer
63{
64    picoos_char *buf;
65    picoos_uint16 rear; /* next free position to write */
66    picoos_uint16 front; /* next position to read */
67    picoos_uint16 len; /* empty: len = 0, full: len = size */
68    picoos_uint16 size;
69
70    picoos_Common common;
71
72    picodata_cbGetItemMethod getItem;
73    picodata_cbPutItemMethod putItem;
74
75    picodata_cbSubResetMethod subReset;
76    picodata_cbSubDeallocateMethod subDeallocate;
77    void * subObj;
78} char_buffer_t;
79
80
81static pico_status_t data_cbPutItem(register picodata_CharBuffer this,
82        const picoos_uint8 *buf, const picoos_uint16 blenmax,
83        picoos_uint16 *blen);
84
85static pico_status_t data_cbGetItem(register picodata_CharBuffer this,
86        picoos_uint8 *buf, const picoos_uint16 blenmax,
87        picoos_uint16 *blen, const picoos_uint8 issd);
88
89pico_status_t picodata_cbReset(register picodata_CharBuffer this)
90{
91    this->rear = 0;
92    this->front = 0;
93    this->len = 0;
94    if (NULL != this->subObj) {
95        return this->subReset(this);
96    } else {
97        return PICO_OK;
98    }
99}
100
101/* CharBuffer constructor */
102picodata_CharBuffer picodata_newCharBuffer(picoos_MemoryManager mm,
103        picoos_Common common,
104        picoos_objsize_t size)
105{
106    picodata_CharBuffer this;
107
108    this = (picodata_CharBuffer) picoos_allocate(mm, sizeof(*this));
109    PICODBG_DEBUG(("new character buffer, size=%i", size));
110    if (NULL == this) {
111        return NULL;
112    }
113    this->buf = picoos_allocate(mm, size);
114    if (NULL == this->buf) {
115        picoos_deallocate(mm, (void*) &this);
116        return NULL;
117    }
118    this->size = size;
119    this->common = common;
120
121    this->getItem = data_cbGetItem;
122    this->putItem = data_cbPutItem;
123
124    this->subReset = NULL;
125    this->subDeallocate = NULL;
126    this->subObj = NULL;
127
128    picodata_cbReset(this);
129    return this;
130}
131
132void picodata_disposeCharBuffer(picoos_MemoryManager mm,
133                                picodata_CharBuffer *this)
134{
135    if (NULL != (*this)) {
136        /* terminate */
137        if (NULL != (*this)->subObj) {
138            (*this)->subDeallocate(*this,mm);
139        }
140        picoos_deallocate(mm,(void*)&(*this)->buf);
141        picoos_deallocate(mm,(void*)this);
142    }
143}
144
145pico_status_t picodata_cbPutCh(register picodata_CharBuffer this,
146                               picoos_char ch)
147{
148    if (this->len < this->size) {
149        this->buf[this->rear++] = ch;
150        this->rear %= this->size;
151        this->len++;
152        return PICO_OK;
153    } else {
154        return PICO_EXC_BUF_OVERFLOW;
155    }
156}
157
158
159picoos_int16 picodata_cbGetCh(register picodata_CharBuffer this)
160{
161    picoos_char ch;
162    if (this->len > 0) {
163        ch = this->buf[this->front++];
164        this->front %= this->size;
165        this->len--;
166        return ch;
167    } else {
168        return PICO_EOF;
169    }
170}
171
172/* ***************************************************************
173 *                   items: CharBuffer functions                 *
174 *****************************************************************/
175
176static pico_status_t data_cbGetItem(register picodata_CharBuffer this,
177        picoos_uint8 *buf, const picoos_uint16 blenmax,
178        picoos_uint16 *blen, const picoos_uint8 issd)
179{
180    picoos_uint16 i;
181
182    if (this->len < PICODATA_ITEM_HEADSIZE) {    /* item not in cb? */
183        *blen = 0;
184        if (this->len == 0) {    /* is cb empty? */
185            PICODBG_DEBUG(("no item to get"));
186            return PICO_EOF;
187        } else {    /* cb not empty, but not a valid item */
188            PICODBG_WARN(("problem getting item, incomplete head, underflow"));
189        }
190        return PICO_EXC_BUF_UNDERFLOW;
191    }
192    *blen = PICODATA_ITEM_HEADSIZE + (picoos_uint8)(this->buf[((this->front) +
193                                      PICODATA_ITEMIND_LEN) % this->size]);
194
195    /* if getting speech data in item */
196    if (issd) {
197        /* check item type */
198        if (this->buf[this->front] != PICODATA_ITEM_FRAME) {
199            PICODBG_WARN(("item type mismatch for speech data: %c",
200                          this->buf[this->front]));
201            for (i=0; i<*blen; i++) {
202                this->front++;
203                this->front %= this->size;
204                this->len--;
205            }
206            *blen = 0;
207            return PICO_OK;
208        }
209    }
210
211    if (*blen > this->len) {    /* item in cb not complete? */
212        PICODBG_WARN(("problem getting item, incomplete content, underflow; "
213                      "blen=%d, len=%d", *blen, this->len));
214        *blen = 0;
215        return PICO_EXC_BUF_UNDERFLOW;
216    }
217    if (blenmax < *blen) {    /* buf not large enough? */
218        PICODBG_WARN(("problem getting item, overflow"));
219        *blen = 0;
220        return PICO_EXC_BUF_OVERFLOW;
221    }
222
223    /* if getting speech data in item */
224    if (issd) {
225        /* skip item header */
226        for (i = 0; i < PICODATA_ITEM_HEADSIZE; i++) {
227            this->front++;
228            this->front %= this->size;
229            this->len--;
230        }
231        *blen -= PICODATA_ITEM_HEADSIZE;
232    }
233
234    /* all ok, now get item (or speech data only) */
235    for (i = 0; i < *blen; i++) {
236        buf[i] = (picoos_uint8)(this->buf[this->front++]);
237        this->front %= this->size;
238        this->len--;
239    }
240
241#if defined(PICO_DEBUG)
242    if (issd) {
243        PICODBG_DEBUG(("got speech data: %d samples", *blen));
244    } else {
245        PICODBG_DEBUG(("got item: %c|%d|%d|%d||", buf[PICODATA_ITEMIND_TYPE],
246                       buf[PICODATA_ITEMIND_INFO1], buf[PICODATA_ITEMIND_INFO2],
247                       buf[PICODATA_ITEMIND_LEN]));
248        for (i=PICODATA_ITEM_HEADSIZE; i<*blen; i++) {
249            if (buf[PICODATA_ITEMIND_TYPE] == PICODATA_ITEM_WORDGRAPH) {
250                PICODBG_DEBUG(("%c", buf[i]));
251            } else {
252                PICODBG_DEBUG((" %d", buf[i]));
253            }
254        }
255    }
256#endif
257
258    return PICO_OK;
259}
260
261static pico_status_t data_cbPutItem(register picodata_CharBuffer this,
262        const picoos_uint8 *buf, const picoos_uint16 blenmax,
263        picoos_uint16 *blen)
264{
265    picoos_uint16 i;
266
267    if (blenmax < PICODATA_ITEM_HEADSIZE) {    /* itemlen not accessible? */
268        PICODBG_WARN(("problem putting item, underflow"));
269        *blen = 0;
270        return PICO_EXC_BUF_UNDERFLOW;
271    }
272    *blen = buf[PICODATA_ITEMIND_LEN] + PICODATA_ITEM_HEADSIZE;
273    if (*blen > (this->size - this->len)) {    /* cb not enough space? */
274        PICODBG_WARN(("problem putting item, overflow"));
275        *blen = 0;
276        return PICO_EXC_BUF_OVERFLOW;
277    }
278    if (*blen > blenmax) {    /* item in buf not completely accessible? */
279        PICODBG_WARN(("problem putting item, underflow"));
280        *blen = 0;
281        return PICO_EXC_BUF_UNDERFLOW;
282    }
283    /* all ok, now put complete item */
284
285#if defined(PICO_DEBUG)
286    PICODBG_DEBUG(("putting item: %c|%d|%d|%d||",
287                   buf[PICODATA_ITEMIND_TYPE],
288                   buf[PICODATA_ITEMIND_INFO1],
289                   buf[PICODATA_ITEMIND_INFO2],
290                   buf[PICODATA_ITEMIND_LEN]));
291    for (i=PICODATA_ITEM_HEADSIZE; i<*blen; i++) {
292        if (buf[PICODATA_ITEMIND_TYPE] == PICODATA_ITEM_WORDGRAPH) {
293            PICODBG_DEBUG(("%c", buf[i]));
294        } else {
295            PICODBG_DEBUG((" %d", buf[i]));
296        }
297    }
298#endif
299
300    for (i = 0; i < *blen; i++) {
301        /* put single byte */
302        this->buf[this->rear++] = (picoos_char)buf[i];
303        this->rear %= this->size;
304        this->len++;
305    }
306    return PICO_OK;
307}
308
309/*----------------------------------------------------------
310 *  Names   : picodata_cbGetItem
311 *            picodata_cbGetSpeechData
312 *  Function: gets one item from 'this' and writes it on 'blenmax' sized 'buf'.
313 *            gets one item from 'this' and writes the speech data to
314 *              'blenmax' sized 'buf'.
315 *  Returns : PICO_OK : one item was copied
316 *            PICO_EOF : 'this' is empty; no new items available
317 *            PICO_BUF_UNDERFLOW : 'this' doesn't contain a full/valid item
318 *            PICO_BUF_OVERFLOW : 'buf[blenmax]' too small to hold item
319 *            on return, '*blen' contains the number of bytes written to 'buf'
320 * ---------------------------------------------------------*/
321pico_status_t picodata_cbGetItem(register picodata_CharBuffer this,
322        picoos_uint8 *buf, const picoos_uint16 blenmax,
323        picoos_uint16 *blen)
324{
325    return this->getItem(this, buf, blenmax, blen, FALSE);
326}
327
328pico_status_t picodata_cbGetSpeechData(register picodata_CharBuffer this,
329        picoos_uint8 *buf, const picoos_uint16 blenmax,
330        picoos_uint16 *blen)
331{
332
333    return this->getItem(this, buf, blenmax, blen, TRUE);
334}
335
336
337pico_status_t picodata_cbPutItem(register picodata_CharBuffer this,
338        const picoos_uint8 *buf, const picoos_uint16 blenmax,
339        picoos_uint16 *blen)
340{
341
342        return this->putItem(this,buf,blenmax,blen);
343}
344
345/* unsafe, just for measuring purposes */
346picoos_uint8 picodata_cbGetFrontItemType(register picodata_CharBuffer this)
347{
348    return  this->buf[this->front];
349}
350/* ***************************************************************
351 *                   items: support function                     *
352 *****************************************************************/
353
354picoos_uint8 is_valid_itemtype(const picoos_uint8 ch) {
355    switch (ch) {
356        case PICODATA_ITEM_WSEQ_GRAPH:
357        case PICODATA_ITEM_TOKEN:
358        case PICODATA_ITEM_WORDGRAPH:
359        case PICODATA_ITEM_WORDINDEX:
360        case PICODATA_ITEM_WORDPHON:
361        case PICODATA_ITEM_SYLLPHON:
362        case PICODATA_ITEM_BOUND:
363        case PICODATA_ITEM_PUNC:
364        case PICODATA_ITEM_CMD:
365        case PICODATA_ITEM_PHONE:
366        case PICODATA_ITEM_FRAME:
367        case PICODATA_ITEM_FRAME_PAR:
368            return TRUE;
369            break;
370        case PICODATA_ITEM_OTHER:
371        default:
372            break;
373    }
374    PICODBG_WARN(("item type problem: %c", ch));
375    return FALSE;
376}
377
378picoos_uint8 picodata_is_valid_itemhead(const picodata_itemhead_t *head) {
379    if ((NULL != head) && is_valid_itemtype(head->type)) {
380        return TRUE;
381    } else {
382        PICODBG_WARN(("item header problem"));
383        return FALSE;
384    }
385}
386
387/* ***************************************************/
388
389
390pico_status_t picodata_get_itemparts_nowarn(
391        const picoos_uint8 *buf, const picoos_uint16 blenmax,
392        picodata_itemhead_t *head, picoos_uint8 *content,
393        const picoos_uint16 clenmax, picoos_uint16 *clen)
394{
395    if (blenmax >= PICODATA_ITEM_HEADSIZE) {
396        head->type = buf[PICODATA_ITEMIND_TYPE];
397        head->info1 = buf[PICODATA_ITEMIND_INFO1];
398        head->info2 = buf[PICODATA_ITEMIND_INFO2];
399        head->len = buf[PICODATA_ITEMIND_LEN];
400        *clen = head->len;
401        if (blenmax >= (*clen + PICODATA_ITEM_HEADSIZE)) {
402            if (clenmax >= head->len) {
403                picoos_uint16 i;
404                for (i=0; i<head->len; i++) {
405                    content[i] = buf[PICODATA_ITEM_HEADSIZE+i];
406                }
407                return PICO_OK;
408            }
409            *clen = 0;
410            return PICO_EXC_BUF_OVERFLOW;
411        }
412    }
413    *clen = 0;
414    return PICO_EXC_BUF_UNDERFLOW;
415}
416
417pico_status_t picodata_get_itemparts(
418        const picoos_uint8 *buf, const picoos_uint16 blenmax,
419        picodata_itemhead_t *head, picoos_uint8 *content,
420        const picoos_uint16 clenmax, picoos_uint16 *clen)
421{
422    pico_status_t status = picodata_get_itemparts_nowarn(buf,blenmax,head,content,clenmax,clen);
423    if (PICO_EXC_BUF_OVERFLOW == status) {
424        PICODBG_WARN(("problem getting item, overflow"));
425    } else if  (PICO_EXC_BUF_UNDERFLOW == status) {
426        PICODBG_WARN(("problem getting item, overflow"));
427    }
428    return status;
429}
430pico_status_t picodata_put_itemparts(const picodata_itemhead_t *head,
431        const picoos_uint8 *content, const picoos_uint16 clenmax,
432        picoos_uint8 *buf, const picoos_uint16 blenmax, picoos_uint16 *blen)
433{
434    *blen = head->len + PICODATA_ITEM_HEADSIZE;
435    if (blenmax >= *blen) {
436        if (clenmax >= head->len) {
437            picoos_uint16 i;
438            buf[PICODATA_ITEMIND_TYPE] = head->type;
439            buf[PICODATA_ITEMIND_INFO1] = head->info1;
440            buf[PICODATA_ITEMIND_INFO2] = head->info2;
441            buf[PICODATA_ITEMIND_LEN] = head->len;
442            for (i=0; i<head->len; i++) {
443                buf[PICODATA_ITEM_HEADSIZE+i] = content[i];
444            }
445            return PICO_OK;
446        }
447        PICODBG_WARN(("problem putting item, underflow"));
448        *blen = 0;
449        return PICO_EXC_BUF_UNDERFLOW;
450    }
451    PICODBG_WARN(("problem putting item, overflow"));
452    *blen = 0;
453    return PICO_EXC_BUF_OVERFLOW;
454}
455
456pico_status_t picodata_get_iteminfo(
457        picoos_uint8 *buf, const picoos_uint16 blenmax,
458        picodata_itemhead_t *head, picoos_uint8 **content) {
459    if (blenmax >= PICODATA_ITEM_HEADSIZE) {
460        head->type = buf[PICODATA_ITEMIND_TYPE];
461        head->info1 = buf[PICODATA_ITEMIND_INFO1];
462        head->info2 = buf[PICODATA_ITEMIND_INFO2];
463        head->len = buf[PICODATA_ITEMIND_LEN];
464        if (head->len == 0) {
465            *content = NULL;
466        } else {
467            *content = &buf[PICODATA_ITEM_HEADSIZE];
468        }
469        return PICO_OK;
470    }
471    return PICO_EXC_BUF_UNDERFLOW;
472}
473
474pico_status_t picodata_copy_item(const picoos_uint8 *inbuf,
475        const picoos_uint16 inlenmax, picoos_uint8 *outbuf,
476        const picoos_uint16 outlenmax, picoos_uint16 *numb)
477{
478    if (picodata_is_valid_item(inbuf, inlenmax)) {
479        *numb = PICODATA_ITEM_HEADSIZE + inbuf[PICODATA_ITEMIND_LEN];
480    } else {
481        *numb = 0;
482    }
483    if (*numb > 0) {
484        if (outlenmax >= inlenmax) {
485            picoos_uint16 i;
486            for (i=0; i<*numb; i++) {
487                outbuf[i] = inbuf[i];
488            }
489            return PICO_OK;
490        } else {
491            PICODBG_WARN(("buffer problem, out: %d > in: %d", outlenmax, inlenmax));
492            *numb = 0;
493            return PICO_EXC_BUF_OVERFLOW;
494        }
495    } else {
496        PICODBG_WARN(("item problem in inbuf"));
497        return PICO_ERR_OTHER;
498    }
499}
500
501pico_status_t picodata_set_iteminfo1(picoos_uint8 *buf,
502        const picoos_uint16 blenmax, const picoos_uint8 info) {
503    if (PICODATA_ITEMIND_INFO1 < blenmax) {
504        buf[PICODATA_ITEMIND_INFO1] = info;
505        return PICO_OK;
506    } else
507        return PICO_EXC_BUF_UNDERFLOW;
508}
509
510pico_status_t picodata_set_iteminfo2(picoos_uint8 *buf,
511        const picoos_uint16 blenmax, const picoos_uint8 info) {
512    if (PICODATA_ITEMIND_INFO2 < blenmax) {
513        buf[PICODATA_ITEMIND_INFO2] = info;
514        return PICO_OK;
515    } else
516        return PICO_EXC_BUF_UNDERFLOW;
517}
518
519/* sets the len field in the header contained in the item in buf;
520   return values:
521   PICO_OK                 <- all ok
522   PICO_EXC_BUF_UNDERFLOW  <- underflow in buf
523*/
524pico_status_t picodata_set_itemlen(picoos_uint8 *buf,
525        const picoos_uint16 blenmax, const picoos_uint8 len) {
526    if (PICODATA_ITEMIND_LEN < blenmax) {
527        buf[PICODATA_ITEMIND_LEN] = len;
528        return PICO_OK;
529    } else
530        return PICO_EXC_BUF_UNDERFLOW;
531}
532
533picoos_uint8 picodata_is_valid_item(const picoos_uint8 *item,
534        const picoos_uint16 ilenmax)
535{
536    if (ilenmax >= PICODATA_ITEM_HEADSIZE) {
537        picodata_itemhead_t head;
538        head.type = item[0];
539        head.info1 = item[1];
540        head.info2 = item[2];
541        head.len = item[3];
542        if ((ilenmax >= (head.len + PICODATA_ITEM_HEADSIZE)) &&
543            picodata_is_valid_itemhead(&head))
544        {
545            return TRUE;
546        }
547    }
548    return FALSE;
549}
550
551/* ***************************************************************
552 *                   ProcessingUnit                              *
553 *****************************************************************/
554picoos_uint16 picodata_get_default_buf_size (picodata_putype_t puType)
555{
556    return  (PICODATA_PUTYPE_TEXT == puType) ? PICODATA_BUFSIZE_TEXT
557          : (PICODATA_PUTYPE_TOK  == puType) ? PICODATA_BUFSIZE_TOK
558          : (PICODATA_PUTYPE_PR   == puType) ? PICODATA_BUFSIZE_PR
559          : (PICODATA_PUTYPE_PR   == puType) ? PICODATA_BUFSIZE_PR
560          : (PICODATA_PUTYPE_WA   == puType) ? PICODATA_BUFSIZE_WA
561          : (PICODATA_PUTYPE_SA   == puType) ? PICODATA_BUFSIZE_SA
562          : (PICODATA_PUTYPE_ACPH == puType) ? PICODATA_BUFSIZE_ACPH
563          : (PICODATA_PUTYPE_SPHO == puType) ? PICODATA_BUFSIZE_SPHO
564          : (PICODATA_PUTYPE_PAM  == puType) ? PICODATA_BUFSIZE_PAM
565          : (PICODATA_PUTYPE_CEP  == puType) ? PICODATA_BUFSIZE_CEP
566          : (PICODATA_PUTYPE_SIG  == puType) ? PICODATA_BUFSIZE_SIG
567          : (PICODATA_PUTYPE_SINK  == puType) ? PICODATA_BUFSIZE_SINK
568          :                                    PICODATA_BUFSIZE_DEFAULT;
569}
570
571
572typedef struct simple_pu_data
573{
574    picorsrc_Voice voice;
575} simple_pu_data_t;
576
577static pico_status_t puSimpleInitialize (register picodata_ProcessingUnit this, picoos_int32 resetMode) {
578    return PICO_OK;
579}
580
581static pico_status_t puSimpleTerminate (register picodata_ProcessingUnit this) {
582    return PICO_OK;
583}
584
585static picodata_step_result_t puSimpleStep (register picodata_ProcessingUnit this,
586                                            picoos_int16 mode,
587                                            picoos_uint16 * numBytesOutput) {
588    picoos_int16 ch;
589    picoos_int16 result = PICO_OK;
590    mode = mode;        /*PP 13.10.08 : fix warning "var not used in this function"*/
591    *numBytesOutput = 0;
592    while ((result == PICO_OK) && (ch = picodata_cbGetCh(this->cbIn)) != PICO_EOF) {
593        result = picodata_cbPutCh(this->cbOut,(picoos_char) ch);
594        (*numBytesOutput)++;
595    }
596    if (PICO_OK != result) {
597        (*numBytesOutput)--;
598    }
599    if (PICO_OK == result) {
600        return PICODATA_PU_IDLE;
601    } else {
602        return PICODATA_PU_ERROR;
603    }
604}
605
606
607picodata_ProcessingUnit picodata_newProcessingUnit(
608        picoos_MemoryManager mm,
609        picoos_Common common,
610        picodata_CharBuffer cbIn,
611        picodata_CharBuffer cbOut,
612        picorsrc_Voice voice)
613{
614    picodata_ProcessingUnit this = (picodata_ProcessingUnit) picoos_allocate(mm, sizeof(*this));
615    if (this == NULL) {
616        picoos_emRaiseException(common->em,PICO_EXC_OUT_OF_MEM,NULL,NULL);
617        return NULL;
618    }
619    this->common = common;
620    this->cbIn = cbIn;
621    this->cbOut = cbOut;
622    this->voice = voice;
623    this->initialize = puSimpleInitialize;
624    this->terminate = puSimpleTerminate;
625    this->step = puSimpleStep;
626    this->subDeallocate = NULL;
627    this->subObj = NULL;
628    return this;
629}
630
631void picodata_disposeProcessingUnit(
632        picoos_MemoryManager mm,
633        picodata_ProcessingUnit * this)
634{
635    if (NULL != (*this)) {
636        /* terminate */
637        if (NULL != (*this)->subObj) {
638            (*this)->subDeallocate(*this,mm);
639        }
640        picoos_deallocate(mm,(void *)this);
641    }
642
643}
644
645
646picodata_CharBuffer picodata_getCbIn(picodata_ProcessingUnit this)
647{
648    if (NULL == this) {
649        picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL);
650        return NULL;
651    } else {
652        return this->cbIn;
653    }
654}
655
656picodata_CharBuffer picodata_getCbOut(picodata_ProcessingUnit this)
657{
658    if (NULL == this) {
659        picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL);
660        return NULL;
661    } else {
662        return this->cbOut;
663    }
664}
665
666pico_status_t picodata_setCbIn(picodata_ProcessingUnit this, picodata_CharBuffer cbIn)
667{
668    if (NULL == this) {
669        picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL);
670        return PICO_ERR_OTHER;
671    } else {
672        this->cbIn = cbIn;
673        return PICO_OK;
674    }
675
676}
677
678pico_status_t picodata_setCbOut(picodata_ProcessingUnit this, picodata_CharBuffer cbOut)
679{
680    if (NULL == this) {
681        picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL);
682        return PICO_ERR_OTHER;
683    } else {
684        this->cbOut = cbOut;
685        return PICO_OK;
686    }
687}
688
689
690/* ***************************************************************
691 *                   auxiliary functions                         *
692 *****************************************************************/
693
694static void transDurUniform(
695        picoos_uint8 frame_duration_exp, /* 2's exponent of frame duration in ms, e.g. 2 for 4ms, 3 for 8ms */
696        picoos_int8 array_length,
697        picoos_uint8 * inout,
698        picoos_int16 inputdur, /* input duration in ms */
699        picoos_int16 targetdur, /* target duration in ms */
700        picoos_int16 * restdur /* in/out, rest in ms */
701        )
702{
703    picoos_int8 i;
704    picoos_int32 fact, rest;
705
706    /* calculate rest and factor in number of frames (in PICODATA_PICODATA_PRECISION) */
707    rest = (*restdur) << (PICODATA_PRECISION - frame_duration_exp);
708    fact = (targetdur << (PICODATA_PRECISION - frame_duration_exp)) / inputdur;
709
710    for (i = 0; i < array_length; i++) {
711        rest += fact * inout[i];
712        /* instead of rounding, we carry the rest to the next state */
713        inout[i] = rest >> PICODATA_PRECISION;
714        rest -= inout[i] << PICODATA_PRECISION;
715    }
716    (*restdur) = rest >> (PICODATA_PRECISION - frame_duration_exp);
717}
718
719static void transDurWeighted(
720        picoos_uint8 frame_duration_exp, /* 2's exponent of frame duration in ms, e.g. 2 for 4ms, 3 for 8ms */
721        picoos_int8 array_length,
722        picoos_uint8 * inout,
723        const picoos_uint16 * weight,  /* integer weights */
724        picoos_int16 inputdur, /* input duration in ms */
725        picoos_int16 targetdur, /* target duration in ms */
726        picoos_int16 * restdur /* in/out, rest in ms */
727        )
728{
729    picoos_int8 i;
730    picoos_int32 fact, rest, out, weighted_sum;
731
732    /* calculate rest and factor in number of frames (in PICODATA_PICODATA_PRECISION) */
733    rest = (*restdur) << (PICODATA_PRECISION - frame_duration_exp);
734    weighted_sum = 0;
735    for (i=0; i < array_length; i++) {
736        weighted_sum += inout[i] * weight[i];
737    }
738    if (0 == weighted_sum) {
739        transDurUniform(frame_duration_exp,array_length,inout,inputdur,targetdur,restdur);
740        return;
741    }
742    /* get the additive change factor in PICODATA_PRECISION: */
743    if (targetdur > inputdur) {
744        fact = ((targetdur - inputdur) << (PICODATA_PRECISION-frame_duration_exp))/ weighted_sum;
745    } else {
746        fact = -((inputdur - targetdur) << (PICODATA_PRECISION-frame_duration_exp))/ weighted_sum;
747    }
748
749    /* input[i] * fact * weight[i] is the additive modification in PICODATA_PRECISION */
750    for (i=0; i < array_length; i++) {
751        rest += fact * inout[i] * weight[i];
752        /* instead of rounding, we carry the rest to the next state */
753        out = inout[i] + (rest >> PICODATA_PRECISION);
754        if (out < 0) {
755            out = 0;
756        }
757        rest -= ((out-inout[i]) << PICODATA_PRECISION);
758        inout[i] = out;
759    }
760   (*restdur) = rest >> (PICODATA_PRECISION - frame_duration_exp);
761}
762
763
764
765void picodata_transformDurations(
766        picoos_uint8 frame_duration_exp,
767        picoos_int8 array_length,
768        picoos_uint8 * inout,
769        const picoos_uint16 * weight,  /* integer weights */
770        picoos_int16 mintarget, /* minimum target duration in ms */
771        picoos_int16 maxtarget, /* maximum target duration in ms */
772        picoos_int16 facttarget, /* factor to be multiplied with original length to get the target
773                                     the factor is fixed-point with PICODATA_PRECISION PICODATA_PRECISION, i.e.
774                                     the factor as float would be facttarget / PICODATA_PRECISION_FACT
775                                     if factor is 0, only min/max are considered */
776        picoos_int16 * dur_rest /* in/out, rest in ms */
777        )
778{
779    picoos_int32 inputdur, targetdur;
780    picoos_int8 i;
781
782    /* find the original duration in ms */
783    inputdur = 0;
784    for (i=0; i < array_length; i++) {
785        inputdur += inout[i];
786    }
787
788    PICODBG_TRACE(("######## transforming duration fact=%i, limits = [%i,%i] (input frames: %i)",facttarget,mintarget,maxtarget, inputdur));
789
790    inputdur <<= frame_duration_exp;
791
792    /* find the target duration */
793    if (facttarget) {
794        targetdur = (facttarget * inputdur + PICODATA_PREC_HALF) >> PICODATA_PRECISION;
795    } else {
796        targetdur = inputdur;
797    }
798
799    /* we need to modify input if there is an explicit factor or input is not in the target range */
800    if (facttarget || (targetdur < mintarget) || (maxtarget < targetdur)) {
801        /* make sure we are in the limits */
802        if (targetdur < mintarget) {
803            targetdur = mintarget;
804        } else if (maxtarget < targetdur) {
805            targetdur = maxtarget;
806        }
807        /* perform modification */
808        if (NULL == weight) {
809            transDurUniform(frame_duration_exp,array_length,inout,inputdur,targetdur,dur_rest);
810        } else {
811            transDurWeighted(frame_duration_exp,array_length,inout,weight,inputdur,targetdur,dur_rest);
812        }
813    }
814}
815
816
817
818extern picoos_uint8 picodata_getPuTypeFromExtension(picoos_uchar * filename, picoos_bool input)
819{
820    if (input) {
821        if (picoos_has_extension(filename, PICODATA_PUTYPE_TOK_INPUT_EXTENSION)) {
822            return PICODATA_ITEMINFO2_CMD_TO_TOK;
823        }
824        else if (picoos_has_extension(filename, PICODATA_PUTYPE_PR_INPUT_EXTENSION)) {
825            return PICODATA_ITEMINFO2_CMD_TO_PR;
826        }
827        else if (picoos_has_extension(filename, PICODATA_PUTYPE_WA_INPUT_EXTENSION)) {
828            return PICODATA_ITEMINFO2_CMD_TO_WA;
829        }
830        else if (picoos_has_extension(filename, PICODATA_PUTYPE_SA_INPUT_EXTENSION)) {
831            return PICODATA_ITEMINFO2_CMD_TO_SA;
832        }
833        else if (picoos_has_extension(filename, PICODATA_PUTYPE_ACPH_INPUT_EXTENSION)) {
834            return PICODATA_ITEMINFO2_CMD_TO_ACPH;
835        }
836        else if (picoos_has_extension(filename, PICODATA_PUTYPE_SPHO_INPUT_EXTENSION)) {
837            return PICODATA_ITEMINFO2_CMD_TO_SPHO;
838        }
839        else if (picoos_has_extension(filename, PICODATA_PUTYPE_PAM_INPUT_EXTENSION)) {
840            return PICODATA_ITEMINFO2_CMD_TO_PAM;
841        }
842        else if (picoos_has_extension(filename, PICODATA_PUTYPE_CEP_INPUT_EXTENSION)) {
843            return PICODATA_ITEMINFO2_CMD_TO_CEP;
844        }
845        else if (picoos_has_extension(filename, PICODATA_PUTYPE_SIG_INPUT_EXTENSION) ||
846                picoos_has_extension(filename, PICODATA_PUTYPE_WAV_INPUT_EXTENSION)) {
847            return PICODATA_ITEMINFO2_CMD_TO_SIG;
848        }
849        else {
850            return PICODATA_ITEMINFO2_CMD_TO_UNKNOWN;
851        }
852    }
853    else {
854        if (picoos_has_extension(filename, PICODATA_PUTYPE_TOK_OUTPUT_EXTENSION)) {
855            return PICODATA_ITEMINFO2_CMD_TO_TOK;
856        }
857        else if (picoos_has_extension(filename, PICODATA_PUTYPE_PR_OUTPUT_EXTENSION)) {
858            return PICODATA_ITEMINFO2_CMD_TO_PR;
859        }
860        else if (picoos_has_extension(filename, PICODATA_PUTYPE_WA_OUTPUT_EXTENSION)) {
861            return PICODATA_ITEMINFO2_CMD_TO_WA;
862        }
863        else if (picoos_has_extension(filename, PICODATA_PUTYPE_SA_OUTPUT_EXTENSION)) {
864            return PICODATA_ITEMINFO2_CMD_TO_SA;
865        }
866        else if (picoos_has_extension(filename, PICODATA_PUTYPE_ACPH_OUTPUT_EXTENSION)) {
867            return PICODATA_ITEMINFO2_CMD_TO_ACPH;
868        }
869        else if (picoos_has_extension(filename, PICODATA_PUTYPE_SPHO_OUTPUT_EXTENSION)) {
870            return PICODATA_ITEMINFO2_CMD_TO_SPHO;
871        }
872        else if (picoos_has_extension(filename, PICODATA_PUTYPE_PAM_OUTPUT_EXTENSION)) {
873            return PICODATA_ITEMINFO2_CMD_TO_PAM;
874        }
875        else if (picoos_has_extension(filename, PICODATA_PUTYPE_CEP_OUTPUT_EXTENSION)) {
876            return PICODATA_ITEMINFO2_CMD_TO_CEP;
877        }
878        else if (picoos_has_extension(filename, PICODATA_PUTYPE_SIG_OUTPUT_EXTENSION) ||
879                picoos_has_extension(filename, PICODATA_PUTYPE_WAV_OUTPUT_EXTENSION)) {
880            return PICODATA_ITEMINFO2_CMD_TO_SIG;
881        }
882        else {
883            return PICODATA_ITEMINFO2_CMD_TO_UNKNOWN;
884        }
885    }
886    return PICODATA_ITEMINFO2_CMD_TO_UNKNOWN;
887}
888
889
890
891
892/**
893 *
894 * @param transducer
895 * @param common
896 * @param xsampa_parser
897 * @param svoxpa_parser
898 * @param xsampa2svoxpa_mapper
899 * @param inputPhones
900 * @param alphabet
901 * @param outputPhoneIds
902 * @param maxOutputPhoneIds
903 * @return
904 */
905pico_status_t picodata_mapPAStrToPAIds(picotrns_SimpleTransducer transducer,
906        picoos_Common common, picokfst_FST xsampa_parser,
907        picokfst_FST svoxpa_parser, picokfst_FST xsampa2svoxpa_mapper,
908        picoos_uchar * inputPhones, picoos_uchar * alphabet,
909        picoos_uint8 * outputPhoneIds, picoos_int32 maxOutputPhoneIds)
910{
911    pico_status_t status = PICO_OK;
912    if (picoos_strcmp(alphabet, PICODATA_XSAMPA) == 0) {
913        if ((NULL != xsampa_parser) && (NULL != xsampa2svoxpa_mapper)) {
914            picotrns_stInitialize(transducer);
915            status = picotrns_stAddWithPlane(transducer, inputPhones,
916                    PICOKFST_PLANE_ASCII);
917            if (PICO_OK != status) {
918                picoos_emRaiseWarning(common->em, status, NULL,
919                        (picoos_char *) "phoneme sequence too long (%s)",
920                        inputPhones);
921            } else {
922                status = picotrns_stTransduce(transducer, xsampa_parser);
923                if (PICO_OK != status) {
924                    picoos_emRaiseWarning(common->em, status, NULL,
925                            (picoos_char *) "not recognized as xsampa (%s)",
926                            inputPhones);
927                } else {
928                    status = picotrns_stTransduce(transducer, xsampa2svoxpa_mapper);
929                    if (PICO_OK != status) {
930                        picoos_emRaiseWarning(common->em, status, NULL,
931                                (picoos_char *) "illeagal phoneme sequence (%s)",
932                                inputPhones);
933                    } else {
934                        status = picotrns_stGetSymSequence(transducer, outputPhoneIds,
935                                maxOutputPhoneIds);
936                    }
937                }
938            }
939            return status;
940        }
941    } else if (picoos_strcmp(alphabet, PICODATA_SVOXPA) == 0) {
942        if ((NULL != svoxpa_parser)) {
943            picotrns_stInitialize(transducer);
944            status = picotrns_stAddWithPlane(transducer, inputPhones,
945                    PICOKFST_PLANE_ASCII);
946            if (PICO_OK == status) {
947                status = picotrns_stTransduce(transducer, svoxpa_parser);
948            }
949            if (PICO_OK == status) {
950                status = picotrns_stGetSymSequence(transducer, outputPhoneIds,
951                        maxOutputPhoneIds);
952            }
953            return status;
954        }
955    }
956    picoos_strlcpy(outputPhoneIds, (picoos_char *) "", maxOutputPhoneIds);
957    picoos_emRaiseWarning(common->em, PICO_EXC_NAME_ILLEGAL, NULL,
958            (picoos_char *) "alphabet not supported (%s)", alphabet);
959    return PICO_EXC_NAME_ILLEGAL;
960
961}
962
963#if defined (PICO_DEBUG)
964/* ***************************************************************
965 *                   For Debugging only                          *
966 *****************************************************************/
967
968
969/* put string representation of 'itemtype' into 'str' (allocated size 'strsize')
970 * return 'str' */
971static picoos_char * data_itemtype_to_string(const picoos_uint8 itemtype,
972        picoos_char * str, picoos_uint16 strsize)
973{
974    picoos_char * tmpstr;
975    switch (itemtype) {
976        case PICODATA_ITEM_BOUND:
977            tmpstr = (picoos_char *)"BOUND";
978            break;
979        case PICODATA_ITEM_FRAME_PAR:
980            tmpstr = (picoos_char *)"FRAME_PAR";
981            break;
982        case PICODATA_ITEM_PHONE:
983            tmpstr = (picoos_char *)"PHONE";
984            break;
985        case PICODATA_ITEM_CMD:
986            tmpstr = (picoos_char *)"CMD";
987            break;
988        case PICODATA_ITEM_ERR:
989            tmpstr = (picoos_char *)"ERR";
990            break;
991        case PICODATA_ITEM_FRAME:
992            tmpstr = (picoos_char *)"FRAME";
993            break;
994        case PICODATA_ITEM_OTHER:
995            tmpstr = (picoos_char *)"OTHER";
996            break;
997        case PICODATA_ITEM_PUNC:
998            tmpstr = (picoos_char *)"PUNC";
999            break;
1000        case PICODATA_ITEM_SYLLPHON:
1001            tmpstr = (picoos_char *)"SYLLPHON";
1002            break;
1003        case PICODATA_ITEM_WORDGRAPH:
1004            tmpstr = (picoos_char *)"WORDGRAPH";
1005            break;
1006        case PICODATA_ITEM_WORDINDEX:
1007            tmpstr = (picoos_char *)"WORDINDEX";
1008            break;
1009        case PICODATA_ITEM_WORDPHON:
1010            tmpstr = (picoos_char *)"WORDPHON";
1011            break;
1012        case PICODATA_ITEM_WSEQ_GRAPH:
1013            tmpstr = (picoos_char *)"WSEQ_GRAPH";
1014            break;
1015        default:
1016            tmpstr = (picoos_char *)"UNKNOWN";
1017            break;
1018    }
1019    picopal_slprintf((picopal_char *) str, strsize, (picopal_char *)"%s",
1020            tmpstr);
1021    return str;
1022}
1023
1024
1025picoos_char * picodata_head_to_string(const picodata_itemhead_t *head,
1026        picoos_char * str, picoos_uint16 strsize)
1027{
1028    picoos_uint16 typelen;
1029
1030    if (NULL == head) {
1031        picoos_strlcpy(str,(picoos_char *)"[head is NULL]",strsize);
1032    } else {
1033        data_itemtype_to_string(head->type, str, strsize);
1034        typelen = picoos_strlen(str);
1035        picopal_slprintf((picopal_char *) str+typelen, strsize-typelen,
1036                (picopal_char *)"|%c|%c|%i", head->info1, head->info2,
1037                head->len);
1038    }
1039
1040    return str;
1041}
1042
1043void picodata_info_item(const picoknow_KnowledgeBase kb,
1044                        const picoos_uint8 *pref6ch,
1045                        const picoos_uint8 *item,
1046                        const picoos_uint16 itemlenmax,
1047                        const picoos_char *filterfn)
1048{
1049#define SA_USE_PHST 1
1050    picoos_uint16 i;
1051    picoos_uint8 ch;
1052
1053    if ((itemlenmax < 4) || (item == NULL)) {
1054        PICODBG_INFO_MSG(("invalid item\n"));
1055    }
1056
1057    /* first 6 char used for prefix */
1058    PICODBG_INFO_MSG_F(filterfn, ("%6s(", pref6ch));
1059
1060    /* type */
1061    ch = item[0];
1062    if ((32 <= ch) && (ch < 127)) {
1063        PICODBG_INFO_MSG_F(filterfn, ("'%c',", ch));
1064    } else {
1065        PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch));
1066    }
1067    /* info1 */
1068    ch = item[1];
1069    if ((32 <= ch) && (ch < 127))
1070        switch (item[0]) {
1071            case PICODATA_ITEM_PUNC:
1072            case PICODATA_ITEM_BOUND:
1073            case PICODATA_ITEM_CMD:
1074            case PICODATA_ITEM_TOKEN:
1075            case PICODATA_ITEM_FRAME_PAR:
1076                PICODBG_INFO_MSG_F(filterfn, ("'%c',", ch));
1077                break;
1078            default:
1079                PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch));
1080        }
1081    else
1082        PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch));
1083
1084    /* info2 */
1085    ch = item[2];
1086    if ((32 <= ch) && (ch < 127))
1087        switch (item[0]) {
1088            case PICODATA_ITEM_PUNC:
1089            case PICODATA_ITEM_BOUND:
1090            case PICODATA_ITEM_CMD:
1091            case PICODATA_ITEM_WORDPHON:
1092            case PICODATA_ITEM_SYLLPHON:
1093                PICODBG_INFO_MSG_F(filterfn, ("'%c',", ch));
1094                break;
1095            default:
1096                PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch));
1097        }
1098    else
1099        PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch));
1100
1101    /* len */
1102    ch = item[3];
1103    PICODBG_INFO_MSG_F(filterfn, ("%3d)", ch));
1104
1105    for (i = 0; i < ch; i++) {
1106        if ((item[0] == PICODATA_ITEM_WSEQ_GRAPH) ||
1107            (item[0] == PICODATA_ITEM_TOKEN) ||
1108            (item[0] == PICODATA_ITEM_WORDGRAPH) ||
1109            ((item[0] == PICODATA_ITEM_CMD) && !((item[1] == PICODATA_ITEMINFO1_CMD_SPEED) ||
1110                                                 (item[1] == PICODATA_ITEMINFO1_CMD_PITCH) ||
1111                                                 (item[1] == PICODATA_ITEMINFO1_CMD_VOLUME) ||
1112                                                 (item[1] == PICODATA_ITEMINFO1_CMD_SPELL) ||
1113                                                 (item[1] == PICODATA_ITEMINFO1_CMD_SIL)))) {
1114            PICODBG_INFO_MSG_F(filterfn, ("%c", item[4 + i]));
1115        } else {
1116            PICODBG_INFO_MSG_F(filterfn, ("%4d", item[4 + i]));
1117        }
1118    }
1119
1120#if defined (SA_USE_PHST)
1121    {
1122#include "picokdbg.h"
1123        picoos_uint8 j;
1124        picokdbg_Dbg kdbg;
1125        kdbg = picokdbg_getDbg(kb);
1126
1127        if ((item[0] == PICODATA_ITEM_WORDPHON) ||
1128                (item[0] == PICODATA_ITEM_SYLLPHON) ||
1129                ((item[0] == PICODATA_ITEM_CMD) && (item[1] == PICODATA_ITEMINFO1_CMD_PHONEME))) {
1130            if (picokdbg_getPhoneSym(kdbg, item[4])) {
1131                PICODBG_INFO_MSG_F(filterfn, ("  "));
1132                for (j = 0; j < item[3]; j++) {
1133                    PICODBG_INFO_MSG_F(filterfn, ("%s",
1134                            picokdbg_getPhoneSym(kdbg, item[4 + j])));
1135                }
1136            }
1137        }
1138    }
1139#endif
1140
1141    PICODBG_INFO_MSG_F(filterfn, ("\n"));
1142}
1143
1144
1145#endif   /* PICO_DEBUG */
1146
1147#ifdef __cplusplus
1148}
1149#endif
1150
1151
1152/* picodata.c end */
1153