dyptrk.c

Go to the documentation of this file.
00001 /*
00002 
00003 $Log$
00004 Revision 1.15  2004/06/26 03:50:14  markster
00005 Merge source cleanups (bug #1911)
00006 
00007 Revision 1.14  2003/02/12 13:59:15  matteo
00008 mer feb 12 14:56:57 CET 2003
00009 
00010 Revision 1.1.1.1  2003/02/12 13:59:15  matteo
00011 mer feb 12 14:56:57 CET 2003
00012 
00013 Revision 1.2  2000/01/05 08:20:39  markster
00014 Some OSS fixes and a few lpc changes to make it actually work
00015 
00016  * Revision 1.2  1996/08/20  20:25:29  jaf
00017  * Removed all static local variables that were SAVE'd in the Fortran
00018  * code, and put them in struct lpc10_encoder_state that is passed as an
00019  * argument.
00020  *
00021  * Removed init function, since all initialization is now done in
00022  * init_lpc10_encoder_state().
00023  *
00024  * Revision 1.1  1996/08/19  22:32:26  jaf
00025  * Initial revision
00026  *
00027 
00028 */
00029 
00030 /*  -- translated by f2c (version 19951025).
00031    You must link the resulting object file with the libraries:
00032    -lf2c -lm   (in that order)
00033 */
00034 
00035 #include "f2c.h"
00036 
00037 #ifdef P_R_O_T_O_T_Y_P_E_S
00038 extern int dyptrk_(real *amdf, integer *ltau, integer *minptr, integer *voice, integer *pitch, integer *midx, struct lpc10_encoder_state *st);
00039 /* comlen contrl_ 12 */
00040 #endif
00041 
00042 /* Common Block Declarations */
00043 
00044 extern struct {
00045     integer order, lframe;
00046     logical corrp;
00047 } contrl_;
00048 
00049 #define contrl_1 contrl_
00050 
00051 /* ********************************************************************* */
00052 
00053 /*    DYPTRK Version 52 */
00054 
00055 /* $Log$
00056  * Revision 1.15  2004/06/26 03:50:14  markster
00057  * Merge source cleanups (bug #1911)
00058  *
00059  * Revision 1.14  2003/02/12 13:59:15  matteo
00060  * mer feb 12 14:56:57 CET 2003
00061  *
00062  * Revision 1.1.1.1  2003/02/12 13:59:15  matteo
00063  * mer feb 12 14:56:57 CET 2003
00064  *
00065  * Revision 1.2  2000/01/05 08:20:39  markster
00066  * Some OSS fixes and a few lpc changes to make it actually work
00067  *
00068  * Revision 1.2  1996/08/20  20:25:29  jaf
00069  * Removed all static local variables that were SAVE'd in the Fortran
00070  * code, and put them in struct lpc10_encoder_state that is passed as an
00071  * argument.
00072  *
00073  * Removed init function, since all initialization is now done in
00074  * init_lpc10_encoder_state().
00075  *
00076  * Revision 1.1  1996/08/19  22:32:26  jaf
00077  * Initial revision
00078  * */
00079 /* Revision 1.5  1996/03/26  19:35:35  jaf */
00080 /* Commented out trace statements. */
00081 
00082 /* Revision 1.4  1996/03/19  18:03:22  jaf */
00083 /* Replaced the initialization "DATA P/60*DEPTH*0/" with "DATA P/120*0/", */
00084 /* because apparently Fortran (or at least f2c) can't handle expressions */
00085 /* like that. */
00086 
00087 /* Revision 1.3  1996/03/19  17:38:32  jaf */
00088 /* Added comments about the local variables that should be saved from one */
00089 /* invocation to the next.  None of them were given initial values in the */
00090 /* original code, but from my testing, it appears that initializing them */
00091 /* all to 0 works. */
00092 
00093 /* Added entry INITDYPTRK to reinitialize these local variables. */
00094 
00095 /* Revision 1.2  1996/03/13  16:32:17  jaf */
00096 /* Comments added explaining which of the local variables of this */
00097 /* subroutine need to be saved from one invocation to the next, and which */
00098 /* do not. */
00099 
00100 /* WARNING!  Some of them that should are never given initial values in */
00101 /* this code.  Hopefully, Fortran 77 defines initial values for them, but */
00102 /* even so, giving them explicit initial values is preferable. */
00103 
00104 /* Revision 1.1  1996/02/07 14:45:14  jaf */
00105 /* Initial revision */
00106 
00107 
00108 /* ********************************************************************* */
00109 
00110 /*   Dynamic Pitch Tracker */
00111 
00112 /* Input: */
00113 /*  AMDF   - Average Magnitude Difference Function array */
00114 /*           Indices 1 through LTAU read, and MINPTR */
00115 /*  LTAU   - Number of lags in AMDF */
00116 /*  MINPTR - Location of minimum AMDF value */
00117 /*  VOICE  - Voicing decision */
00118 /* Output: */
00119 /*  PITCH  - Smoothed pitch value, 2 frames delayed */
00120 /*  MIDX   - Initial estimate of current frame pitch */
00121 /* Compile time constant: */
00122 /*  DEPTH  - Number of frames to trace back */
00123 
00124 /* This subroutine maintains local state from one call to the next.  If */
00125 /* you want to switch to using a new audio stream for this filter, or */
00126 /* reinitialize its state for any other reason, call the ENTRY */
00127 /* INITDYPTRK. */
00128 
00129 /* Subroutine */ int dyptrk_(real *amdf, integer *ltau, integer *
00130    minptr, integer *voice, integer *pitch, integer *midx,
00131                 struct lpc10_encoder_state *st)
00132 {
00133     /* Initialized data */
00134 
00135     real *s;
00136     integer *p;
00137     integer *ipoint;
00138     real *alphax;
00139 
00140     /* System generated locals */
00141     integer i__1;
00142 
00143     /* Local variables */
00144     integer pbar;
00145     real sbar;
00146     integer iptr, i__, j;
00147     real alpha, minsc, maxsc;
00148 
00149 /*       Arguments */
00150 /* $Log$
00151  * Revision 1.15  2004/06/26 03:50:14  markster
00152  * Merge source cleanups (bug #1911)
00153  *
00154  * Revision 1.14  2003/02/12 13:59:15  matteo
00155  * mer feb 12 14:56:57 CET 2003
00156  *
00157  * Revision 1.1.1.1  2003/02/12 13:59:15  matteo
00158  * mer feb 12 14:56:57 CET 2003
00159  *
00160  * Revision 1.2  2000/01/05 08:20:39  markster
00161  * Some OSS fixes and a few lpc changes to make it actually work
00162  *
00163  * Revision 1.2  1996/08/20  20:25:29  jaf
00164  * Removed all static local variables that were SAVE'd in the Fortran
00165  * code, and put them in struct lpc10_encoder_state that is passed as an
00166  * argument.
00167  *
00168  * Removed init function, since all initialization is now done in
00169  * init_lpc10_encoder_state().
00170  *
00171  * Revision 1.1  1996/08/19  22:32:26  jaf
00172  * Initial revision
00173  * */
00174 /* Revision 1.3  1996/03/29  22:05:55  jaf */
00175 /* Commented out the common block variables that are not needed by the */
00176 /* embedded version. */
00177 
00178 /* Revision 1.2  1996/03/26  19:34:50  jaf */
00179 /* Added comments indicating which constants are not needed in an */
00180 /* application that uses the LPC-10 coder. */
00181 
00182 /* Revision 1.1  1996/02/07  14:44:09  jaf */
00183 /* Initial revision */
00184 
00185 /*   LPC Processing control variables: */
00186 
00187 /* *** Read-only: initialized in setup */
00188 
00189 /*  Files for Speech, Parameter, and Bitstream Input & Output, */
00190 /*    and message and debug outputs. */
00191 
00192 /* Here are the only files which use these variables: */
00193 
00194 /* lpcsim.f setup.f trans.f error.f vqsetup.f */
00195 
00196 /* Many files which use fdebug are not listed, since it is only used in */
00197 /* those other files conditionally, to print trace statements. */
00198 /*    integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */
00199 /*  LPC order, Frame size, Quantization rate, Bits per frame, */
00200 /*    Error correction */
00201 /* Subroutine SETUP is the only place where order is assigned a value, */
00202 /* and that value is 10.  It could increase efficiency 1% or so to */
00203 /* declare order as a constant (i.e., a Fortran PARAMETER) instead of as 
00204 */
00205 /* a variable in a COMMON block, since it is used in many places in the */
00206 /* core of the coding and decoding routines.  Actually, I take that back. 
00207 */
00208 /* At least when compiling with f2c, the upper bound of DO loops is */
00209 /* stored in a local variable before the DO loop begins, and then that is 
00210 */
00211 /* compared against on each iteration. */
00212 /* Similarly for lframe, which is given a value of MAXFRM in SETUP. */
00213 /* Similarly for quant, which is given a value of 2400 in SETUP.  quant */
00214 /* is used in only a few places, and never in the core coding and */
00215 /* decoding routines, so it could be eliminated entirely. */
00216 /* nbits is similar to quant, and is given a value of 54 in SETUP. */
00217 /* corrp is given a value of .TRUE. in SETUP, and is only used in the */
00218 /* subroutines ENCODE and DECODE.  It doesn't affect the speed of the */
00219 /* coder significantly whether it is .TRUE. or .FALSE., or whether it is 
00220 */
00221 /* a constant or a variable, since it is only examined once per frame. */
00222 /* Leaving it as a variable that is set to .TRUE.  seems like a good */
00223 /* idea, since it does enable some error-correction capability for */
00224 /* unvoiced frames, with no change in the coding rate, and no noticeable 
00225 */
00226 /* quality difference in the decoded speech. */
00227 /*    integer quant, nbits */
00228 /* *** Read/write: variables for debugging, not needed for LPC algorithm 
00229 */
00230 
00231 /*  Current frame, Unstable frames, Output clip count, Max onset buffer, 
00232 */
00233 /*    Debug listing detail level, Line count on listing page */
00234 
00235 /* nframe is not needed for an embedded LPC10 at all. */
00236 /* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */
00237 /* ERROR, which is only called from RCCHK.  When LPC10 is embedded into */
00238 /* an application, I would recommend removing the call to ERROR in RCCHK, 
00239 */
00240 /* and remove ERROR and nunsfm completely. */
00241 /* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in 
00242 */
00243 /* sread.f.  When LPC10 is embedded into an application, one might want */
00244 /* to cause it to be incremented in a routine that takes the output of */
00245 /* SYNTHS and sends it to an audio device.  It could be optionally */
00246 /* displayed, for those that might want to know what it is. */
00247 /* maxosp is never initialized to 0 in SETUP, although it probably should 
00248 */
00249 /* be, and it is updated in subroutine ANALYS.  I doubt that its value */
00250 /* would be of much interest to an application in which LPC10 is */
00251 /* embedded. */
00252 /* listl and lincnt are not needed for an embedded LPC10 at all. */
00253 /*    integer nframe, nunsfm, iclip, maxosp, listl, lincnt */
00254 /*    common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */
00255 /*    common /contrl/ quant, nbits */
00256 /*    common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */
00257 /*    Parameters/constants */
00258 /*       Local variables that need not be saved */
00259 /*       Note that PATH is only used for debugging purposes, and can be */
00260 /*       removed. */
00261 /*       Local state */
00262 /*       It would be a bit more "general" to define S(LTAU), if Fortran */
00263 /*       allows the argument of a function to be used as the dimension of 
00264 */
00265 /*       a local array variable. */
00266 /*       IPOINT is always in the range 0 to DEPTH-1. */
00267 /*       WARNING! */
00268 
00269 /*       In the original version of this subroutine, IPOINT, ALPHAX, */
00270 /*       every element of S, and potentially any element of P with the */
00271 /*       second index value .NE. IPTR were read without being given */
00272 /*       initial values (all indices of P with second index equal to */
00273 /*       IPTR are all written before being read in this subroutine). */
00274 
00275 /*       From examining the code carefully, it appears that all of these 
00276 */
00277 /*       should be saved from one invocation to the next. */
00278 
00279 /*       I've run lpcsim with the "-l 6" option to see all of the */
00280 /*       debugging information that is printed out by this subroutine */
00281 /*       below, and it appears that S, P, IPOINT, and ALPHAX are all */
00282 /*       initialized to 0 (these initial values would likely be different 
00283 */
00284 /*       on different platforms, compilers, etc.).  Given that the output 
00285 */
00286 /*       of the coder sounds reasonable, I'm going to initialize these */
00287 /*       variables to 0 explicitly. */
00288 
00289     s = &(st->s[0]);
00290     p = &(st->p[0]);
00291     ipoint = &(st->ipoint);
00292     alphax = &(st->alphax);
00293 
00294 
00295     /* Parameter adjustments */
00296     if (amdf) {
00297    --amdf;
00298    }
00299 
00300     /* Function Body */
00301 
00302 /*   Calculate the confidence factor ALPHA, used as a threshold slope in 
00303 */
00304 /*   SEESAW.  If unvoiced, set high slope so that every point in P array 
00305 */
00306 /*  is marked as a potential pitch frequency.  A scaled up version (ALPHAX
00307 )*/
00308 /*   is used to maintain arithmetic precision. */
00309     if (*voice == 1) {
00310    *alphax = *alphax * .75f + amdf[*minptr] / 2.f;
00311     } else {
00312    *alphax *= .984375f;
00313     }
00314     alpha = *alphax / 16;
00315     if (*voice == 0 && *alphax < 128.f) {
00316    alpha = 8.f;
00317     }
00318 /* SEESAW: Construct a pitch pointer array and intermediate winner functio
00319 n*/
00320 /*   Left to right pass: */
00321     iptr = *ipoint + 1;
00322     p[iptr * 60 - 60] = 1;
00323     i__ = 1;
00324     pbar = 1;
00325     sbar = s[0];
00326     i__1 = *ltau;
00327     for (i__ = 1; i__ <= i__1; ++i__) {
00328    sbar += alpha;
00329    if (sbar < s[i__ - 1]) {
00330        s[i__ - 1] = sbar;
00331        p[i__ + iptr * 60 - 61] = pbar;
00332    } else {
00333        sbar = s[i__ - 1];
00334        p[i__ + iptr * 60 - 61] = i__;
00335        pbar = i__;
00336    }
00337     }
00338 /*   Right to left pass: */
00339     i__ = pbar - 1;
00340     sbar = s[i__];
00341     while(i__ >= 1) {
00342    sbar += alpha;
00343    if (sbar < s[i__ - 1]) {
00344        s[i__ - 1] = sbar;
00345        p[i__ + iptr * 60 - 61] = pbar;
00346    } else {
00347        pbar = p[i__ + iptr * 60 - 61];
00348        i__ = pbar;
00349        sbar = s[i__ - 1];
00350    }
00351    --i__;
00352     }
00353 /*   Update S using AMDF */
00354 /*   Find maximum, minimum, and location of minimum */
00355     s[0] += amdf[1] / 2;
00356     minsc = s[0];
00357     maxsc = minsc;
00358     *midx = 1;
00359     i__1 = *ltau;
00360     for (i__ = 2; i__ <= i__1; ++i__) {
00361    s[i__ - 1] += amdf[i__] / 2;
00362    if (s[i__ - 1] > maxsc) {
00363        maxsc = s[i__ - 1];
00364    }
00365    if (s[i__ - 1] < minsc) {
00366        *midx = i__;
00367        minsc = s[i__ - 1];
00368    }
00369     }
00370 /*   Subtract MINSC from S to prevent overflow */
00371     i__1 = *ltau;
00372     for (i__ = 1; i__ <= i__1; ++i__) {
00373    s[i__ - 1] -= minsc;
00374     }
00375     maxsc -= minsc;
00376 /*   Use higher octave pitch if significant null there */
00377     j = 0;
00378     for (i__ = 20; i__ <= 40; i__ += 10) {
00379    if (*midx > i__) {
00380        if (s[*midx - i__ - 1] < maxsc / 4) {
00381       j = i__;
00382        }
00383    }
00384     }
00385     *midx -= j;
00386 /*   TRACE: look back two frames to find minimum cost pitch estimate */
00387     j = *ipoint;
00388     *pitch = *midx;
00389     for (i__ = 1; i__ <= 2; ++i__) {
00390    j = j % 2 + 1;
00391    *pitch = p[*pitch + j * 60 - 61];
00392     }
00393 
00394 /*       The following statement subtracts one from IPOINT, mod DEPTH.  I 
00395 */
00396 /*       think the author chose to add DEPTH-1, instead of subtracting 1, 
00397 */
00398 /*       because then it will work even if MOD doesn't work as desired on 
00399 */
00400 /*       negative arguments. */
00401 
00402     *ipoint = (*ipoint + 1) % 2;
00403     return 0;
00404 } /* dyptrk_ */

Generated on Thu Apr 16 06:27:33 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6