Home | History | Annotate | Download | only in clib
      1 /*---------------------------------------------------------------------------*
      2  *  fpi_tgt.c  *
      3  *                                                                           *
      4  *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
      5  *                                                                           *
      6  *  Licensed under the Apache License, Version 2.0 (the 'License');          *
      7  *  you may not use this file except in compliance with the License.         *
      8  *                                                                           *
      9  *  You may obtain a copy of the License at                                  *
     10  *      http://www.apache.org/licenses/LICENSE-2.0                           *
     11  *                                                                           *
     12  *  Unless required by applicable law or agreed to in writing, software      *
     13  *  distributed under the License is distributed on an 'AS IS' BASIS,        *
     14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
     15  *  See the License for the specific language governing permissions and      *
     16  *  limitations under the License.                                           *
     17  *                                                                           *
     18  *---------------------------------------------------------------------------*/
     19 
     20 
     21 
     22 
     23 
     24 #ifndef _RTT
     25 #include <stdio.h>
     26 #endif
     27 #include <assert.h>
     28 
     29 #include "all_defs.h"
     30 #include "fpi_tgt.h"
     31 #include "voicing.h"
     32 #include "portable.h"
     33 
     34 #include "fpi_tgt.inl"
     35 
     36 #define DEBUG_REWIND 0
     37 
     38 /************************************************************************
     39  * Create a Frame Buffer                                                *
     40  ************************************************************************
     41  *
     42  * On the Real Time Target (_RTT) the caller of this function is
     43  * responsible for publically declaring the location of the Frame Buffer
     44  * so that the REC unit can locate it.  This is achived by use of the
     45  * 'setPublicLocation()' and 'publicLocation()' functions.
     46  *
     47  ************************************************************************
     48  *
     49  * Arguments: "fCnt"       Size of Frame Stack
     50  *            "dimen"      Size of Frame
     51  *            "blockLen"   Blocking length (if Using)
     52  *            "doVoice"    Reserve voicing parameter
     53  *
     54  * Returns:   fepFramePkt* Pointer to frame buffer
     55  *                          NULL on error
     56  *
     57  ************************************************************************/
     58 
     59 static int  incThisFramePtr(fepFramePkt* frmPkt, featdata** parPtr);
     60 static int  decThisFramePtr(fepFramePkt* frmPkt, featdata** parPtr);
     61 
     62 
     63 
     64 fepFramePkt* createFrameBuffer(int fCnt, int dimen, int blockLen, int doVoice)
     65 {
     66   fepFramePkt* frmPkt;
     67 #if QUICK
     68   unsigned long frame_mask = 1, tmpsiz;
     69 #endif
     70 
     71   ASSERT(fCnt > 0);
     72   ASSERT(dimen > 0);
     73 
     74   /* Allocate space for the Frame Packet  *
     75    * and then accommodate the Frame Stack */
     76 
     77   frmPkt = (fepFramePkt*) CALLOC_CLR(1, sizeof(fepFramePkt), "clib.Frame_Buffer");
     78   if (frmPkt == NULL)
     79     return NULL;
     80 
     81 #if QUICK
     82   tmpsiz = blockLen;
     83   frame_mask = 1;
     84   tmpsiz >>= 1;
     85   while (tmpsiz)
     86   {
     87     frame_mask = (frame_mask << 1) | 0x01;
     88     tmpsiz >>= 1;
     89   }
     90   blockLen = frame_mask + 1;
     91   frmPkt->stackMask = frame_mask;
     92 #endif
     93 
     94   frmPkt->uttDim = dimen;
     95   if (doVoice) dimen++;
     96 
     97   frmPkt->frameStackSize  = fCnt;
     98   frmPkt->frameSize       = dimen;
     99   frmPkt->featuresInStack = fCnt * dimen;
    100   frmPkt->blockLen = blockLen;
    101   if (doVoice) frmPkt->haveVoiced = True;
    102   else frmPkt->haveVoiced = False;
    103 
    104   frmPkt->frameStack = (featdata *) CALLOC(fCnt,
    105                        sizeof(featdata) * dimen, "clib.Frame_Stack");
    106   if (frmPkt == NULL)
    107     return NULL;
    108   frmPkt->lastFrameInStack = frmPkt->frameStack + (fCnt - 1) * dimen;
    109 
    110   /* Use standard function to clear the buffer,    *
    111    * we don't care about the return code because   *
    112    * we built it, others should care...            */
    113 
    114   (void) clearFrameBuffer(frmPkt);
    115 
    116   frmPkt->uttTimeout = 20;             /* default setting */
    117 
    118   return frmPkt;
    119 }
    120 
    121 
    122 /************************************************************************
    123  * Clear an existing Frame Buffer                                       *
    124  ************************************************************************
    125  *
    126  * Given a pointer to a previously created frame buffer structure
    127  * this funtion will reset its member components to their initial
    128  * values.
    129  *
    130  ************************************************************************
    131  *
    132  * Arguments: "frmPkt"     Frame Buffer Structure Pointer
    133  *
    134  * Returns:   int          non-ZERO on Error
    135  *
    136  ************************************************************************/
    137 
    138 int clearFrameBuffer(fepFramePkt* frmPkt)
    139 {
    140   ASSERT(frmPkt != NULL);
    141 
    142   /* Clear the frame stack to ZERO as  *
    143    * this is done by model_allocate()  */
    144 
    145   memset(frmPkt->frameStack, 0,  /*  TODO: do we need this? */
    146          sizeof(featdata) * frmPkt->frameSize * frmPkt->frameStackSize);
    147 
    148   /* Reset Structure Members           */
    149 
    150   frmPkt->isCollecting = FB_IDLE;
    151   frmPkt->pullp       = frmPkt->frameStack;
    152 
    153   frmPkt->pushp       = frmPkt->frameStack;
    154   frmPkt->pushBlkp    = frmPkt->frameStack;
    155   frmPkt->pushBlocked = False;
    156   frmPkt->blockTime   = 0;
    157   frmPkt->pushTime    = 1;    /* 0 == invalid frame ID, 1 == first    */
    158   frmPkt->pullTime    = 1;
    159   frmPkt->startTime   = 0;    /* 0 == start hasn't been called        */
    160   frmPkt->stopTime    = 0;    /* 0 == stop  hasn't been called        */
    161 
    162   clearEndOfUtterance(frmPkt);
    163   clearC0Entries(frmPkt);
    164 
    165   return False;
    166 }
    167 
    168 /************************************************************************
    169  * Destroy a Previously Created Frame Buffer                            *
    170  ************************************************************************
    171  *
    172  * On the Real Time Target (_RTT) the caller of this function is
    173  * responsible for publically declaring the location of the Frame Buffer
    174  * so that the REC unit can locate it.  This is achived by use of the
    175  * 'setPublicLocation()' and 'publicLocation()' functions.
    176  *
    177  ************************************************************************
    178  *
    179  * Arguments: fepFramePkt* Pointer to frame buffer to destroy
    180  *
    181  * Returns:   int          non-ZERO on error
    182  *
    183  ************************************************************************/
    184 
    185 int destroyFrameBuffer(fepFramePkt* frmPkt)
    186 {
    187   ASSERT(frmPkt);
    188   /* De-allocate space for the Frame Stack *
    189    * and then the Frame Packet             */
    190 
    191   FREE(frmPkt->frameStack);
    192   FREE(frmPkt);
    193   return False;
    194 }
    195 
    196 /************************************************************************
    197  * To Start Collecting Frames                                           *
    198  ***********************************************************************/
    199 
    200 void startFrameCollection(fepFramePkt* frmPkt)
    201 {
    202   ASSERT(frmPkt);
    203   if (frmPkt->isCollecting == FB_IDLE)
    204   {
    205     clearEndOfUtterance(frmPkt);
    206     clearC0Entries(frmPkt);
    207 
    208     frmPkt->startTime = frmPkt->pushTime;
    209     frmPkt->stopTime = 0;
    210     frmPkt->isCollecting = FB_ACTIVE;
    211   }
    212   return;
    213 }
    214 
    215 /************************************************************************
    216  * To Stop Collecting Frames                                            *
    217  ***********************************************************************/
    218 
    219 int stopFrameCollection(fepFramePkt* frmPkt)
    220 {
    221   ASSERT(frmPkt);
    222   ASSERT(frmPkt->startTime != 0);
    223 
    224   if (frmPkt->isCollecting == FB_ACTIVE)
    225   {
    226 
    227     /* Remember, pushTime is the ID of the next frame to arrive
    228      * The buffer starts empty, with pushTime == 1.
    229      * So if Stop occurs at this point, then the start and end frames
    230      * will be
    231      */
    232 
    233     frmPkt->stopTime = frmPkt->pushTime;
    234     frmPkt->isCollecting = FB_IDLE;
    235 
    236     return (True);
    237   }
    238 
    239   return (False);
    240 }
    241 
    242 /************************************************************************
    243  ***********************************************************************/
    244 
    245 void setupEndOfUtterance(fepFramePkt* frmPkt, long timeout, long holdOff)
    246 {
    247   ASSERT(frmPkt);
    248   ASSERT(timeout >= 0);
    249   ASSERT(holdOff >= 0);
    250   frmPkt->uttTimeout = timeout;
    251   frmPkt->holdOffPeriod = holdOff;
    252   frmPkt->holdOff = 0;
    253   return;
    254 }
    255 
    256 /************************************************************************
    257  ***********************************************************************/
    258 
    259 void clearEndOfUtterance(fepFramePkt* frmPkt)
    260 {
    261   ASSERT(frmPkt);
    262   ASSERT(frmPkt->holdOffPeriod >= 0);
    263   frmPkt->voicingDetected = 0;
    264   frmPkt->quietFrames = 0;
    265   frmPkt->utt_ended = False;
    266   frmPkt->holdOff = frmPkt->holdOffPeriod;
    267 
    268   return;
    269 }
    270 
    271 void releaseBlockedFramesInBuffer(fepFramePkt* frmPkt)
    272 {
    273   frmPkt->pullp = frmPkt->pushp;     /*  Move the Blocker to pullp */
    274   frmPkt->pushBlkp = frmPkt->pushp;     /*  Move the Blocker to pullp */
    275   frmPkt->pullTime = frmPkt->pushTime;
    276   frmPkt->blockTime = frmPkt->pushTime;
    277 
    278   return;
    279 }
    280 
    281 /************************************************************************
    282  * Push a Single Frame into Frame Buffer                                *
    283  ************************************************************************
    284  *
    285  * Inserts a new frame into the frame buffer.
    286  *
    287  * If there is no room in the buffer (the frame maker has exhausted the
    288  * space which is being slowly 'eaten' by the associated recognizer) then
    289  * the data is not inserted and an error value is returned.  For this to
    290  * happen, blockLen member must be set.  Otherwise pushBlkp will always
    291  * point to the oldest valid frame in the buffer.
    292  *
    293  ************************************************************************
    294  *
    295  * Arguments: "frmPkt"  Frame Buffer Pointer
    296  *            "parPtr"  Pointer to contiguous block of Frame Parameters
    297  *
    298  * Returns:   int       non-ZERO on ERROR
    299  *
    300  ************************************************************************/
    301 
    302 int pushSingleFEPframe(fepFramePkt* frmPkt, featdata* parPtr, int voiceData)
    303 {
    304   featdata*   destFrmPtr;
    305   featdata*   nextFrmPtr;
    306 
    307   ASSERT(frmPkt);
    308   ASSERT(parPtr);
    309 
    310   /* 'pushp' must be either within the frame buffer or NULL. *
    311    * If it is NULL then the frame is just discarded.         */
    312 
    313   if (frmPkt->isCollecting != FB_ACTIVE) return True;
    314   if ((destFrmPtr = nextFrmPtr = (featdata*) frmPkt->pushp) == NULL)
    315     return (0);
    316 
    317 #if DEBUG_REWIND
    318   log_report("U: voicing at %d was %x\n", frmPkt->pushTime, voiceData);
    319 #endif
    320 
    321   /* Copy the frame into the buffer.  Once this is done     *
    322    * advance 'pushp' (unless it is up against the 'blocker' *
    323    * The frame consists of Parameters and Signal Data       */
    324 
    325   memcpy(destFrmPtr, parPtr, frmPkt->uttDim * sizeof(featdata));
    326   if (frmPkt->haveVoiced)
    327     destFrmPtr[frmPkt->uttDim] = voiceData;
    328 
    329   /* The following (vocing detection which triggers EOU),
    330    * is only active when the 'holdOff' member is 0.
    331    * The intension is to delay 'voicing' signal for at least
    332   * 'holdOffPeriod' frames.
    333    */
    334   if (frmPkt->holdOff <= 0)
    335   {
    336     if (frmPkt->haveVoiced && frmPkt->utt_ended == False)
    337     {
    338       if (voiceData & VOICE_BIT)
    339       {
    340         frmPkt->voicingDetected = 1;
    341       }
    342       if (voiceData & QUIET_BIT)
    343       {
    344         frmPkt->quietFrames++;
    345         if (frmPkt->voicingDetected
    346             && frmPkt->quietFrames > frmPkt->uttTimeout)
    347         {
    348           log_report("Level based utterance ended at %d\n",
    349                      frmPkt->pushTime);
    350           frmPkt->utt_ended = True;
    351         }
    352       }
    353       else
    354         frmPkt->quietFrames = 0;
    355     }
    356   }
    357   else
    358   {
    359     ASSERT(frmPkt->holdOff > 0);
    360     frmPkt->holdOff--;
    361   }
    362 
    363   /*  Track C0 values
    364   */
    365   if (frmPkt->maxC0 < parPtr[0])      /* only works if the 0th entry - */
    366     frmPkt->maxC0 = parPtr[0];       /* is C0 */
    367 
    368   if (frmPkt->minC0 > parPtr[0])      /* only works if the 0th entry - */
    369     frmPkt->minC0 = parPtr[0];       /* is C0 */
    370 
    371   frmPkt->pushTime++;
    372   if (frmPkt->pushTime == 0L)          /* Check for wrap - and ensure */
    373     frmPkt->pushTime++;              /* ZERO is NEVER used          */
    374 
    375   /* Try to move the push pointer on, if it meets the *
    376    * push blocker it should not increment.            */
    377 
    378   nextFrmPtr = (featdata *) NEXT_FRAME_POINTER(frmPkt, frmPkt->pushp);
    379 
    380   if (nextFrmPtr == frmPkt->pullp)
    381   {
    382     /* Latest Frame was blocked, so record the fact and then *
    383     * record the frame time that this occured (useful?)     */
    384 
    385     frmPkt->pushBlocked++;
    386     frmPkt->blockTime = frmPkt->pushTime;
    387 
    388     return True;
    389   }
    390 
    391   else if (nextFrmPtr == frmPkt->pushBlkp)
    392   {
    393     if (frmPkt->blockLen == 0)
    394     {
    395       /* Simply move pushBlkp along */
    396 
    397       frmPkt->pushBlkp = NEXT_FRAME_POINTER(frmPkt, frmPkt->pushBlkp);
    398     }
    399     else
    400     {
    401       /* Latest Frame was blocked, so record the fact and then *
    402        * record the frame time that this occured (useful?)     */
    403 
    404       frmPkt->pushBlocked++;
    405       frmPkt->blockTime = frmPkt->pushTime;
    406 
    407       return True;
    408     }
    409   }
    410 
    411   /* Free to move ahead, so increment the push pointer     *
    412    * and increase the frame-count between pull & push      */
    413 
    414   frmPkt->pushp = nextFrmPtr;
    415   /*      Increment semaphore count for each frame pushed.
    416    Decrement is in waitforsinglefepframe */
    417   return False;
    418 }
    419 
    420 /************************************************************************
    421  * Sets oldest frame pointer (Use with caution)                         *
    422  ************************************************************************
    423  *
    424  * NOTES
    425  *
    426  * If 'masterREC', 'pullp' is manipulated, otherwise one of the
    427  * multiple recognition pointers, 'auxPullp[]' is used.
    428  *
    429  ************************************************************************
    430  *
    431  * CAUTION
    432  *
    433  * With multiple recognizers, the gap-test doesn't work !!!
    434  *
    435  ************************************************************************
    436  *
    437  * Arguments: "frmPkt"     Pointer to Frame Packet
    438  *            "fCnt"       Frame offset from Newest Frame
    439  *                              +ve == Increase Distance between oldest & newest
    440  *                              -ve == Decrease Distance
    441  *            "mode"           ZERO means movement wrt Newest Frame
    442  *                         non-ZERO means movement wrt Current Oldest Frame
    443  *
    444  * Retunrs:   int          Status of operation
    445  *                          No Problems: False
    446  *                          No FEP     : DUKRC_NOFEP
    447  *
    448  * Critical section code!
    449  *
    450  ************************************************************************/
    451 
    452 int setRECframePtr(fepFramePkt* frmPkt, int fCnt, int mode)
    453 {
    454   int   gap;
    455 
    456   ASSERT(frmPkt);
    457 
    458   if (mode != 0) /* wrt Current Oldest Frame */
    459   {
    460     /************
    461     * Relative *
    462     ************/
    463 
    464     /* Can it go backwards? */
    465 
    466     gap = POINTER_GAP(frmPkt, frmPkt->pullp, frmPkt->pushBlkp);
    467     if (fCnt > gap)                         /* Limit movement      */
    468       fCnt = gap;
    469 
    470     /* Can it go forwards? */
    471 
    472     gap = POINTER_GAP(frmPkt, frmPkt->pushp, frmPkt->pullp);
    473     if (fCnt < -gap)                         /* Limit movement      */
    474       fCnt = -gap;
    475 
    476     frmPkt->pullp = FIX_FRAME_POINTER(frmPkt,
    477                                       frmPkt->pullp - fCnt * frmPkt->frameSize);
    478     frmPkt->pullTime -= fCnt;
    479 
    480   }
    481   else  /* wrt Newest Frame */
    482   {
    483     /************
    484     * Absolute *
    485     ************/
    486 
    487     /* ASSERT(fCnt); moved from the above block, do we need this? */
    488     ASSERT(frmPkt->isCollecting != FB_DEAD);
    489 
    490     gap = POINTER_GAP(frmPkt, frmPkt->pushp, frmPkt->pushBlkp);
    491 
    492     if (fCnt > gap)                         /* Limit movement      */
    493       fCnt = gap;
    494 
    495     frmPkt->pullp = FIX_FRAME_POINTER(frmPkt,
    496                                       frmPkt->pushp - fCnt * frmPkt->frameSize);
    497     frmPkt->pullTime = frmPkt->pushTime - fCnt;
    498 
    499   }
    500 
    501   return (fCnt);
    502   ;
    503 }
    504 
    505 /************************************************************************
    506  * Returns Pointer to Oldest unread REC frame                           *
    507  ************************************************************************
    508  *
    509  * Arguments: "frmPkt"  Frame Buffer Pointer
    510  *
    511  * Retunrs:   featdata*   Pointer to newest frame
    512  *                          NULL on Error
    513  *
    514  ************************************************************************/
    515 
    516 featdata* currentRECframePtr(fepFramePkt* frmPkt)
    517 {
    518   ASSERT(frmPkt);
    519   if (frmPkt->pushp == frmPkt->pushBlkp)            /* uninitialized? */
    520     return NULL;
    521   return ((featdata *)frmPkt->pullp);
    522 }
    523 
    524 /************************************************************************
    525  * Returns Pointer to Newest Complete frame of given channel            *
    526  ************************************************************************
    527  *
    528  * Arguments: "frmPkt"  Frame Buffer Pointer
    529  *
    530  * Retunrs:   featdata*   Pointer to newest frame
    531  *                          NULL on Error.
    532  *
    533  ************************************************************************/
    534 
    535 featdata* currentFEPframePtr(fepFramePkt* frmPkt)
    536 {
    537   featdata* frmPtr;
    538 
    539   ASSERT(frmPkt);
    540   frmPtr = frmPkt->pushp;  /* Where is FEP?    */
    541   if (frmPtr == NULL)
    542     return NULL;
    543   (void) decThisFramePtr(frmPkt, &frmPtr);/* Move backwards   */
    544   return frmPtr;
    545 }
    546 
    547 /************************************************************************
    548  * Moves REC's Frame Pointer backwards one Frame (if it can)            *
    549  ************************************************************************
    550  *
    551  * NOTES
    552  *
    553  * If 'masterREC', 'pullp' is manipulated, otherwise one of the
    554  * multiple recognition pointers, 'auxPullp[]' is used. (not sure about this)
    555  * The pushBlkp is also moved accordingly.
    556  *
    557  ************************************************************************
    558  *
    559  * Arguments: "n"      Channel Number of Selected Frame
    560  *
    561  * Retunrs:   int      Non-zero on error
    562  *
    563  ************************************************************************/
    564 
    565 int incRECframePtr(fepFramePkt* frmPkt)
    566 {
    567   ASSERT(frmPkt);
    568 
    569   /* Ensure that the frame buffer for *
    570    * the channel specified exists     */
    571 
    572   if (frmPkt->pullp == frmPkt->pushp)
    573     return True;
    574 
    575 
    576   frmPkt->pullp = NEXT_FRAME_POINTER(frmPkt, frmPkt->pullp);
    577 
    578   frmPkt->pullTime++;
    579   if (frmPkt->pullTime == 0)  /* Check for wrap and ensure */
    580     frmPkt->pullTime++;     /* that it is never ZERO     */
    581 
    582   /* New 'pushBlkp' */
    583   if (frmPkt->blockLen > 0 && frmPkt->isCollecting == FB_ACTIVE)
    584   {
    585     if (POINTER_GAP(frmPkt, frmPkt->pullp, frmPkt->pushBlkp) >= frmPkt->blockLen)
    586     {
    587       frmPkt->pushBlkp = NEXT_FRAME_POINTER(frmPkt, frmPkt->pushBlkp);
    588     }
    589   }
    590 
    591   return False;
    592 }
    593 
    594 /************************************************************************
    595  * Moves REC's Frame Pointer backwards one Frame (if it can)            *
    596  ************************************************************************
    597  *
    598  * NOTES
    599  *
    600  * If 'masterREC', 'pullp' is manipulated, otherwise one of the
    601  * multiple recognition pointers, 'auxPullp[]' is used. (not sure about this)
    602  * The pushBlkp is also moved accordingly.
    603  *
    604  ************************************************************************
    605  *
    606  * Arguments: "n"      Channel Number of Selected Frame
    607  *
    608  * Retunrs:   int      Non-zero on error
    609  *
    610  ************************************************************************/
    611 
    612 int decRECframePtr(fepFramePkt* frmPkt)
    613 {
    614   ASSERT(frmPkt);
    615 
    616   /* Ensure that the frame buffer for *
    617    * the channel specified exists     */
    618 
    619   /* New 'pullp' */
    620 
    621   if (frmPkt->pullp == frmPkt->pushBlkp) return True;
    622   frmPkt->pullp = PREV_FRAME_POINTER(frmPkt, frmPkt->pullp);
    623   frmPkt->pullTime--;
    624   return False;
    625 }
    626 
    627 /************************************************************************
    628  * Moves a Frame Pointer forwards one Frame (if it can)                 *
    629  ************************************************************************
    630  *
    631  * Arguments: "n"      Channel Number of Selected Frame
    632  *            "parPtr" Current Frame Pointer
    633  *
    634  * Retunrs:   int      Non-zero on error
    635  *                     "parPtr" and "sigPtr" may have changed
    636  *
    637  * Caution:            Does not test to see whether 'parPtr' lies
    638  *                     legally within the appropriate buffer or on an
    639  *                     appropriate valid frame boundary
    640  *
    641  *                     The caller should NEVER modify frame buffer
    642  *                     pointers by hand, always call an RTT-supplied function
    643  *
    644  ************************************************************************/
    645 
    646 static int incThisFramePtr(fepFramePkt* frmPkt, featdata** parPtr)
    647 {
    648   ASSERT(frmPkt);
    649   ASSERT(parPtr);
    650   if (*parPtr == frmPkt->pushp)
    651     return True;
    652   *parPtr = NEXT_FRAME_POINTER(frmPkt, *parPtr);
    653   return False;
    654 }
    655 
    656 /************************************************************************
    657  * Moves a Frame Pointer backwards one Frame (if it can)                *
    658  ************************************************************************
    659  *
    660  * Arguments: "frmPkt" Frame Buffer Pointer
    661  *            "parPtr" Current Frame Pointer
    662  *            "sigPtr" Signal Pointer
    663  *                          Set to NULL if not required
    664  *
    665  * Retunrs:   int      Non-zero on error
    666  *                     "parPtr" may have changed
    667  *
    668  * Caution:            Checks for bound within pushBlkp.
    669  *                     The caller should NEVER modify frame buffer
    670  *                     pointers by hand, always call an RTT-supplied function
    671  *
    672  ************************************************************************/
    673 
    674 static int decThisFramePtr(fepFramePkt* frmPkt, featdata** parPtr)
    675 {
    676   ASSERT(frmPkt);
    677   ASSERT(parPtr);
    678   if (*parPtr == frmPkt->pushBlkp)
    679     return True;
    680   *parPtr = PREV_FRAME_POINTER(frmPkt, *parPtr);
    681   return False;
    682 }
    683 
    684 /************************************************************************
    685  ************************************************************************/
    686 
    687 featdata getVoicingCode(fepFramePkt* frmPkt, featdata *frmptr)
    688 {
    689   ASSERT(frmPkt);
    690   frmptr = CHECK_BOUND(frmPkt, frmptr);
    691   if (frmptr && frmPkt->haveVoiced)
    692     return (frmptr[frmPkt->uttDim]);
    693   else
    694     return (0);
    695 }
    696 
    697 /************************************************************************
    698  ************************************************************************/
    699 
    700 void setVoicingCode(fepFramePkt* frmPkt, featdata *frmptr, featdata vcode)
    701 {
    702   ASSERT(frmPkt);
    703   frmptr = CHECK_BOUND(frmPkt, frmptr);
    704   if (frmptr && frmPkt->haveVoiced)
    705     frmptr[frmPkt->uttDim] =
    706       SET_VOICING_CODES(frmptr[frmPkt->uttDim], vcode);
    707   return;
    708 }
    709 
    710 /************************************************************************
    711  ************************************************************************/
    712 
    713 void clearC0Entries(fepFramePkt* frmPkt)
    714 {
    715   ASSERT(frmPkt);
    716   frmPkt->maxC0 = 0;           /*  Assuming a normal range of 0 - 255 */
    717   frmPkt->minC0 = 255;
    718   return;
    719 }
    720 
    721 int get_background_statistics(fepFramePkt *frmPkt, int start, int end,
    722                               spect_dist_info **spec, int num,
    723                               int relative_to_pullp)
    724 {
    725   int len, /* count= 0, */ num_frames = 0;
    726   int ii, jj, got;
    727   featdata  *frame_ptr;
    728 #ifndef NDEBUG
    729   featdata  *base_ptr = NULL;
    730 #endif
    731 
    732   ASSERT(frmPkt);
    733   ASSERT(spec);
    734   if (!frmPkt->haveVoiced) return(0);
    735   if (start == end || (start == 0 && !relative_to_pullp))
    736     return (0);
    737 
    738   /*  Cannot access the frames
    739   */
    740   if (relative_to_pullp && getBlockGap(frmPkt) < start)
    741     return (0);
    742 
    743   ASSERT(base_ptr = frmPkt->pullp);
    744   got = setRECframePtr(frmPkt, end, relative_to_pullp);
    745   if (got != end)
    746   {
    747     (void) setRECframePtr(frmPkt, -got, relative_to_pullp);
    748     ASSERT(base_ptr == currentRECframePtr(frmPkt));
    749     return (0);
    750   }
    751   len = start - end;
    752 
    753   for (ii = 0; ii < len; ii++)
    754   {
    755     decRECframePtr(frmPkt);
    756     frame_ptr   = currentRECframePtr(frmPkt);
    757 #if DEBUG
    758     log_report("%d %d %x\n", frame_ptr[0],
    759                frame_ptr[frmPkt->uttDim], frame_ptr);
    760 #endif
    761     if ((frame_ptr[frmPkt->uttDim] & BELOW_THRESHOLD_BIT))
    762     {
    763       num_frames++;
    764       for (jj = 0; jj < num; jj++)
    765       {
    766         ASSERT(spec[jj]);
    767         add_distribution_data(spec[jj], (int) frame_ptr[jj]);
    768       }
    769     }
    770   }
    771 #if DEBUG
    772   log_report("End of chunk\n");
    773 #endif
    774 
    775   /* Put it back in the same place !
    776   */
    777   if (start != 0)
    778     (void) setRECframePtr(frmPkt, -start, relative_to_pullp);
    779   ASSERT(base_ptr == currentRECframePtr(frmPkt));
    780   return (num_frames);
    781 }
    782 
    783 void utterance_detection_fixup(fepFramePkt *frmPkt, featdata **last_pushp,
    784                                int voice_duration, int quite_duration, int unsure_duration)
    785 {
    786   featdata  *fram;
    787   long   gotstat, count, voistat;
    788   featdata  *fepFrmPtr, *recFrmPtr, *last_push, voice_result;
    789 
    790   /* Adjust for delay in decision making by voicing_analysis
    791   */
    792   ASSERT(frmPkt);
    793   ASSERT(last_pushp);
    794   fepFrmPtr = currentFEPframePtr(frmPkt);
    795   last_push = *last_pushp;
    796   if (last_push == fepFrmPtr)
    797     return;
    798 
    799   recFrmPtr = currentRECframePtr(frmPkt);
    800   if (last_push == NULL)
    801   {
    802     last_push = recFrmPtr;
    803     voistat = FAST_MATCH_DATA(getVoicingCode(frmPkt, last_push));
    804   }
    805   else if (decThisFramePtr(frmPkt, &last_push) == False)
    806   {
    807     voistat = FAST_MATCH_DATA(getVoicingCode(frmPkt, last_push));
    808     (void) incThisFramePtr(frmPkt, &last_push);
    809   }
    810   else
    811     voistat = FAST_MATCH_DATA(getVoicingCode(frmPkt, last_push));
    812 
    813   while (last_push != fepFrmPtr)
    814   {
    815 
    816     gotstat = FAST_MATCH_DATA(getVoicingCode(frmPkt, last_push));
    817     if (gotstat != voistat)
    818     {
    819       /*  Voicing status has changed
    820       */
    821       fram = last_push;
    822       voice_result = getVoicingCode(frmPkt, fram);
    823       if (FAST_BIT_SET(voice_result))
    824       {
    825         for (count = voice_duration; count > 0 && fram != recFrmPtr;
    826              count--)
    827         {
    828           if (decThisFramePtr(frmPkt, &fram) != False)
    829             break;
    830 #if DEBUG_REWIND
    831           log_report("U: voice rewind at %d was %x\n", frmPkt->pullTime
    832                      + POINTER_GAP(frmPkt, fram, recFrmPtr),
    833                      getVoicingCode(frmPkt, fram));
    834 #endif
    835           setVoicingCode(frmPkt, fram, REC_VOICE_BIT);
    836         }
    837 
    838         /* set to unsure for start period of voicing
    839         */
    840         for (count = 0; count < unsure_duration && fram != recFrmPtr;
    841              count++)
    842         {
    843           if (decThisFramePtr(frmPkt, &fram) != False)
    844             break;
    845 #if DEBUG_REWIND
    846           log_report("U: unsure rewind at %d was %x\n", frmPkt->pullTime
    847                      + POINTER_GAP(frmPkt, fram, recFrmPtr),
    848                      getVoicingCode(frmPkt, fram));
    849 #endif
    850           setVoicingCode(frmPkt, fram, REC_UNSURE_BIT);
    851         }
    852       }
    853 
    854       else if (QUIET_BIT_SET(voice_result))
    855       {
    856         for (count = quite_duration; count > 0 && fram != recFrmPtr;
    857              count--)
    858         {
    859           if (decThisFramePtr(frmPkt, &fram) != False)
    860             break;
    861 #if DEBUG_REWIND
    862           log_report("U: quiet rewind at %d was %x\n", frmPkt->pullTime
    863                      + POINTER_GAP(frmPkt, fram, recFrmPtr),
    864                      getVoicingCode(frmPkt, fram));
    865 #endif
    866           setVoicingCode(frmPkt, fram, REC_QUIET_BIT);
    867         }
    868       }
    869 
    870       voistat = gotstat;
    871     }
    872 
    873     /* copy to recognizer bits if status not changed */
    874 #if DEBUG_REWIND
    875     log_report("U: copying at %d was %x\n", frmPkt->pullTime
    876                + POINTER_GAP(frmPkt, last_push, recFrmPtr),
    877                getVoicingCode(frmPkt, last_push));
    878 #endif
    879     if (QUIET_BIT_SET(getVoicingCode(frmPkt, last_push)))
    880       setVoicingCode(frmPkt, last_push, REC_QUIET_BIT);
    881     else if (FAST_BIT_SET(getVoicingCode(frmPkt, last_push)))
    882       setVoicingCode(frmPkt, last_push, REC_VOICE_BIT);
    883     else
    884       setVoicingCode(frmPkt, last_push, REC_UNSURE_BIT);
    885 
    886     if (incThisFramePtr(frmPkt, &last_push) != False) break;
    887   }
    888 
    889   *last_pushp = last_push;
    890   return;
    891 }
    892 
    893 int rec_frame_voicing_status(fepFramePkt *frmPkt)
    894 {
    895   ASSERT(frmPkt);
    896   return (getVoicingCode(frmPkt, (featdata *)frmPkt->pullp));
    897 }
    898