Home | History | Annotate | Download | only in arm
      1 
      2 /* -----------------------------------------------------------------------------------------------------------
      3 Software License for The Fraunhofer FDK AAC Codec Library for Android
      4 
      5  Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Frderung der angewandten Forschung e.V.
      6   All rights reserved.
      7 
      8  1.    INTRODUCTION
      9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
     10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
     11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
     12 
     13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
     14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
     15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
     16 of the MPEG specifications.
     17 
     18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
     19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
     20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
     21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
     22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
     23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
     24 
     25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
     26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
     27 applications information and documentation.
     28 
     29 2.    COPYRIGHT LICENSE
     30 
     31 Redistribution and use in source and binary forms, with or without modification, are permitted without
     32 payment of copyright license fees provided that you satisfy the following conditions:
     33 
     34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
     35 your modifications thereto in source code form.
     36 
     37 You must retain the complete text of this software license in the documentation and/or other materials
     38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
     39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
     40 modifications thereto to recipients of copies in binary form.
     41 
     42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
     43 prior written permission.
     44 
     45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
     46 software or your modifications thereto.
     47 
     48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
     49 and the date of any change. For modified versions of the FDK AAC Codec, the term
     50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
     51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
     52 
     53 3.    NO PATENT LICENSE
     54 
     55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
     56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
     57 respect to this software.
     58 
     59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
     60 by appropriate patent licenses.
     61 
     62 4.    DISCLAIMER
     63 
     64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
     65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
     66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
     68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
     69 or business interruption, however caused and on any theory of liability, whether in contract, strict
     70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
     71 advised of the possibility of such damage.
     72 
     73 5.    CONTACT INFORMATION
     74 
     75 Fraunhofer Institute for Integrated Circuits IIS
     76 Attention: Audio and Multimedia Departments - FDK AAC LL
     77 Am Wolfsmantel 33
     78 91058 Erlangen, Germany
     79 
     80 www.iis.fraunhofer.de/amm
     81 amm-info (at) iis.fraunhofer.de
     82 ----------------------------------------------------------------------------------------------------------- */
     83 
     84 
     85 
     86 #ifdef FUNCTION_dct_IV_func1
     87 
     88 /*
     89    Note: This assembler routine is here, because the ARM926 compiler does
     90          not encode the inline assembler with optimal speed.
     91          With this version, we save 2 cycles per loop iteration.
     92 */
     93 
     94 __asm  void dct_IV_func1(
     95     int i,
     96     const FIXP_SPK *twiddle,
     97     FIXP_DBL *RESTRICT pDat_0,
     98     FIXP_DBL *RESTRICT pDat_1)
     99 {
    100     /* Register map:
    101        r0   i
    102        r1   twiddle
    103        r2   pDat_0
    104        r3   pDat_1
    105        r4   accu1
    106        r5   accu2
    107        r6   accu3
    108        r7   accu4
    109        r8   val_tw
    110        r9   accuX
    111     */
    112     PUSH    {r4-r9}
    113 
    114      /* 44 cycles for 2 iterations = 22 cycles/iteration */
    115 dct_IV_loop1_start
    116 /*  First iteration */
    117     LDR     r8, [r1], #4    // val_tw = *twiddle++;
    118     LDR     r5, [r2, #0]    // accu2 = pDat_0[0]
    119     LDR     r4, [r3, #0]    // accu1 = pDat_1[0]
    120 
    121     SMULWT  r9, r5, r8      // accuX = accu2*val_tw.l
    122     SMULWB  r5, r5, r8      // accu2 = accu2*val_tw.h
    123     RSB     r9, r9, #0      // accuX =-accu2*val_tw.l
    124     SMLAWT  r5, r4, r8, r5  // accu2 = accu2*val_tw.h + accu1*val_tw.l
    125     SMLAWB  r4, r4, r8, r9  // accu1 = accu1*val_tw.h - accu2*val_tw.l
    126 
    127     LDR     r8, [r1], #4    // val_tw = *twiddle++;
    128     LDR     r7, [r3, #-4]   // accu4 = pDat_1[-1]
    129     LDR     r6, [r2, #4]    // accu3 = pDat_0[1]
    130 
    131     SMULWB  r9, r7, r8      // accuX = accu4*val_tw.h
    132     SMULWT  r7, r7, r8      // accu4 = accu4*val_tw.l
    133     RSB     r9, r9, #0      // accuX =-accu4*val_tw.h
    134     SMLAWB  r7, r6, r8, r7  // accu4 = accu4*val_tw.l+accu3*val_tw.h
    135     SMLAWT  r6, r6, r8, r9  // accu3 = accu3*val_tw.l-accu4*val_tw.h
    136 
    137     STR     r5, [r2], #4    // *pDat_0++ = accu2
    138     STR     r4, [r2], #4    // *pDat_0++ = accu1
    139     STR     r6, [r3], #-4   // *pDat_1-- = accu3
    140     STR     r7, [r3], #-4   // *pDat_1-- = accu4
    141 
    142 /*  Second iteration */
    143     LDR     r8, [r1], #4    // val_tw = *twiddle++;
    144     LDR     r5, [r2, #0]    // accu2 = pDat_0[0]
    145     LDR     r4, [r3, #0]    // accu1 = pDat_1[0]
    146 
    147     SMULWT  r9, r5, r8      // accuX = accu2*val_tw.l
    148     SMULWB  r5, r5, r8      // accu2 = accu2*val_tw.h
    149     RSB     r9, r9, #0      // accuX =-accu2*val_tw.l
    150     SMLAWT  r5, r4, r8, r5  // accu2 = accu2*val_tw.h + accu1*val_tw.l
    151     SMLAWB  r4, r4, r8, r9  // accu1 = accu1*val_tw.h - accu2*val_tw.l
    152 
    153     LDR     r8, [r1], #4    // val_tw = *twiddle++;
    154     LDR     r7, [r3, #-4]   // accu4 = pDat_1[-1]
    155     LDR     r6, [r2, #4]    // accu3 = pDat_0[1]
    156 
    157     SMULWB  r9, r7, r8      // accuX = accu4*val_tw.h
    158     SMULWT  r7, r7, r8      // accu4 = accu4*val_tw.l
    159     RSB     r9, r9, #0      // accuX =-accu4*val_tw.h
    160     SMLAWB  r7, r6, r8, r7  // accu4 = accu4*val_tw.l+accu3*val_tw.h
    161     SMLAWT  r6, r6, r8, r9  // accu3 = accu3*val_tw.l-accu4*val_tw.h
    162 
    163     STR     r5, [r2], #4    // *pDat_0++ = accu2
    164     STR     r4, [r2], #4    // *pDat_0++ = accu1
    165     STR     r6, [r3], #-4   // *pDat_1-- = accu3
    166     STR     r7, [r3], #-4   // *pDat_1-- = accu4
    167 
    168     SUBS    r0, r0, #1
    169     BNE     dct_IV_loop1_start
    170 
    171     POP     {r4-r9}
    172 
    173     BX      lr
    174 }
    175 
    176 #endif /* FUNCTION_dct_IV_func1 */
    177 
    178 
    179 #ifdef FUNCTION_dct_IV_func2
    180 
    181 FDK_INLINE
    182 /* __attribute__((noinline)) */
    183 static void dct_IV_func2(
    184     int i,
    185     const FIXP_SPK *twiddle,
    186     FIXP_DBL *pDat_0,
    187     FIXP_DBL *pDat_1,
    188     int inc)
    189 {
    190   FIXP_DBL accu1, accu2, accu3, accu4, accuX;
    191   LONG val_tw;
    192 
    193   accu1 = pDat_1[-2];
    194   accu2 = pDat_1[-1];
    195 
    196   *--pDat_1 = -(pDat_0[1]>>1);
    197   *pDat_0++ = (pDat_0[0]>>1);
    198 
    199   twiddle += inc;
    200 
    201 __asm
    202   {
    203     LDR     val_tw, [twiddle], inc, LSL #2    // val_tw = *twiddle; twiddle += inc
    204     B       dct_IV_loop2_2nd_part
    205 
    206     /* 42 cycles for 2 iterations = 21 cycles/iteration */
    207 dct_IV_loop2:
    208     SMULWT  accuX, accu2, val_tw
    209     SMULWB  accu2, accu2, val_tw
    210     RSB     accuX, accuX, #0
    211     SMLAWB  accuX, accu1, val_tw, accuX
    212     SMLAWT  accu2, accu1, val_tw, accu2
    213     STR     accuX, [pDat_0], #4
    214     STR     accu2, [pDat_1, #-4] !
    215 
    216     LDR     accu4, [pDat_0, #4]
    217     LDR     accu3, [pDat_0]
    218     SMULWB  accuX, accu4, val_tw
    219     SMULWT  accu4, accu4, val_tw
    220     RSB     accuX, accuX, #0
    221     SMLAWT  accuX, accu3, val_tw, accuX
    222     SMLAWB  accu4, accu3, val_tw, accu4
    223 
    224     LDR     accu1, [pDat_1, #-8]
    225     LDR     accu2, [pDat_1, #-4]
    226 
    227     LDR     val_tw, [twiddle], inc, LSL #2    // val_tw = *twiddle; twiddle += inc
    228 
    229     STR     accuX, [pDat_1, #-4] !
    230     STR     accu4, [pDat_0], #4
    231 
    232 dct_IV_loop2_2nd_part:
    233     SMULWT  accuX, accu2, val_tw
    234     SMULWB  accu2, accu2, val_tw
    235     RSB     accuX, accuX, #0
    236     SMLAWB  accuX, accu1, val_tw, accuX
    237     SMLAWT  accu2, accu1, val_tw, accu2
    238     STR     accuX, [pDat_0], #4
    239     STR     accu2, [pDat_1, #-4] !
    240 
    241     LDR     accu4, [pDat_0, #4]
    242     LDR     accu3, [pDat_0]
    243     SMULWB  accuX, accu4, val_tw
    244     SMULWT  accu4, accu4, val_tw
    245     RSB     accuX, accuX, #0
    246     SMLAWT  accuX, accu3, val_tw, accuX
    247     SMLAWB  accu4, accu3, val_tw, accu4
    248 
    249     LDR     accu1, [pDat_1, #-8]
    250     LDR     accu2, [pDat_1, #-4]
    251 
    252     STR     accuX, [pDat_1, #-4] !
    253     STR     accu4, [pDat_0], #4
    254 
    255     LDR     val_tw, [twiddle], inc, LSL #2    // val_tw = *twiddle; twiddle += inc
    256 
    257     SUBS    i, i, #1
    258     BNE     dct_IV_loop2
    259   }
    260 
    261   /* Last Sin and Cos value pair are the same */
    262   accu1 = fMultDiv2(accu1, WTC(0x5a82799a));
    263   accu2 = fMultDiv2(accu2, WTC(0x5a82799a));
    264 
    265   *--pDat_1 = accu1 + accu2;
    266   *pDat_0++ = accu1 - accu2;
    267 }
    268 #endif /* FUNCTION_dct_IV_func2 */
    269 
    270 
    271 #ifdef FUNCTION_dst_IV_func1
    272 
    273 __asm void dst_IV_func1(
    274     int i,
    275     const FIXP_SPK *twiddle,
    276     FIXP_DBL *pDat_0,
    277     FIXP_DBL *pDat_1)
    278 {
    279     /* Register map:
    280        r0   i
    281        r1   twiddle
    282        r2   pDat_0
    283        r3   pDat_1
    284        r4   accu1
    285        r5   accu2
    286        r6   accu3
    287        r7   accu4
    288        r8   val_tw
    289        r9   accuX
    290     */
    291     PUSH    {r4-r9}
    292 
    293 dst_IV_loop1
    294     LDR     r8, [r1], #4               // val_tw = *twiddle++
    295     LDR     r5, [r2]                   // accu2 = pDat_0[0]
    296     LDR     r6, [r2, #4]               // accu3 = pDat_0[1]
    297     RSB     r5, r5, #0                 // accu2 = -accu2
    298     SMULWT  r9, r5, r8                 // accuX = (-accu2)*val_tw.l
    299     LDR     r4, [r3, #-4]              // accu1 = pDat_1[-1]
    300     RSB     r9, r9, #0                 // accuX = -(-accu2)*val_tw.l
    301     SMLAWB  r9, r4, r8, r9             // accuX = accu1*val_tw.h-(-accu2)*val_tw.l
    302     SMULWT  r4, r4, r8                 // accu1 = accu1*val_tw.l
    303     LDR     r7, [r3, #-8]              // accu4 = pDat_1[-2]
    304     SMLAWB  r5, r5, r8, r4             // accu2 = (-accu2)*val_tw.t+accu1*val_tw.l
    305     LDR     r8, [r1], #4               // val_tw = *twiddle++
    306     STR     r5, [r2], #4               // *pDat_0++ = accu2
    307     STR     r9, [r2], #4               // *pDat_0++ = accu1 (accuX)
    308     RSB     r7, r7, #0                 // accu4 = -accu4
    309     SMULWB  r5, r7, r8                 // accu2 = (-accu4)*val_tw.h
    310     SMULWB  r4, r6, r8                 // accu1 = (-accu4)*val_tw.l
    311     RSB     r5, r5, #0                 // accu2 = -(-accu4)*val_tw.h
    312     SMLAWT  r6, r6, r8, r5             // accu3 = (-accu4)*val_tw.l-(-accu3)*val_tw.h
    313     SMLAWT  r7, r7, r8, r4             // accu4 = (-accu3)*val_tw.l+(-accu4)*val_tw.h
    314     STR     r6, [r3, #-4] !            // *--pDat_1 = accu3
    315     STR     r7, [r3, #-4] !            // *--pDat_1 = accu4
    316 
    317     LDR     r8, [r1], #4               // val_tw = *twiddle++
    318     LDR     r5, [r2]                   // accu2 = pDat_0[0]
    319     LDR     r6, [r2, #4]               // accu3 = pDat_0[1]
    320     RSB     r5, r5, #0                 // accu2 = -accu2
    321     SMULWT  r9, r5, r8                 // accuX = (-accu2)*val_tw.l
    322     LDR     r4, [r3, #-4]              // accu1 = pDat_1[-1]
    323     RSB     r9, r9, #0                 // accuX = -(-accu2)*val_tw.l
    324     SMLAWB  r9, r4, r8, r9             // accuX = accu1*val_tw.h-(-accu2)*val_tw.l
    325     SMULWT  r4, r4, r8                 // accu1 = accu1*val_tw.l
    326     LDR     r7, [r3, #-8]              // accu4 = pDat_1[-2]
    327     SMLAWB  r5, r5, r8, r4             // accu2 = (-accu2)*val_tw.t+accu1*val_tw.l
    328     LDR     r8, [r1], #4               // val_tw = *twiddle++
    329     STR     r5, [r2], #4               // *pDat_0++ = accu2
    330     STR     r9, [r2], #4               // *pDat_0++ = accu1 (accuX)
    331     RSB     r7, r7, #0                 // accu4 = -accu4
    332     SMULWB  r5, r7, r8                 // accu2 = (-accu4)*val_tw.h
    333     SMULWB  r4, r6, r8                 // accu1 = (-accu4)*val_tw.l
    334     RSB     r5, r5, #0                 // accu2 = -(-accu4)*val_tw.h
    335     SMLAWT  r6, r6, r8, r5             // accu3 = (-accu4)*val_tw.l-(-accu3)*val_tw.h
    336     SMLAWT  r7, r7, r8, r4             // accu4 = (-accu3)*val_tw.l+(-accu4)*val_tw.h
    337     STR     r6, [r3, #-4] !            // *--pDat_1 = accu3
    338     STR     r7, [r3, #-4] !            // *--pDat_1 = accu4
    339 
    340     SUBS    r0, r0, #4                 // i-= 4
    341     BNE     dst_IV_loop1
    342 
    343     POP     {r4-r9}
    344     BX      lr
    345 }
    346 #endif /* FUNCTION_dst_IV_func1 */
    347 
    348 #ifdef FUNCTION_dst_IV_func2
    349 
    350 FDK_INLINE
    351 /* __attribute__((noinline)) */
    352 static void dst_IV_func2(
    353     int i,
    354     const FIXP_SPK *twiddle,
    355     FIXP_DBL *RESTRICT pDat_0,
    356     FIXP_DBL *RESTRICT pDat_1,
    357     int inc)
    358 {
    359   FIXP_DBL accu1,accu2,accu3,accu4;
    360   LONG val_tw;
    361 
    362   accu4 = pDat_0[0];
    363   accu3 = pDat_0[1];
    364   accu4 >>= 1;
    365   accu3 >>= 1;
    366   accu4 = -accu4;
    367 
    368   accu1 = pDat_1[-1];
    369   accu2 = pDat_1[0];
    370 
    371   *pDat_0++ = accu3;
    372   *pDat_1-- = accu4;
    373 
    374 
    375   __asm
    376   {
    377     B       dst_IV_loop2_2nd_part
    378 
    379     /* 50 cycles for 2 iterations = 25 cycles/iteration */
    380 
    381 dst_IV_loop2:
    382 
    383     LDR     val_tw, [twiddle], inc, LSL #2    // val_tw = *twiddle; twiddle += inc
    384 
    385     RSB     accu2, accu2, #0                  // accu2 = -accu2
    386     RSB     accu1, accu1, #0                  // accu1 = -accu1
    387     SMULWT  accu3, accu2, val_tw              // accu3 = (-accu2)*val_tw.l
    388     SMULWT  accu4, accu1, val_tw              // accu4 = (-accu1)*val_tw.l
    389     RSB     accu3, accu3, #0                  // accu3 = -accu2*val_tw.l
    390     SMLAWB  accu1, accu1, val_tw, accu3       // accu1 = -accu1*val_tw.h-(-accu2)*val_tw.l
    391     SMLAWB  accu2, accu2, val_tw, accu4       // accu2 = (-accu1)*val_tw.l+(-accu2)*val_tw.h
    392     STR     accu1, [pDat_1], #-4              // *pDat_1-- = accu1
    393   	STR     accu2, [pDat_0], #4               // *pDat_0++ = accu2
    394 
    395   	LDR     accu4, [pDat_0]                   // accu4 = pDat_0[0]
    396   	LDR     accu3, [pDat_0, #4]               // accu3 = pDat_0[1]
    397 
    398     RSB     accu4, accu4, #0                  // accu4 = -accu4
    399     RSB     accu3, accu3, #0                  // accu3 = -accu3
    400 
    401     SMULWB  accu1, accu3, val_tw              // accu1 = (-accu3)*val_tw.h
    402     SMULWT  accu2, accu3, val_tw              // accu2 = (-accu3)*val_tw.l
    403     RSB     accu1, accu1, #0                  // accu1 = -(-accu3)*val_tw.h
    404     SMLAWT  accu3, accu4, val_tw, accu1       // accu3 = (-accu4)*val_tw.l-(-accu3)*val_tw.h
    405     SMLAWB  accu4, accu4, val_tw, accu2       // accu4 = (-accu3)*val_tw.l+(-accu4)*val_tw.h
    406 
    407     LDR     accu1, [pDat_1, #-4]              // accu1 = pDat_1[-1]
    408     LDR     accu2, [pDat_1]                   // accu2 = pDat_1[0]
    409 
    410     STR     accu3, [pDat_0], #4               // *pDat_0++ = accu3
    411     STR     accu4, [pDat_1], #-4              // *pDat_1-- = accu4
    412 
    413 dst_IV_loop2_2nd_part:
    414 
    415     LDR     val_tw, [twiddle], inc, LSL #2    // val_tw = *twiddle; twiddle += inc
    416 
    417     RSB     accu2, accu2, #0                  // accu2 = -accu2
    418     RSB     accu1, accu1, #0                  // accu1 = -accu1
    419     SMULWT  accu3, accu2, val_tw              // accu3 = (-accu2)*val_tw.l
    420     SMULWT  accu4, accu1, val_tw              // accu4 = (-accu1)*val_tw.l
    421     RSB     accu3, accu3, #0                  // accu3 = -accu2*val_tw.l
    422     SMLAWB  accu1, accu1, val_tw, accu3       // accu1 = -accu1*val_tw.h-(-accu2)*val_tw.l
    423     SMLAWB  accu2, accu2, val_tw, accu4       // accu2 = (-accu1)*val_tw.l+(-accu2)*val_tw.h
    424     STR     accu1, [pDat_1], #-4              // *pDat_1-- = accu1
    425   	STR     accu2, [pDat_0], #4               // *pDat_0++ = accu2
    426 
    427   	LDR     accu4, [pDat_0]                   // accu4 = pDat_0[0]
    428   	LDR     accu3, [pDat_0, #4]               // accu3 = pDat_0[1]
    429 
    430     RSB     accu4, accu4, #0                  // accu4 = -accu4
    431     RSB     accu3, accu3, #0                  // accu3 = -accu3
    432 
    433     SMULWB  accu1, accu3, val_tw              // accu1 = (-accu3)*val_tw.h
    434     SMULWT  accu2, accu3, val_tw              // accu2 = (-accu3)*val_tw.l
    435     RSB     accu1, accu1, #0                  // accu1 = -(-accu3)*val_tw.h
    436     SMLAWT  accu3, accu4, val_tw, accu1       // accu3 = (-accu4)*val_tw.l-(-accu3)*val_tw.h
    437     SMLAWB  accu4, accu4, val_tw, accu2       // accu4 = (-accu3)*val_tw.l+(-accu4)*val_tw.h
    438 
    439     LDR     accu1, [pDat_1, #-4]              // accu1 = pDat_1[-1]
    440     LDR     accu2, [pDat_1]                   // accu2 = pDat_1[0]
    441 
    442     STR     accu3, [pDat_0], #4               // *pDat_0++ = accu3
    443     STR     accu4, [pDat_1], #-4              // *pDat_1-- = accu4
    444 
    445     SUBS    i, i, #1
    446     BNE     dst_IV_loop2
    447   }
    448 
    449   /* Last Sin and Cos value pair are the same */
    450   accu1 = fMultDiv2(-accu1, WTC(0x5a82799a));
    451   accu2 = fMultDiv2(-accu2, WTC(0x5a82799a));
    452 
    453   *pDat_0 = accu1 + accu2;
    454   *pDat_1 = accu1 - accu2;
    455 }
    456 #endif /* FUNCTION_dst_IV_func2 */
    457