00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 267492 $")
00033
00034 #include "asterisk/lock.h"
00035 #include "asterisk/linkedlists.h"
00036 #include "asterisk/module.h"
00037 #include "asterisk/config.h"
00038 #include "asterisk/translate.h"
00039 #include "asterisk/utils.h"
00040
00041 #define WANT_ASM
00042 #include "log2comp.h"
00043
00044
00045
00046
00047 #if defined(NOT_BLI)
00048 # if defined(_MSC_VER)
00049 typedef __int64 sint64;
00050 # elif defined(__GNUC__)
00051 typedef long long sint64;
00052 # else
00053 # error 64-bit integer type is not defined for your compiler/platform
00054 # endif
00055 #endif
00056
00057 #define BUFFER_SAMPLES 8096
00058 #define BUF_SHIFT 5
00059
00060
00061 #include "asterisk/slin.h"
00062 #include "ex_g726.h"
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 struct g726_state {
00074 long yl;
00075 int yu;
00076 int dms;
00077 int dml;
00078 int ap;
00079 int a[2];
00080
00081 int b[6];
00082
00083 int pk[2];
00084
00085 int dq[6];
00086
00087
00088 int sr[2];
00089
00090
00091 int td;
00092 };
00093
00094 static int qtab_721[7] = {-124, 80, 178, 246, 300, 349, 400};
00095
00096
00097
00098
00099 static int _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425,
00100 425, 373, 323, 273, 213, 135, 4, -2048};
00101
00102
00103 static int _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122,
00104 1122, 355, 198, 112, 64, 41, 18, -12};
00105
00106
00107
00108
00109
00110 static int _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00,
00111 0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0};
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 static void g726_init_state(struct g726_state *state_ptr)
00122 {
00123 int cnta;
00124
00125 state_ptr->yl = 34816;
00126 state_ptr->yu = 544;
00127 state_ptr->dms = 0;
00128 state_ptr->dml = 0;
00129 state_ptr->ap = 0;
00130 for (cnta = 0; cnta < 2; cnta++) {
00131 state_ptr->a[cnta] = 0;
00132 state_ptr->pk[cnta] = 0;
00133 #ifdef NOT_BLI
00134 state_ptr->sr[cnta] = 1;
00135 #else
00136 state_ptr->sr[cnta] = 32;
00137 #endif
00138 }
00139 for (cnta = 0; cnta < 6; cnta++) {
00140 state_ptr->b[cnta] = 0;
00141 #ifdef NOT_BLI
00142 state_ptr->dq[cnta] = 1;
00143 #else
00144 state_ptr->dq[cnta] = 32;
00145 #endif
00146 }
00147 state_ptr->td = 0;
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 static int quan(int val, int *table, int size)
00159 {
00160 int i;
00161
00162 for (i = 0; i < size && val >= *table; ++i, ++table)
00163 ;
00164 return (i);
00165 }
00166
00167 #ifdef NOT_BLI
00168
00169
00170
00171
00172
00173
00174
00175 static int predictor_zero(struct g726_state *state_ptr)
00176 {
00177 int i;
00178 sint64 sezi;
00179 for (sezi = 0, i = 0; i < 6; i++)
00180 sezi += (sint64)state_ptr->b[i] * state_ptr->dq[i];
00181 return (int)(sezi >> 13) / 2 ;
00182 }
00183
00184
00185
00186
00187
00188
00189
00190 static int predictor_pole(struct g726_state *state_ptr)
00191 {
00192 return (int)(((sint64)state_ptr->a[1] * state_ptr->sr[1] +
00193 (sint64)state_ptr->a[0] * state_ptr->sr[0]) >> 13) / 2 ;
00194 }
00195
00196 #else
00197
00198
00199
00200
00201
00202
00203 static int fmult(int an, int srn)
00204 {
00205 int anmag, anexp, anmant;
00206 int wanexp, wanmant;
00207 int retval;
00208
00209 anmag = (an > 0) ? an : ((-an) & 0x1FFF);
00210 anexp = ilog2(anmag) - 5;
00211 anmant = (anmag == 0) ? 32 :
00212 (anexp >= 0) ? anmag >> anexp : anmag << -anexp;
00213 wanexp = anexp + ((srn >> 6) & 0xF) - 13;
00214
00215 wanmant = (anmant * (srn & 077) + 0x30) >> 4;
00216 retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) :
00217 (wanmant >> -wanexp);
00218
00219 return (((an ^ srn) < 0) ? -retval : retval);
00220 }
00221
00222 static int predictor_zero(struct g726_state *state_ptr)
00223 {
00224 int i;
00225 int sezi;
00226 for (sezi = 0, i = 0; i < 6; i++)
00227 sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]);
00228 return sezi;
00229 }
00230
00231 static int predictor_pole(struct g726_state *state_ptr)
00232 {
00233 return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) +
00234 fmult(state_ptr->a[0] >> 2, state_ptr->sr[0]));
00235 }
00236
00237 #endif
00238
00239
00240
00241
00242
00243
00244
00245 static int step_size(struct g726_state *state_ptr)
00246 {
00247 int y;
00248 int dif;
00249 int al;
00250
00251 if (state_ptr->ap >= 256)
00252 return (state_ptr->yu);
00253 else {
00254 y = state_ptr->yl >> 6;
00255 dif = state_ptr->yu - y;
00256 al = state_ptr->ap >> 2;
00257 if (dif > 0)
00258 y += (dif * al) >> 6;
00259 else if (dif < 0)
00260 y += (dif * al + 0x3F) >> 6;
00261 return (y);
00262 }
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 static int quantize(
00275 int d,
00276 int y,
00277 int *table,
00278 int size)
00279 {
00280 int dqm;
00281 int exp;
00282 int mant;
00283 int dl;
00284 int dln;
00285 int i;
00286
00287
00288
00289
00290
00291
00292 dqm = abs(d);
00293 exp = ilog2(dqm);
00294 if (exp < 0)
00295 exp = 0;
00296 mant = ((dqm << 7) >> exp) & 0x7F;
00297 dl = (exp << 7) | mant;
00298
00299
00300
00301
00302
00303
00304 dln = dl - (y >> 2);
00305
00306
00307
00308
00309
00310
00311 i = quan(dln, table, size);
00312 if (d < 0)
00313 return ((size << 1) + 1 - i);
00314 else if (i == 0)
00315 return ((size << 1) + 1);
00316 else
00317 return (i);
00318 }
00319
00320
00321
00322
00323
00324
00325
00326
00327 static int reconstruct(
00328 int sign,
00329 int dqln,
00330 int y)
00331 {
00332 int dql;
00333 int dex;
00334 int dqt;
00335 int dq;
00336
00337 dql = dqln + (y >> 2);
00338
00339 if (dql < 0) {
00340 #ifdef NOT_BLI
00341 return (sign) ? -1 : 1;
00342 #else
00343 return (sign) ? -0x8000 : 0;
00344 #endif
00345 } else {
00346 dex = (dql >> 7) & 15;
00347 dqt = 128 + (dql & 127);
00348 #ifdef NOT_BLI
00349 dq = ((dqt << 19) >> (14 - dex));
00350 return (sign) ? -dq : dq;
00351 #else
00352 dq = (dqt << 7) >> (14 - dex);
00353 return (sign) ? (dq - 0x8000) : dq;
00354 #endif
00355 }
00356 }
00357
00358
00359
00360
00361
00362
00363 static void update(
00364 int code_size,
00365 int y,
00366 int wi,
00367 int fi,
00368 int dq,
00369 int sr,
00370 int dqsez,
00371 struct g726_state *state_ptr)
00372 {
00373 int cnt;
00374 int mag;
00375 #ifndef NOT_BLI
00376 int exp;
00377 #endif
00378 int a2p=0;
00379 int a1ul;
00380 int pks1;
00381 int fa1;
00382 int tr;
00383 int ylint, thr2, dqthr;
00384 int ylfrac, thr1;
00385 int pk0;
00386
00387 pk0 = (dqsez < 0) ? 1 : 0;
00388
00389 #ifdef NOT_BLI
00390 mag = abs(dq / 0x1000);
00391 #else
00392 mag = dq & 0x7FFF;
00393 #endif
00394
00395 ylint = state_ptr->yl >> 15;
00396 ylfrac = (state_ptr->yl >> 10) & 0x1F;
00397 thr1 = (32 + ylfrac) << ylint;
00398 thr2 = (ylint > 9) ? 31 << 10 : thr1;
00399 dqthr = (thr2 + (thr2 >> 1)) >> 1;
00400 if (state_ptr->td == 0)
00401 tr = 0;
00402 else if (mag <= dqthr)
00403 tr = 0;
00404 else
00405 tr = 1;
00406
00407
00408
00409
00410
00411
00412
00413 state_ptr->yu = y + ((wi - y) >> 5);
00414
00415
00416 if (state_ptr->yu < 544)
00417 state_ptr->yu = 544;
00418 else if (state_ptr->yu > 5120)
00419 state_ptr->yu = 5120;
00420
00421
00422
00423 state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6);
00424
00425
00426
00427
00428 if (tr == 1) {
00429 state_ptr->a[0] = 0;
00430 state_ptr->a[1] = 0;
00431 state_ptr->b[0] = 0;
00432 state_ptr->b[1] = 0;
00433 state_ptr->b[2] = 0;
00434 state_ptr->b[3] = 0;
00435 state_ptr->b[4] = 0;
00436 state_ptr->b[5] = 0;
00437 } else {
00438 pks1 = pk0 ^ state_ptr->pk[0];
00439
00440
00441 a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7);
00442 if (dqsez != 0) {
00443 fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0];
00444 if (fa1 < -8191)
00445 a2p -= 0x100;
00446 else if (fa1 > 8191)
00447 a2p += 0xFF;
00448 else
00449 a2p += fa1 >> 5;
00450
00451 if (pk0 ^ state_ptr->pk[1])
00452
00453 if (a2p <= -12160)
00454 a2p = -12288;
00455 else if (a2p >= 12416)
00456 a2p = 12288;
00457 else
00458 a2p -= 0x80;
00459 else if (a2p <= -12416)
00460 a2p = -12288;
00461 else if (a2p >= 12160)
00462 a2p = 12288;
00463 else
00464 a2p += 0x80;
00465 }
00466
00467
00468 state_ptr->a[1] = a2p;
00469
00470
00471
00472 state_ptr->a[0] -= state_ptr->a[0] >> 8;
00473 if (dqsez != 0) {
00474 if (pks1 == 0)
00475 state_ptr->a[0] += 192;
00476 else
00477 state_ptr->a[0] -= 192;
00478 }
00479
00480 a1ul = 15360 - a2p;
00481 if (state_ptr->a[0] < -a1ul)
00482 state_ptr->a[0] = -a1ul;
00483 else if (state_ptr->a[0] > a1ul)
00484 state_ptr->a[0] = a1ul;
00485
00486
00487 for (cnt = 0; cnt < 6; cnt++) {
00488 if (code_size == 5)
00489 state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9;
00490 else
00491 state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8;
00492 if (mag)
00493 {
00494 if ((dq ^ state_ptr->dq[cnt]) >= 0)
00495 state_ptr->b[cnt] += 128;
00496 else
00497 state_ptr->b[cnt] -= 128;
00498 }
00499 }
00500 }
00501
00502 for (cnt = 5; cnt > 0; cnt--)
00503 state_ptr->dq[cnt] = state_ptr->dq[cnt-1];
00504 #ifdef NOT_BLI
00505 state_ptr->dq[0] = dq;
00506 #else
00507
00508 if (mag == 0) {
00509 state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0x20 - 0x400;
00510 } else {
00511 exp = ilog2(mag) + 1;
00512 state_ptr->dq[0] = (dq >= 0) ?
00513 (exp << 6) + ((mag << 6) >> exp) :
00514 (exp << 6) + ((mag << 6) >> exp) - 0x400;
00515 }
00516 #endif
00517
00518 state_ptr->sr[1] = state_ptr->sr[0];
00519 #ifdef NOT_BLI
00520 state_ptr->sr[0] = sr;
00521 #else
00522
00523 if (sr == 0) {
00524 state_ptr->sr[0] = 0x20;
00525 } else if (sr > 0) {
00526 exp = ilog2(sr) + 1;
00527 state_ptr->sr[0] = (exp << 6) + ((sr << 6) >> exp);
00528 } else if (sr > -0x8000) {
00529 mag = -sr;
00530 exp = ilog2(mag) + 1;
00531 state_ptr->sr[0] = (exp << 6) + ((mag << 6) >> exp) - 0x400;
00532 } else
00533 state_ptr->sr[0] = 0x20 - 0x400;
00534 #endif
00535
00536
00537 state_ptr->pk[1] = state_ptr->pk[0];
00538 state_ptr->pk[0] = pk0;
00539
00540
00541 if (tr == 1)
00542 state_ptr->td = 0;
00543 else if (a2p < -11776)
00544 state_ptr->td = 1;
00545 else
00546 state_ptr->td = 0;
00547
00548
00549
00550
00551 state_ptr->dms += (fi - state_ptr->dms) >> 5;
00552 state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7);
00553
00554 if (tr == 1)
00555 state_ptr->ap = 256;
00556 else if (y < 1536)
00557 state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
00558 else if (state_ptr->td == 1)
00559 state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
00560 else if (abs((state_ptr->dms << 2) - state_ptr->dml) >=
00561 (state_ptr->dml >> 3))
00562 state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
00563 else
00564 state_ptr->ap += (-state_ptr->ap) >> 4;
00565 }
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 static int g726_decode(int i, struct g726_state *state_ptr)
00577 {
00578 int sezi, sez, se;
00579 int y;
00580 int sr;
00581 int dq;
00582 int dqsez;
00583
00584 i &= 0x0f;
00585 #ifdef NOT_BLI
00586 sezi = predictor_zero(state_ptr);
00587 sez = sezi;
00588 se = sezi + predictor_pole(state_ptr);
00589 #else
00590 sezi = predictor_zero(state_ptr);
00591 sez = sezi >> 1;
00592 se = (sezi + predictor_pole(state_ptr)) >> 1;
00593 #endif
00594
00595 y = step_size(state_ptr);
00596
00597 dq = reconstruct(i & 8, _dqlntab[i], y);
00598
00599 #ifdef NOT_BLI
00600 sr = se + dq;
00601 dqsez = dq + sez;
00602 #else
00603 sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq;
00604 dqsez = sr - se + sez;
00605 #endif
00606
00607 update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
00608
00609 #ifdef NOT_BLI
00610 return (sr >> 10);
00611 #else
00612 return (sr << 2);
00613 #endif
00614 }
00615
00616
00617
00618
00619
00620
00621
00622 static int g726_encode(int sl, struct g726_state *state_ptr)
00623 {
00624 int sezi, se, sez;
00625 int d;
00626 int sr;
00627 int y;
00628 int dqsez;
00629 int dq, i;
00630
00631 #ifdef NOT_BLI
00632 sl <<= 10;
00633
00634 sezi = predictor_zero(state_ptr);
00635 sez = sezi;
00636 se = sezi + predictor_pole(state_ptr);
00637 #else
00638 sl >>= 2;
00639
00640 sezi = predictor_zero(state_ptr);
00641 sez = sezi >> 1;
00642 se = (sezi + predictor_pole(state_ptr)) >> 1;
00643 #endif
00644
00645 d = sl - se;
00646
00647
00648 y = step_size(state_ptr);
00649 #ifdef NOT_BLI
00650 d /= 0x1000;
00651 #endif
00652 i = quantize(d, y, qtab_721, 7);
00653
00654 dq = reconstruct(i & 8, _dqlntab[i], y);
00655
00656 #ifdef NOT_BLI
00657 sr = se + dq;
00658 dqsez = dq + sez;
00659 #else
00660 sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq;
00661 dqsez = sr - se + sez;
00662 #endif
00663
00664 update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
00665
00666 return (i);
00667 }
00668
00669
00670
00671
00672
00673
00674 struct g726_coder_pvt {
00675
00676 unsigned char next_flag;
00677 struct g726_state g726;
00678 };
00679
00680
00681 static int lintog726_new(struct ast_trans_pvt *pvt)
00682 {
00683 struct g726_coder_pvt *tmp = pvt->pvt;
00684
00685 g726_init_state(&tmp->g726);
00686
00687 return 0;
00688 }
00689
00690
00691 static int g726aal2tolin_framein (struct ast_trans_pvt *pvt, struct ast_frame *f)
00692 {
00693 struct g726_coder_pvt *tmp = pvt->pvt;
00694 unsigned char *src = f->data.ptr;
00695 int16_t *dst = pvt->outbuf.i16 + pvt->samples;
00696 unsigned int i;
00697
00698 for (i = 0; i < f->datalen; i++) {
00699 *dst++ = g726_decode((src[i] >> 4) & 0xf, &tmp->g726);
00700 *dst++ = g726_decode(src[i] & 0x0f, &tmp->g726);
00701 }
00702
00703 pvt->samples += f->samples;
00704 pvt->datalen += 2 * f->samples;
00705
00706 return 0;
00707 }
00708
00709
00710 static int lintog726aal2_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00711 {
00712 struct g726_coder_pvt *tmp = pvt->pvt;
00713 int16_t *src = f->data.ptr;
00714 unsigned int i;
00715
00716 for (i = 0; i < f->samples; i++) {
00717 unsigned char d = g726_encode(src[i], &tmp->g726);
00718
00719 if (tmp->next_flag & 0x80) {
00720 pvt->outbuf.c[pvt->datalen++] = ((tmp->next_flag & 0xf)<< 4) | d;
00721 pvt->samples += 2;
00722 tmp->next_flag = 0;
00723 } else {
00724 tmp->next_flag = 0x80 | d;
00725 }
00726 }
00727
00728 return 0;
00729 }
00730
00731
00732 static int g726tolin_framein (struct ast_trans_pvt *pvt, struct ast_frame *f)
00733 {
00734 struct g726_coder_pvt *tmp = pvt->pvt;
00735 unsigned char *src = f->data.ptr;
00736 int16_t *dst = pvt->outbuf.i16 + pvt->samples;
00737 unsigned int i;
00738
00739 for (i = 0; i < f->datalen; i++) {
00740 *dst++ = g726_decode(src[i] & 0x0f, &tmp->g726);
00741 *dst++ = g726_decode((src[i] >> 4) & 0xf, &tmp->g726);
00742 }
00743
00744 pvt->samples += f->samples;
00745 pvt->datalen += 2 * f->samples;
00746
00747 return 0;
00748 }
00749
00750
00751 static int lintog726_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00752 {
00753 struct g726_coder_pvt *tmp = pvt->pvt;
00754 int16_t *src = f->data.ptr;
00755 unsigned int i;
00756
00757 for (i = 0; i < f->samples; i++) {
00758 unsigned char d = g726_encode(src[i], &tmp->g726);
00759
00760 if (tmp->next_flag & 0x80) {
00761 pvt->outbuf.c[pvt->datalen++] = (d << 4) | (tmp->next_flag & 0xf);
00762 pvt->samples += 2;
00763 tmp->next_flag = 0;
00764 } else {
00765 tmp->next_flag = 0x80 | d;
00766 }
00767 }
00768
00769 return 0;
00770 }
00771
00772 static struct ast_translator g726tolin = {
00773 .name = "g726tolin",
00774 .srcfmt = AST_FORMAT_G726,
00775 .dstfmt = AST_FORMAT_SLINEAR,
00776 .newpvt = lintog726_new,
00777 .framein = g726tolin_framein,
00778 .sample = g726_sample,
00779 .desc_size = sizeof(struct g726_coder_pvt),
00780 .buffer_samples = BUFFER_SAMPLES,
00781 .buf_size = BUFFER_SAMPLES * 2,
00782 };
00783
00784 static struct ast_translator lintog726 = {
00785 .name = "lintog726",
00786 .srcfmt = AST_FORMAT_SLINEAR,
00787 .dstfmt = AST_FORMAT_G726,
00788 .newpvt = lintog726_new,
00789 .framein = lintog726_framein,
00790 .sample = slin8_sample,
00791 .desc_size = sizeof(struct g726_coder_pvt),
00792 .buffer_samples = BUFFER_SAMPLES,
00793 .buf_size = BUFFER_SAMPLES/2,
00794 };
00795
00796 static struct ast_translator g726aal2tolin = {
00797 .name = "g726aal2tolin",
00798 .srcfmt = AST_FORMAT_G726_AAL2,
00799 .dstfmt = AST_FORMAT_SLINEAR,
00800 .newpvt = lintog726_new,
00801 .framein = g726aal2tolin_framein,
00802 .sample = g726_sample,
00803 .desc_size = sizeof(struct g726_coder_pvt),
00804 .buffer_samples = BUFFER_SAMPLES,
00805 .buf_size = BUFFER_SAMPLES * 2,
00806 };
00807
00808 static struct ast_translator lintog726aal2 = {
00809 .name = "lintog726aal2",
00810 .srcfmt = AST_FORMAT_SLINEAR,
00811 .dstfmt = AST_FORMAT_G726_AAL2,
00812 .newpvt = lintog726_new,
00813 .framein = lintog726aal2_framein,
00814 .sample = slin8_sample,
00815 .desc_size = sizeof(struct g726_coder_pvt),
00816 .buffer_samples = BUFFER_SAMPLES,
00817 .buf_size = BUFFER_SAMPLES / 2,
00818 };
00819
00820 static int reload(void)
00821 {
00822 return AST_MODULE_LOAD_SUCCESS;
00823 }
00824
00825 static int unload_module(void)
00826 {
00827 int res = 0;
00828
00829 res |= ast_unregister_translator(&g726tolin);
00830 res |= ast_unregister_translator(&lintog726);
00831
00832 res |= ast_unregister_translator(&g726aal2tolin);
00833 res |= ast_unregister_translator(&lintog726aal2);
00834
00835 return res;
00836 }
00837
00838 static int load_module(void)
00839 {
00840 int res = 0;
00841
00842 res |= ast_register_translator(&g726tolin);
00843 res |= ast_register_translator(&lintog726);
00844
00845 res |= ast_register_translator(&g726aal2tolin);
00846 res |= ast_register_translator(&lintog726aal2);
00847
00848 if (res) {
00849 unload_module();
00850 return AST_MODULE_LOAD_FAILURE;
00851 }
00852
00853 return AST_MODULE_LOAD_SUCCESS;
00854 }
00855
00856 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.726-32kbps G726 Transcoder",
00857 .load = load_module,
00858 .unload = unload_module,
00859 .reload = reload,
00860 );