4 Revision 1.11 2000/01/05 08:20:39 markster
5 Version 0.1.12 from FTP
7 Revision 1.2 2000/01/05 08:20:39 markster
8 Some OSS fixes and a few lpc changes to make it actually work
10 * Revision 1.2 1996/08/20 20:25:29 jaf
11 * Removed all static local variables that were SAVE'd in the Fortran
12 * code, and put them in struct lpc10_encoder_state that is passed as an
15 * Removed init function, since all initialization is now done in
16 * init_lpc10_encoder_state().
18 * Revision 1.1 1996/08/19 22:32:26 jaf
24 #ifdef P_R_O_T_O_T_Y_P_E_S
25 extern int dyptrk_(real *amdf, integer *ltau, integer *minptr, integer *voice, integer *pitch, integer *midx, struct lpc10_encoder_state *st);
26 /* comlen contrl_ 12 */
29 /* -- translated by f2c (version 19951025).
30 You must link the resulting object file with the libraries:
31 -lf2c -lm (in that order)
36 /* Common Block Declarations */
39 integer order, lframe;
43 #define contrl_1 contrl_
45 /* ********************************************************************* */
47 /* DYPTRK Version 52 */
50 * Revision 1.11 2000/01/05 08:20:39 markster
51 * Version 0.1.12 from FTP
53 /* Revision 1.2 2000/01/05 08:20:39 markster
54 /* Some OSS fixes and a few lpc changes to make it actually work
56 * Revision 1.2 1996/08/20 20:25:29 jaf
57 * Removed all static local variables that were SAVE'd in the Fortran
58 * code, and put them in struct lpc10_encoder_state that is passed as an
61 * Removed init function, since all initialization is now done in
62 * init_lpc10_encoder_state().
64 * Revision 1.1 1996/08/19 22:32:26 jaf
67 /* Revision 1.5 1996/03/26 19:35:35 jaf */
68 /* Commented out trace statements. */
70 /* Revision 1.4 1996/03/19 18:03:22 jaf */
71 /* Replaced the initialization "DATA P/60*DEPTH*0/" with "DATA P/120*0/", */
72 /* because apparently Fortran (or at least f2c) can't handle expressions */
75 /* Revision 1.3 1996/03/19 17:38:32 jaf */
76 /* Added comments about the local variables that should be saved from one */
77 /* invocation to the next. None of them were given initial values in the */
78 /* original code, but from my testing, it appears that initializing them */
81 /* Added entry INITDYPTRK to reinitialize these local variables. */
83 /* Revision 1.2 1996/03/13 16:32:17 jaf */
84 /* Comments added explaining which of the local variables of this */
85 /* subroutine need to be saved from one invocation to the next, and which */
88 /* WARNING! Some of them that should are never given initial values in */
89 /* this code. Hopefully, Fortran 77 defines initial values for them, but */
90 /* even so, giving them explicit initial values is preferable. */
92 /* Revision 1.1 1996/02/07 14:45:14 jaf */
93 /* Initial revision */
96 /* ********************************************************************* */
98 /* Dynamic Pitch Tracker */
101 /* AMDF - Average Magnitude Difference Function array */
102 /* Indices 1 through LTAU read, and MINPTR */
103 /* LTAU - Number of lags in AMDF */
104 /* MINPTR - Location of minimum AMDF value */
105 /* VOICE - Voicing decision */
107 /* PITCH - Smoothed pitch value, 2 frames delayed */
108 /* MIDX - Initial estimate of current frame pitch */
109 /* Compile time constant: */
110 /* DEPTH - Number of frames to trace back */
112 /* This subroutine maintains local state from one call to the next. If */
113 /* you want to switch to using a new audio stream for this filter, or */
114 /* reinitialize its state for any other reason, call the ENTRY */
117 /* Subroutine */ int dyptrk_(real *amdf, integer *ltau, integer *
118 minptr, integer *voice, integer *pitch, integer *midx,
119 struct lpc10_encoder_state *st)
121 /* Initialized data */
128 /* System generated locals */
131 /* Local variables */
134 integer path[2], iptr, i__, j;
135 real alpha, minsc, maxsc;
139 * Revision 1.11 2000/01/05 08:20:39 markster
140 * Version 0.1.12 from FTP
142 /* Revision 1.2 2000/01/05 08:20:39 markster
143 /* Some OSS fixes and a few lpc changes to make it actually work
145 * Revision 1.2 1996/08/20 20:25:29 jaf
146 * Removed all static local variables that were SAVE'd in the Fortran
147 * code, and put them in struct lpc10_encoder_state that is passed as an
150 * Removed init function, since all initialization is now done in
151 * init_lpc10_encoder_state().
153 * Revision 1.1 1996/08/19 22:32:26 jaf
156 /* Revision 1.3 1996/03/29 22:05:55 jaf */
157 /* Commented out the common block variables that are not needed by the */
158 /* embedded version. */
160 /* Revision 1.2 1996/03/26 19:34:50 jaf */
161 /* Added comments indicating which constants are not needed in an */
162 /* application that uses the LPC-10 coder. */
164 /* Revision 1.1 1996/02/07 14:44:09 jaf */
165 /* Initial revision */
167 /* LPC Processing control variables: */
169 /* *** Read-only: initialized in setup */
171 /* Files for Speech, Parameter, and Bitstream Input & Output, */
172 /* and message and debug outputs. */
174 /* Here are the only files which use these variables: */
176 /* lpcsim.f setup.f trans.f error.f vqsetup.f */
178 /* Many files which use fdebug are not listed, since it is only used in */
179 /* those other files conditionally, to print trace statements. */
180 /* integer fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */
181 /* LPC order, Frame size, Quantization rate, Bits per frame, */
182 /* Error correction */
183 /* Subroutine SETUP is the only place where order is assigned a value, */
184 /* and that value is 10. It could increase efficiency 1% or so to */
185 /* declare order as a constant (i.e., a Fortran PARAMETER) instead of as
187 /* a variable in a COMMON block, since it is used in many places in the */
188 /* core of the coding and decoding routines. Actually, I take that back.
190 /* At least when compiling with f2c, the upper bound of DO loops is */
191 /* stored in a local variable before the DO loop begins, and then that is
193 /* compared against on each iteration. */
194 /* Similarly for lframe, which is given a value of MAXFRM in SETUP. */
195 /* Similarly for quant, which is given a value of 2400 in SETUP. quant */
196 /* is used in only a few places, and never in the core coding and */
197 /* decoding routines, so it could be eliminated entirely. */
198 /* nbits is similar to quant, and is given a value of 54 in SETUP. */
199 /* corrp is given a value of .TRUE. in SETUP, and is only used in the */
200 /* subroutines ENCODE and DECODE. It doesn't affect the speed of the */
201 /* coder significantly whether it is .TRUE. or .FALSE., or whether it is
203 /* a constant or a variable, since it is only examined once per frame. */
204 /* Leaving it as a variable that is set to .TRUE. seems like a good */
205 /* idea, since it does enable some error-correction capability for */
206 /* unvoiced frames, with no change in the coding rate, and no noticeable
208 /* quality difference in the decoded speech. */
209 /* integer quant, nbits */
210 /* *** Read/write: variables for debugging, not needed for LPC algorithm
213 /* Current frame, Unstable frames, Output clip count, Max onset buffer,
215 /* Debug listing detail level, Line count on listing page */
217 /* nframe is not needed for an embedded LPC10 at all. */
218 /* nunsfm is initialized to 0 in SETUP, and incremented in subroutine */
219 /* ERROR, which is only called from RCCHK. When LPC10 is embedded into */
220 /* an application, I would recommend removing the call to ERROR in RCCHK,
222 /* and remove ERROR and nunsfm completely. */
223 /* iclip is initialized to 0 in SETUP, and incremented in entry SWRITE in
225 /* sread.f. When LPC10 is embedded into an application, one might want */
226 /* to cause it to be incremented in a routine that takes the output of */
227 /* SYNTHS and sends it to an audio device. It could be optionally */
228 /* displayed, for those that might want to know what it is. */
229 /* maxosp is never initialized to 0 in SETUP, although it probably should
231 /* be, and it is updated in subroutine ANALYS. I doubt that its value */
232 /* would be of much interest to an application in which LPC10 is */
234 /* listl and lincnt are not needed for an embedded LPC10 at all. */
235 /* integer nframe, nunsfm, iclip, maxosp, listl, lincnt */
236 /* common /contrl/ fsi, fso, fpi, fpo, fbi, fbo, pbin, fmsg, fdebug */
237 /* common /contrl/ quant, nbits */
238 /* common /contrl/ nframe, nunsfm, iclip, maxosp, listl, lincnt */
239 /* Parameters/constants */
240 /* Local variables that need not be saved */
241 /* Note that PATH is only used for debugging purposes, and can be */
244 /* It would be a bit more "general" to define S(LTAU), if Fortran */
245 /* allows the argument of a function to be used as the dimension of
247 /* a local array variable. */
248 /* IPOINT is always in the range 0 to DEPTH-1. */
251 /* In the original version of this subroutine, IPOINT, ALPHAX, */
252 /* every element of S, and potentially any element of P with the */
253 /* second index value .NE. IPTR were read without being given */
254 /* initial values (all indices of P with second index equal to */
255 /* IPTR are all written before being read in this subroutine). */
257 /* From examining the code carefully, it appears that all of these
259 /* should be saved from one invocation to the next. */
261 /* I've run lpcsim with the "-l 6" option to see all of the */
262 /* debugging information that is printed out by this subroutine */
263 /* below, and it appears that S, P, IPOINT, and ALPHAX are all */
264 /* initialized to 0 (these initial values would likely be different
266 /* on different platforms, compilers, etc.). Given that the output
268 /* of the coder sounds reasonable, I'm going to initialize these */
269 /* variables to 0 explicitly. */
273 ipoint = &(st->ipoint);
274 alphax = &(st->alphax);
277 /* Parameter adjustments */
284 /* Calculate the confidence factor ALPHA, used as a threshold slope in
286 /* SEESAW. If unvoiced, set high slope so that every point in P array
288 /* is marked as a potential pitch frequency. A scaled up version (ALPHAX
290 /* is used to maintain arithmetic precision. */
292 *alphax = *alphax * .75f + amdf[*minptr] / 2.f;
296 alpha = *alphax / 16;
297 if (*voice == 0 && *alphax < 128.f) {
300 /* SEESAW: Construct a pitch pointer array and intermediate winner functio
302 /* Left to right pass: */
304 p[iptr * 60 - 60] = 1;
309 for (i__ = 1; i__ <= i__1; ++i__) {
311 if (sbar < s[i__ - 1]) {
313 p[i__ + iptr * 60 - 61] = pbar;
316 p[i__ + iptr * 60 - 61] = i__;
320 /* Right to left pass: */
325 if (sbar < s[i__ - 1]) {
327 p[i__ + iptr * 60 - 61] = pbar;
329 pbar = p[i__ + iptr * 60 - 61];
335 /* Update S using AMDF */
336 /* Find maximum, minimum, and location of minimum */
342 for (i__ = 2; i__ <= i__1; ++i__) {
343 s[i__ - 1] += amdf[i__] / 2;
344 if (s[i__ - 1] > maxsc) {
347 if (s[i__ - 1] < minsc) {
352 /* Subtract MINSC from S to prevent overflow */
354 for (i__ = 1; i__ <= i__1; ++i__) {
358 /* Use higher octave pitch if significant null there */
360 for (i__ = 20; i__ <= 40; i__ += 10) {
362 if (s[*midx - i__ - 1] < maxsc / 4) {
368 /* TRACE: look back two frames to find minimum cost pitch estimate */
371 for (i__ = 1; i__ <= 2; ++i__) {
373 *pitch = p[*pitch + j * 60 - 61];
374 path[i__ - 1] = *pitch;
377 /* The following statement subtracts one from IPOINT, mod DEPTH. I
379 /* think the author chose to add DEPTH-1, instead of subtracting 1,
381 /* because then it will work even if MOD doesn't work as desired on
383 /* negative arguments. */
385 *ipoint = (*ipoint + 1) % 2;