pitsyn.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. /*
  2. $Log$
  3. Revision 1.16 2004/06/26 03:50:14 markster
  4. Merge source cleanups (bug #1911)
  5. Revision 1.15 2003/11/23 22:14:32 markster
  6. Various warning cleanups
  7. Revision 1.14 2003/02/12 13:59:15 matteo
  8. mer feb 12 14:56:57 CET 2003
  9. Revision 1.1.1.1 2003/02/12 13:59:15 matteo
  10. mer feb 12 14:56:57 CET 2003
  11. Revision 1.2 2000/01/05 08:20:39 markster
  12. Some OSS fixes and a few lpc changes to make it actually work
  13. * Revision 1.2 1996/08/20 20:40:12 jaf
  14. * Removed all static local variables that were SAVE'd in the Fortran
  15. * code, and put them in struct lpc10_decoder_state that is passed as an
  16. * argument.
  17. *
  18. * Removed init function, since all initialization is now done in
  19. * init_lpc10_decoder_state().
  20. *
  21. * Revision 1.1 1996/08/19 22:31:12 jaf
  22. * Initial revision
  23. *
  24. */
  25. /* -- translated by f2c (version 19951025).
  26. You must link the resulting object file with the libraries:
  27. -lf2c -lm (in that order)
  28. */
  29. #include "f2c.h"
  30. #ifdef P_R_O_T_O_T_Y_P_E_S
  31. extern int pitsyn_(integer *order, integer *voice, integer *pitch, real *rms, real *rc, integer *lframe, integer *ivuv, integer *ipiti, real *rmsi, real *rci, integer *nout, real *ratio, struct lpc10_decoder_state *st);
  32. #endif
  33. /* ***************************************************************** */
  34. /* PITSYN Version 53 */
  35. /* $Log$
  36. * Revision 1.16 2004/06/26 03:50:14 markster
  37. * Merge source cleanups (bug #1911)
  38. *
  39. * Revision 1.15 2003/11/23 22:14:32 markster
  40. * Various warning cleanups
  41. *
  42. * Revision 1.14 2003/02/12 13:59:15 matteo
  43. * mer feb 12 14:56:57 CET 2003
  44. *
  45. * Revision 1.1.1.1 2003/02/12 13:59:15 matteo
  46. * mer feb 12 14:56:57 CET 2003
  47. *
  48. * Revision 1.2 2000/01/05 08:20:39 markster
  49. * Some OSS fixes and a few lpc changes to make it actually work
  50. *
  51. * Revision 1.2 1996/08/20 20:40:12 jaf
  52. * Removed all static local variables that were SAVE'd in the Fortran
  53. * code, and put them in struct lpc10_decoder_state that is passed as an
  54. * argument.
  55. *
  56. * Removed init function, since all initialization is now done in
  57. * init_lpc10_decoder_state().
  58. *
  59. * Revision 1.1 1996/08/19 22:31:12 jaf
  60. * Initial revision
  61. * */
  62. /* Revision 1.2 1996/03/25 18:49:07 jaf */
  63. /* Added comments about which indices of array arguments are read or */
  64. /* written. */
  65. /* Rearranged local variable declarations to indicate which need to be */
  66. /* saved from one invocation to the next. Added entry INITPITSYN to */
  67. /* reinitialize local state variables, if desired. */
  68. /* Added lots of comments about proving that the maximum number of pitch */
  69. /* periods (NOUT) that can be returned is 16. The call to STOP that */
  70. /* could happen if NOUT got too large was removed as a result. */
  71. /* Also proved that the total number of samples returned from N calls, */
  72. /* each with identical values of LFRAME, will always be in the range */
  73. /* N*LFRAME-MAXPIT+1 to N*LFRAME. */
  74. /* Revision 1.1 1996/02/07 14:48:18 jaf */
  75. /* Initial revision */
  76. /* ***************************************************************** */
  77. /* Synthesize a single pitch epoch */
  78. /* Input: */
  79. /* ORDER - Synthesis order (number of RC's) */
  80. /* VOICE - Half frame voicing decisions */
  81. /* Indices 1 through 2 read. */
  82. /* LFRAME - Length of speech buffer */
  83. /* Input/Output: */
  84. /* PITCH - Pitch */
  85. /* This value should be in the range MINPIT (20) to MAXPIT */
  86. /* (156), inclusive. */
  87. /* PITCH can be modified under some conditions. */
  88. /* RMS - Energy (can be modified) */
  89. /* RMS is changed to 1 if the value passed in is less than 1. */
  90. /* RC - Reflection coefficients */
  91. /* Indices 1 through ORDER can be temporarily overwritten with */
  92. /* RCO, and then replaced with original values, under some */
  93. /* conditions. */
  94. /* Output: */
  95. /* IVUV - Pitch epoch voicing decisions */
  96. /* Indices (I) of IVUV, IPITI, and RMSI are written, */
  97. /* and indices (J,I) of RCI are written, */
  98. /* where I ranges from 1 to NOUT, and J ranges from 1 to ORDER. */
  99. /* IPITI - Pitch epoch length */
  100. /* RMSI - Pitch epoch energy */
  101. /* RCI - Pitch epoch RC's */
  102. /* NOUT - Number of pitch periods in this frame */
  103. /* This is at least 0, at least 1 if MAXPIT .LT. LFRAME (this */
  104. /* is currently true on every call), and can never be more than */
  105. /* (LFRAME+MAXPIT-1)/PITCH, which is currently 16 with */
  106. /* LFRAME=180, MAXPIT=156, and PITCH .GE. 20, as SYNTHS */
  107. /* guarantees when it calls this subroutine. */
  108. /* RATIO - Previous to present energy ratio */
  109. /* Always assigned a value. */
  110. /* Subroutine */ int pitsyn_(integer *order, integer *voice,
  111. integer *pitch, real *rms, real *rc, integer *lframe, integer *ivuv,
  112. integer *ipiti, real *rmsi, real *rci, integer *nout, real *ratio,
  113. struct lpc10_decoder_state *st)
  114. {
  115. /* Initialized data */
  116. real *rmso;
  117. logical *first;
  118. /* System generated locals */
  119. integer rci_dim1 = 0, rci_offset, i__1, i__2;
  120. real r__1;
  121. /* Builtin functions */
  122. double log(doublereal), exp(doublereal);
  123. /* Local variables */
  124. real alrn, alro, yarc[10], prop;
  125. integer i__, j, vflag, jused, lsamp;
  126. integer *jsamp;
  127. real slope;
  128. integer *ipito;
  129. real uvpit;
  130. integer ip, nl, ivoice;
  131. integer *ivoico;
  132. integer istart;
  133. real *rco;
  134. real xxy;
  135. /* Arguments */
  136. /* $Log$
  137. * Revision 1.16 2004/06/26 03:50:14 markster
  138. * Merge source cleanups (bug #1911)
  139. *
  140. * Revision 1.15 2003/11/23 22:14:32 markster
  141. * Various warning cleanups
  142. *
  143. * Revision 1.14 2003/02/12 13:59:15 matteo
  144. * mer feb 12 14:56:57 CET 2003
  145. *
  146. * Revision 1.1.1.1 2003/02/12 13:59:15 matteo
  147. * mer feb 12 14:56:57 CET 2003
  148. *
  149. * Revision 1.2 2000/01/05 08:20:39 markster
  150. * Some OSS fixes and a few lpc changes to make it actually work
  151. *
  152. * Revision 1.2 1996/08/20 20:40:12 jaf
  153. * Removed all static local variables that were SAVE'd in the Fortran
  154. * code, and put them in struct lpc10_decoder_state that is passed as an
  155. * argument.
  156. *
  157. * Removed init function, since all initialization is now done in
  158. * init_lpc10_decoder_state().
  159. *
  160. * Revision 1.1 1996/08/19 22:31:12 jaf
  161. * Initial revision
  162. * */
  163. /* Revision 1.3 1996/03/29 22:03:47 jaf */
  164. /* Removed definitions for any constants that were no longer used. */
  165. /* Revision 1.2 1996/03/26 19:34:33 jaf */
  166. /* Added comments indicating which constants are not needed in an */
  167. /* application that uses the LPC-10 coder. */
  168. /* Revision 1.1 1996/02/07 14:43:51 jaf */
  169. /* Initial revision */
  170. /* LPC Configuration parameters: */
  171. /* Frame size, Prediction order, Pitch period */
  172. /* Local variables that need not be saved */
  173. /* LSAMP is initialized in the IF (FIRST) THEN clause, but it is */
  174. /* not used the first time through, and it is given a value before
  175. */
  176. /* use whenever FIRST is .FALSE., so it appears unnecessary to */
  177. /* assign it a value when FIRST is .TRUE. */
  178. /* Local state */
  179. /* FIRST - .TRUE. only on first call to PITSYN. */
  180. /* IVOICO - Previous VOICE(2) value. */
  181. /* IPITO - Previous PITCH value. */
  182. /* RMSO - Previous RMS value. */
  183. /* RCO - Previous RC values. */
  184. /* JSAMP - If this routine is called N times with identical values of */
  185. /* LFRAME, then the total length of all pitch periods returned */
  186. /* is always N*LFRAME-JSAMP, and JSAMP is always in the range 0
  187. */
  188. /* to MAXPIT-1 (see below for why this is so). Thus JSAMP is */
  189. /* the number of samples "left over" from the previous call to */
  190. /* PITSYN, that haven't been "used" in a pitch period returned */
  191. /* from this subroutine. Every time this subroutine is called,
  192. */
  193. /* it returns pitch periods with a total length of at most */
  194. /* LFRAME+JSAMP. */
  195. /* IVOICO, IPITO, RCO, and JSAMP need not be assigned an initial value */
  196. /* with a DATA statement, because they are always initialized on the */
  197. /* first call to PITSYN. */
  198. /* FIRST and RMSO should be initialized with DATA statements, because */
  199. /* even on the first call, they are used before being initialized. */
  200. /* Parameter adjustments */
  201. if (rc) {
  202. --rc;
  203. }
  204. if (rci) {
  205. rci_dim1 = *order;
  206. rci_offset = rci_dim1 + 1;
  207. rci -= rci_offset;
  208. }
  209. if (voice) {
  210. --voice;
  211. }
  212. if (ivuv) {
  213. --ivuv;
  214. }
  215. if (ipiti) {
  216. --ipiti;
  217. }
  218. if (rmsi) {
  219. --rmsi;
  220. }
  221. /* Function Body */
  222. ivoico = &(st->ivoico);
  223. ipito = &(st->ipito);
  224. rmso = &(st->rmso);
  225. rco = &(st->rco[0]);
  226. jsamp = &(st->jsamp);
  227. first = &(st->first_pitsyn);
  228. if (*rms < 1.f) {
  229. *rms = 1.f;
  230. }
  231. if (*rmso < 1.f) {
  232. *rmso = 1.f;
  233. }
  234. uvpit = 0.f;
  235. *ratio = *rms / (*rmso + 8.f);
  236. if (*first) {
  237. lsamp = 0;
  238. ivoice = voice[2];
  239. if (ivoice == 0) {
  240. *pitch = *lframe / 4;
  241. }
  242. *nout = *lframe / *pitch;
  243. *jsamp = *lframe - *nout * *pitch;
  244. /* SYNTHS only calls this subroutine with PITCH in the range
  245. 20 */
  246. /* to 156. LFRAME = MAXFRM = 180, so NOUT is somewhere in th
  247. e */
  248. /* range 1 to 9. */
  249. /* JSAMP is "LFRAME mod PITCH", so it is in the range 0 to */
  250. /* (PITCH-1), or 0 to MAXPIT-1=155, after the first call. */
  251. i__1 = *nout;
  252. for (i__ = 1; i__ <= i__1; ++i__) {
  253. i__2 = *order;
  254. for (j = 1; j <= i__2; ++j) {
  255. rci[j + i__ * rci_dim1] = rc[j];
  256. }
  257. ivuv[i__] = ivoice;
  258. ipiti[i__] = *pitch;
  259. rmsi[i__] = *rms;
  260. }
  261. *first = FALSE_;
  262. } else {
  263. vflag = 0;
  264. lsamp = *lframe + *jsamp;
  265. slope = (*pitch - *ipito) / (real) lsamp;
  266. *nout = 0;
  267. jused = 0;
  268. istart = 1;
  269. if (voice[1] == *ivoico && voice[2] == voice[1]) {
  270. if (voice[2] == 0) {
  271. /* SSUV - - 0 , 0 , 0 */
  272. *pitch = *lframe / 4;
  273. *ipito = *pitch;
  274. if (*ratio > 8.f) {
  275. *rmso = *rms;
  276. }
  277. }
  278. /* SSVC - - 1 , 1 , 1 */
  279. slope = (*pitch - *ipito) / (real) lsamp;
  280. ivoice = voice[2];
  281. } else {
  282. if (*ivoico != 1) {
  283. if (*ivoico == voice[1]) {
  284. /* UV2VC2 - - 0 , 0 , 1 */
  285. nl = lsamp - *lframe / 4;
  286. } else {
  287. /* UV2VC1 - - 0 , 1 , 1 */
  288. nl = lsamp - *lframe * 3 / 4;
  289. }
  290. ipiti[1] = nl / 2;
  291. ipiti[2] = nl - ipiti[1];
  292. ivuv[1] = 0;
  293. ivuv[2] = 0;
  294. rmsi[1] = *rmso;
  295. rmsi[2] = *rmso;
  296. i__1 = *order;
  297. for (i__ = 1; i__ <= i__1; ++i__) {
  298. rci[i__ + rci_dim1] = rco[i__ - 1];
  299. rci[i__ + (rci_dim1 << 1)] = rco[i__ - 1];
  300. rco[i__ - 1] = rc[i__];
  301. }
  302. slope = 0.f;
  303. *nout = 2;
  304. *ipito = *pitch;
  305. jused = nl;
  306. istart = nl + 1;
  307. ivoice = 1;
  308. } else {
  309. if (*ivoico != voice[1]) {
  310. /* VC2UV1 - - 1 , 0 , 0 */
  311. lsamp = *lframe / 4 + *jsamp;
  312. } else {
  313. /* VC2UV2 - - 1 , 1 , 0 */
  314. lsamp = *lframe * 3 / 4 + *jsamp;
  315. }
  316. i__1 = *order;
  317. for (i__ = 1; i__ <= i__1; ++i__) {
  318. yarc[i__ - 1] = rc[i__];
  319. rc[i__] = rco[i__ - 1];
  320. }
  321. ivoice = 1;
  322. slope = 0.f;
  323. vflag = 1;
  324. }
  325. }
  326. /* Here is the value of most variables that are used below, depending
  327. on */
  328. /* the values of IVOICO, VOICE(1), and VOICE(2). VOICE(1) and VOICE(2
  329. ) */
  330. /* are input arguments, and IVOICO is the value of VOICE(2) on the */
  331. /* previous call (see notes for the IF (NOUT .NE. 0) statement near th
  332. e */
  333. /* end). Each of these three values is either 0 or 1. These three */
  334. /* values below are given as 3-bit long strings, in the order IVOICO,
  335. */
  336. /* VOICE(1), and VOICE(2). It appears that the code above assumes tha
  337. t */
  338. /* the bit sequences 010 and 101 never occur, but I wonder whether a
  339. */
  340. /* large enough number of bit errors in the channel could cause such a
  341. */
  342. /* thing to happen, and if so, could that cause NOUT to ever go over 1
  343. 1? */
  344. /* Note that all of the 180 values in the table are really LFRAME, but
  345. */
  346. /* 180 has fewer characters, and it makes the table a little more */
  347. /* concrete. If LFRAME is ever changed, keep this in mind. Similarly
  348. , */
  349. /* 135's are 3*LFRAME/4, and 45's are LFRAME/4. If LFRAME is not a */
  350. /* multiple of 4, then the 135 for NL-JSAMP is actually LFRAME-LFRAME/
  351. 4, */
  352. /* and the 45 for NL-JSAMP is actually LFRAME-3*LFRAME/4. */
  353. /* Note that LSAMP-JSAMP is given as the variable. This was just for
  354. */
  355. /* brevity, to avoid adding "+JSAMP" to all of the column entries. */
  356. /* Similarly for NL-JSAMP. */
  357. /* Variable | 000 001 011,010 111 110 100,101 */
  358. /* ------------+-------------------------------------------------- */
  359. /* ISTART | 1 NL+1 NL+1 1 1 1 */
  360. /* LSAMP-JSAMP | 180 180 180 180 135 45 */
  361. /* IPITO | 45 PITCH PITCH oldPITCH oldPITCH oldPITCH */
  362. /* SLOPE | 0 0 0 seebelow 0 0 */
  363. /* JUSED | 0 NL NL 0 0 0 */
  364. /* PITCH | 45 PITCH PITCH PITCH PITCH PITCH */
  365. /* NL-JSAMP | -- 135 45 -- -- -- */
  366. /* VFLAG | 0 0 0 0 1 1 */
  367. /* NOUT | 0 2 2 0 0 0 */
  368. /* IVOICE | 0 1 1 1 1 1 */
  369. /* while_loop | once once once once twice twice */
  370. /* ISTART | -- -- -- -- JUSED+1 JUSED+1 */
  371. /* LSAMP-JSAMP | -- -- -- -- 180 180 */
  372. /* IPITO | -- -- -- -- oldPITCH oldPITCH */
  373. /* SLOPE | -- -- -- -- 0 0 */
  374. /* JUSED | -- -- -- -- ?? ?? */
  375. /* PITCH | -- -- -- -- PITCH PITCH */
  376. /* NL-JSAMP | -- -- -- -- -- -- */
  377. /* VFLAG | -- -- -- -- 0 0 */
  378. /* NOUT | -- -- -- -- ?? ?? */
  379. /* IVOICE | -- -- -- -- 0 0 */
  380. /* UVPIT is always 0.0 on the first pass through the DO WHILE (.TRUE.)
  381. */
  382. /* loop below. */
  383. /* The only possible non-0 value of SLOPE (in column 111) is */
  384. /* (PITCH-IPITO)/FLOAT(LSAMP) */
  385. /* Column 101 is identical to 100. Any good properties we can prove
  386. */
  387. /* for 100 will also hold for 101. Similarly for 010 and 011. */
  388. /* SYNTHS calls this subroutine with PITCH restricted to the range 20
  389. to */
  390. /* 156. IPITO is similarly restricted to this range, after the first
  391. */
  392. /* call. IP below is also restricted to this range, given the */
  393. /* definitions of IPITO, SLOPE, UVPIT, and that I is in the range ISTA
  394. RT */
  395. /* to LSAMP. */
  396. while(TRUE_) {
  397. /* JUSED is the total length of all pitch periods curr
  398. ently */
  399. /* in the output arrays, in samples. */
  400. /* An invariant of the DO I = ISTART,LSAMP loop below,
  401. under */
  402. /* the condition that IP is always in the range 1 thro
  403. ugh */
  404. /* MAXPIT, is: */
  405. /* (I - MAXPIT) .LE. JUSED .LE. (I-1) */
  406. /* Note that the final value of I is LSAMP+1, so that
  407. after */
  408. /* the DO loop is complete, we know: */
  409. /* (LSAMP - MAXPIT + 1) .LE. JUSED .LE. LSAMP */
  410. i__1 = lsamp;
  411. for (i__ = istart; i__ <= i__1; ++i__) {
  412. r__1 = *ipito + slope * i__;
  413. ip = (integer)(r__1 + .5f);
  414. if (uvpit != 0.f) {
  415. ip = (integer)uvpit;
  416. }
  417. if (ip <= i__ - jused) {
  418. ++(*nout);
  419. /* The following check is no longer nece
  420. ssary, now that */
  421. /* we can prove that NOUT will never go
  422. over 16. */
  423. /* IF (NOUT .GT. 16) STOP 'PITSYN: too many epochs'
  424. */
  425. ipiti[*nout] = ip;
  426. *pitch = ip;
  427. ivuv[*nout] = ivoice;
  428. jused += ip;
  429. prop = (jused - ip / 2) / (real) lsamp;
  430. i__2 = *order;
  431. for (j = 1; j <= i__2; ++j) {
  432. alro = (real)log((rco[j - 1] + 1) / (1 - rco[j - 1]));
  433. alrn = (real)log((rc[j] + 1) / (1 - rc[j]));
  434. xxy = alro + prop * (alrn - alro);
  435. xxy = (real)exp(xxy);
  436. rci[j + *nout * rci_dim1] = (xxy - 1) / (xxy + 1);
  437. }
  438. rmsi[*nout] = (real)(log(*rmso) + prop * (log(*rms) - log(*rmso)));
  439. rmsi[*nout] = (real)exp(rmsi[*nout]);
  440. }
  441. }
  442. if (vflag != 1) {
  443. goto L100;
  444. }
  445. /* I want to prove what range UVPIT must lie in after
  446. the */
  447. /* assignments to it below. To do this, I must determ
  448. ine */
  449. /* what range (LSAMP-ISTART) must lie in, after the */
  450. /* assignments to ISTART and LSAMP below. */
  451. /* Let oldLSAMP be the value of LSAMP at this point in
  452. the */
  453. /* execution. This is 135+JSAMP in state 110, or 45+J
  454. SAMP in */
  455. /* states 100 or 101. */
  456. /* Given the loop invariant on JUSED above, we know th
  457. at: */
  458. /* (oldLSAMP - MAXPIT + 1) .LE. JUSED .LE. oldLSAMP */
  459. /* ISTART is one more than this. */
  460. /* Let newLSAMP be the value assigned to LSAMP below.
  461. This */
  462. /* is 180+JSAMP. Thus (newLSAMP-oldLSAMP) is either 4
  463. 5 or */
  464. /* 135, depending on the state. */
  465. /* Thus, the range of newLSAMP-ISTART is: */
  466. /* (newLSAMP-(oldLSAMP+1)) .LE. newLSAMP-ISTART */
  467. /* .LE. (newLSAMP-(oldLSAMP - MAXPIT + 2)) */
  468. /* or: */
  469. /* 46 .LE. newLSAMP-ISTART .LE. 133+MAXPIT .EQ. 289 */
  470. /* Therefore, UVPIT is in the range 23 to 144 after th
  471. e first */
  472. /* assignment to UVPIT below, and after the conditiona
  473. l */
  474. /* assignment, it is in the range 23 to 90. */
  475. /* The important thing is that it is in the range 20 t
  476. o 156, */
  477. /* so that in the loop above, IP is always in this ran
  478. ge. */
  479. vflag = 0;
  480. istart = jused + 1;
  481. lsamp = *lframe + *jsamp;
  482. slope = 0.f;
  483. ivoice = 0;
  484. uvpit = (real) ((lsamp - istart) / 2);
  485. if (uvpit > 90.f) {
  486. uvpit /= 2;
  487. }
  488. *rmso = *rms;
  489. i__1 = *order;
  490. for (i__ = 1; i__ <= i__1; ++i__) {
  491. rc[i__] = yarc[i__ - 1];
  492. rco[i__ - 1] = yarc[i__ - 1];
  493. }
  494. }
  495. L100:
  496. *jsamp = lsamp - jused;
  497. }
  498. /* Given that the maximum pitch period MAXPIT .LT. LFRAME (this is
  499. */
  500. /* currently true on every call, since SYNTHS always sets */
  501. /* LFRAME=180), NOUT will always be .GE. 1 at this point. */
  502. if (*nout != 0) {
  503. *ivoico = voice[2];
  504. *ipito = *pitch;
  505. *rmso = *rms;
  506. i__1 = *order;
  507. for (i__ = 1; i__ <= i__1; ++i__) {
  508. rco[i__ - 1] = rc[i__];
  509. }
  510. }
  511. return 0;
  512. } /* pitsyn_ */