Home | History | Annotate | Download | only in source
      1 @
      2 @ Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3 @
      4 @ Use of this source code is governed by a BSD-style license
      5 @ that can be found in the LICENSE file in the root of the source
      6 @ tree. An additional intellectual property rights grant can be found
      7 @ in the file PATENTS.  All contributing project authors may
      8 @ be found in the AUTHORS file in the root of the source tree.
      9 @
     10 @ Reference code in transform.c. Bit not exact due to how rounding is
     11 @ done in C code and ARM instructions, but quality by assembly code is
     12 @ not worse.
     13 
     14 #include "webrtc/modules/audio_coding/codecs/isac/fix/source/settings.h"
     15 #include "webrtc/system_wrappers/interface/asm_defines.h"
     16 
     17 GLOBAL_FUNCTION WebRtcIsacfix_Spec2TimeNeon
     18 GLOBAL_FUNCTION WebRtcIsacfix_Time2SpecNeon
     19 GLOBAL_LABEL WebRtcIsacfix_kSinTab1
     20 GLOBAL_LABEL WebRtcIsacfix_kCosTab1
     21 GLOBAL_LABEL WebRtcIsacfix_kSinTab2
     22 
     23 @ void WebRtcIsacfix_Time2SpecNeon(int16_t* inre1Q9,
     24 @                                  int16_t* inre2Q9,
     25 @                                  int16_t* outreQ7,
     26 @                                  int16_t* outimQ7);
     27 
     28 DEFINE_FUNCTION WebRtcIsacfix_Time2SpecNeon
     29 .align  2
     30   push {r4-r11,lr}
     31   sub sp, sp, #(16 + FRAMESAMPLES * 4)
     32 
     33   str r0, [sp]                @ inre1Q9
     34   str r1, [sp, #4]            @ inre2Q9
     35   str r2, [sp, #8]            @ outreQ7
     36   str r3, [sp, #12]           @ outimQ7
     37 
     38   mov r8, #(FRAMESAMPLES - 16)
     39   add r12, r0, r8             @ &inreQ7[FRAMESAMPLES / 2 - 4]
     40   add r11, r1, r8             @ &inimQ7[FRAMESAMPLES / 2 - 4]
     41   add r4, sp, #16             @ tmpreQ16;
     42   add r5, sp, #(16 + FRAMESAMPLES * 2)  @ tmpimQ16;
     43 
     44   adr r9, WebRtcIsacfix_kCosTab1
     45 #if defined(__APPLE__)
     46   mov r6, #:lower16:(WebRtcIsacfix_kSinTab1 - WebRtcIsacfix_kCosTab1)
     47 #else
     48   mov r6, #(WebRtcIsacfix_kSinTab1 - WebRtcIsacfix_kCosTab1)
     49 #endif
     50   add r10, r9, r6             @ WebRtcIsacfix_kSinTab1
     51 
     52   vmov.u32 q14, #0            @ Initialize the maximum values for tmpInIm.
     53   vmov.u32 q15, #0            @ Initialize the maximum values for tmpInRe.
     54   movw r6, #16921             @ 0.5 / sqrt(240) in Q19
     55   lsl r6, #5                  @ Together with vqdmulh, net effect is ">> 26".
     56   mov r8, #(FRAMESAMPLES / 2) @ loop counter
     57   vdup.s32 q11, r6
     58 
     59 Time2Spec_TransformAndFindMax:
     60 @ Use ">> 26", instead of ">> 7", ">> 16" and then ">> 3" as in the C code.
     61 
     62   subs r8, #8
     63 
     64   vld1.16 {q0}, [r9, :64]!    @ WebRtcIsacfix_kCosTab1[]
     65   vld1.16 {q2}, [r0]!         @ inre1Q9[]
     66   vmull.s16 q8, d0, d4        @ WebRtcIsacfix_kCosTab1[k] * inre1Q9[k]
     67   vld1.16 {q1}, [r10, :64]!   @ WebRtcIsacfix_kSinTab1[]
     68   vmull.s16 q9, d1, d5        @ WebRtcIsacfix_kCosTab1[k] * inre1Q9[k]
     69   vld1.16 {q3}, [r1]!         @ inre2Q9[]
     70   vmlal.s16 q8, d2, d6        @ WebRtcIsacfix_kSinTab1[k] * inre2Q9[k]
     71   vmlal.s16 q9, d3, d7        @ WebRtcIsacfix_kSinTab1[k] * inre2Q9[k]
     72   vmull.s16 q12, d0, d6       @ WebRtcIsacfix_kCosTab1[k] * inre2Q9[k]
     73   vmull.s16 q13, d1, d7       @ WebRtcIsacfix_kCosTab1[k] * inre2Q9[k]
     74   vmlsl.s16 q12, d2, d4       @ WebRtcIsacfix_kSinTab1[k] * inre1Q9[k]
     75   vmlsl.s16 q13, d3, d5       @ WebRtcIsacfix_kSinTab1[k] * inre1Q9[k]
     76 
     77   vqdmulh.s32 q0, q8, q11     @ xrQ16 * factQ19
     78   vqdmulh.s32 q1, q9, q11     @ xrQ16 * factQ19
     79   vqdmulh.s32 q2, q12, q11    @ xrQ16 * factQ19
     80   vqdmulh.s32 q3, q13, q11    @ xrQ16 * factQ19
     81 
     82   @ Find the absolute maximum in the vectors and store them.
     83   vabs.s32 q8, q0
     84   vabs.s32 q9, q1
     85   vabs.s32 q12, q2
     86   vst1.32  {q0, q1}, [r4]!    @ tmpreQ16[k]
     87   vabs.s32 q13, q3
     88   vmax.u32 q14, q8            @ Use u32 so we don't lose the value 0x80000000.
     89   vmax.u32 q15, q12
     90   vst1.32  {q2, q3}, [r5]!    @ tmpimQ16[k]
     91   vmax.u32 q15, q13
     92   vmax.u32 q14, q9            @ Maximum for outre1Q16[].
     93 
     94   bgt Time2Spec_TransformAndFindMax
     95 
     96   @ Find the maximum value in the Neon registers
     97   vmax.u32 d28, d29
     98   vmax.u32 d30, d31
     99   vpmax.u32 d28, d28, d28     @ Both 32 bits words hold the same value tmpInIm.
    100   vpmax.u32 d30, d30, d30     @ Both 32 bits words hold the same value tmpInRe.
    101   vmax.s32 d30, d28, d30      @ if (yrQ16 > xrQ16) {xrQ16 = yrQ16};
    102 
    103   ldr r4, [sp]                @ inre1Q9
    104   vcls.s32  d31, d30          @ sh = WebRtcSpl_NormW32(tmpInRe);
    105   ldr r5, [sp, #4]            @ inre2Q9
    106   vmov.i32  d30, #24
    107   add r6, sp, #16             @ tmpreQ16;
    108   vsub.s32  d31, d31, d30     @ sh = sh - 24;
    109   add r7, sp, #(16 + FRAMESAMPLES * 2)  @ tmpimQ16;
    110   vdup.s32  q8, d31[0]                  @ sh
    111 
    112   mov r8, #(FRAMESAMPLES / 2) @ loop counter
    113 
    114 Time2Spec_PreFftShift:
    115   subs r8, #16
    116 
    117   vld1.32 {q0, q1}, [r6]!     @ tmpreQ16[]
    118   vrshl.s32 q0, q0, q8
    119   vld1.32 {q2, q3}, [r6]!     @ tmpreQ16[]
    120   vrshl.s32 q1, q1, q8
    121   vld1.32 {q10, q11}, [r7]!   @ tmpimQ16[]
    122   vrshl.s32 q2, q2, q8
    123   vld1.32 {q12, q13}, [r7]!   @ tmpimQ16[]
    124   vrshl.s32 q3, q3, q8
    125   vrshl.s32 q10, q10, q8
    126   vrshl.s32 q11, q11, q8
    127   vrshl.s32 q12, q12, q8
    128   vrshl.s32 q13, q13, q8
    129 
    130   vmovn.s32 d0, q0
    131   vmovn.s32 d1, q1
    132   vmovn.s32 d2, q2
    133   vmovn.s32 d3, q3
    134   vmovn.s32 d4, q10
    135   vmovn.s32 d5, q11
    136   vmovn.s32 d6, q12
    137   vmovn.s32 d7, q13
    138 
    139   vst1.16 {q0, q1}, [r4]!     @ inre1Q9[]
    140   vst1.16 {q2, q3}, [r5]!     @ inre2Q9[]
    141 
    142   bgt Time2Spec_PreFftShift
    143 
    144   vmov.s32 r10, d16[0]        @ Store value of sh.
    145   ldr r0, [sp]                @ inre1Q9
    146   ldr r1, [sp, #4]            @ inre2Q9
    147   mov r2, #-1
    148   CALL_FUNCTION WebRtcIsacfix_FftRadix16Fastest
    149 
    150   vdup.s32 q8, r10            @ sh
    151   mov r8, #(FRAMESAMPLES - 8)
    152   ldr r2, [sp, #8]            @ outreQ7
    153   ldr r3, [sp, #12]           @ outimQ7
    154   add r11, r2, r8             @ &outRe1Q16[FRAMESAMPLES / 2 - 4]
    155   add r12, r3, r8             @ &outim2Q16[FRAMESAMPLES / 2 - 4]
    156   ldr r6, [sp]                @ inre1Q9
    157   ldr r7, [sp, #4]            @ inre2Q9
    158   add r4, r6, r8              @ &inre1Q9[FRAMESAMPLES / 2 - 4]
    159   add r5, r7, r8              @ &inre2Q9[FRAMESAMPLES / 2 - 4]
    160   adr r10, WebRtcIsacfix_kSinTab2
    161 
    162   add r9, r10, #(120*2 - 8)   @ &WebRtcIsacfix_kSinTab2[119 - 4]
    163 
    164   vneg.s32 q15, q8            @ -sh
    165   vmov.i32 q0, #23
    166   vsub.s32 q15, q15, q0       @ -sh - 23
    167 
    168   mov r8, #(FRAMESAMPLES / 4) @ loop counter
    169 
    170   @ Pre-load variables.
    171   vld1.16 {d2}, [r4]          @ inre1Q9[FRAMESAMPLES / 2 - 4 - i]
    172   vld1.16 {d3}, [r5]          @ inre2Q9[FRAMESAMPLES / 2 - 4 - i]
    173   vld1.16 {d0}, [r6]!         @ inre1Q9
    174   vld1.16 {d1}, [r7]!         @ inre2Q9
    175 
    176 Time2Spec_PostFftTransform:
    177 @ By vshl, we effectively did "<< (-sh - 23)", instead of "<< (-sh)",
    178 @ ">> 14" and then ">> 9" as in the C code.
    179 
    180   vld1.16 {d6}, [r9, :64]     @ kCosTab2[]
    181   vneg.s16 d6, d6
    182   vld1.16 {d7}, [r10, :64]!   @ WebRtcIsacfix_kSinTab2[]
    183   vrev64.16 q1, q1            @ Reverse samples in 2nd half of xrQ16[].
    184   vqadd.s16 d4, d0, d2        @ xrQ16
    185   vqsub.s16 d5, d1, d3        @ xiQ16
    186   vrev64.16 d6, d6
    187 
    188   sub r9, #8                  @ Update pointers for kCosTab2[].
    189   sub r4, #8                  @ Update pointers for inre1Q9[].
    190   sub r5, #8                  @ Update pointers for inr22Q9[].
    191   subs r8, #4                 @ Update loop counter.
    192 
    193   vqadd.s16 d1, d1, d3        @ yrQ16
    194   vqsub.s16 d0, d2, d0        @ yiQ16
    195 
    196   vmull.s16 q12, d6, d4       @ kCosTab2[k] * xrQ16
    197   vmlsl.s16 q12, d7, d5       @ WebRtcIsacfix_kSinTab2[k] * xiQ16
    198   vmull.s16 q13, d7, d4       @ WebRtcIsacfix_kSinTab2[k] * xrQ16
    199   vmlal.s16 q13, d6, d5       @ kCosTab2[k] * xiQ16
    200   vmull.s16 q9, d7, d1        @ WebRtcIsacfix_kSinTab2[k] * yrQ16
    201   vmlal.s16 q9, d6, d0        @ kCosTab2[k] * yiQ16
    202   vmull.s16 q10, d7, d0       @ WebRtcIsacfix_kSinTab2[k] * yiQ16
    203   vmlsl.s16 q10, d6, d1       @ kCosTab2[k] * yrQ16
    204 
    205   vshl.s32 q12, q12, q15
    206   vshl.s32 q13, q13, q15
    207   vshl.s32 q9, q9, q15
    208   vshl.s32 q10, q10, q15
    209 
    210   vneg.s32 q8, q9
    211   vld1.16 {d0}, [r6]!         @ inre1Q9
    212   vmovn.s32 d24, q12
    213   vld1.16 {d1}, [r7]!         @ inre2Q9
    214   vmovn.s32 d25, q13
    215   vld1.16 {d2}, [r4]          @ inre1Q9[FRAMESAMPLES / 2 - 4 - i]
    216   vmovn.s32 d5, q10
    217   vld1.16 {d3}, [r5]          @ inre2Q9[FRAMESAMPLES / 2 - 4 - i]
    218   vmovn.s32 d4, q8
    219   vst1.16  {d24}, [r2]!       @ outreQ7[k]
    220   vrev64.16 q2, q2            @ Reverse the order of the samples.
    221   vst1.16  {d25}, [r3]!       @ outimQ7[k]
    222   vst1.16 {d4}, [r11]         @ outreQ7[FRAMESAMPLES / 2 - 1 - k]
    223   vst1.16 {d5}, [r12]         @ outimQ7[FRAMESAMPLES / 2 - 1 - k]
    224   sub r11, #8                 @ Update pointers for outreQ7[].
    225   sub r12, #8                 @ Update pointers for outimQ7[].
    226 
    227   bgt Time2Spec_PostFftTransform
    228 
    229   add sp, sp, #(16 + FRAMESAMPLES * 4)
    230   pop {r4-r11,pc}
    231 
    232 .align  8
    233 @ Cosine table 1 in Q14
    234 WebRtcIsacfix_kCosTab1:
    235 _WebRtcIsacfix_kCosTab1:  @ Label for iOS
    236   .short 16384, 16383, 16378, 16371, 16362, 16349, 16333, 16315
    237   .short 16294, 16270, 16244, 16214, 16182, 16147, 16110, 16069
    238   .short 16026, 15980, 15931, 15880, 15826, 15769, 15709, 15647
    239   .short 15582, 15515, 15444, 15371, 15296, 15218, 15137, 15053
    240   .short 14968, 14879, 14788, 14694, 14598, 14500, 14399, 14295
    241   .short 14189, 14081, 13970, 13856, 13741, 13623, 13502, 13380
    242   .short 13255, 13128, 12998, 12867, 12733, 12597, 12458, 12318
    243   .short 12176, 12031, 11885, 11736, 11585, 11433, 11278, 11121
    244   .short 10963, 10803, 10641, 10477, 10311, 10143, 9974, 9803
    245   .short 9630, 9456, 9280, 9102, 8923, 8743, 8561, 8377
    246   .short 8192, 8006, 7818, 7629, 7438, 7246, 7053, 6859
    247   .short 6664, 6467, 6270, 6071, 5872, 5671, 5469, 5266
    248   .short 5063, 4859, 4653, 4447, 4240, 4033, 3825, 3616
    249   .short 3406, 3196, 2986, 2775, 2563, 2351, 2139, 1926
    250   .short 1713, 1499, 1285, 1072,  857,  643,  429,  214
    251   .short 0, -214, -429, -643, -857, -1072, -1285, -1499
    252   .short -1713, -1926, -2139, -2351, -2563, -2775, -2986, -3196
    253   .short -3406, -3616, -3825, -4033, -4240, -4447, -4653, -4859
    254   .short -5063, -5266, -5469, -5671, -5872, -6071, -6270, -6467
    255   .short -6664, -6859, -7053, -7246, -7438, -7629, -7818, -8006
    256   .short -8192, -8377, -8561, -8743, -8923, -9102, -9280, -9456
    257   .short -9630, -9803, -9974, -10143, -10311, -10477, -10641, -10803
    258   .short -10963, -11121, -11278, -11433, -11585, -11736, -11885, -12031
    259   .short -12176, -12318, -12458, -12597, -12733, -12867, -12998, -13128
    260   .short -13255, -13380, -13502, -13623, -13741, -13856, -13970, -14081
    261   .short -14189, -14295, -14399, -14500, -14598, -14694, -14788, -14879
    262   .short -14968, -15053, -15137, -15218, -15296, -15371, -15444, -15515
    263   .short -15582, -15647, -15709, -15769, -15826, -15880, -15931, -15980
    264   .short -16026, -16069, -16110, -16147, -16182, -16214, -16244, -16270
    265   .short -16294, -16315, -16333, -16349, -16362, -16371, -16378, -16383
    266 
    267 .align  8
    268 @ Sine table 2 in Q14
    269 WebRtcIsacfix_kSinTab2:
    270 _WebRtcIsacfix_kSinTab2:  @ Label for iOS
    271   .short 16384, -16381, 16375, -16367, 16356, -16342, 16325, -16305
    272   .short 16283, -16257, 16229, -16199, 16165, -16129, 16090, -16048
    273   .short 16003, -15956, 15906, -15853, 15798, -15739, 15679, -15615
    274   .short 15549, -15480, 15408, -15334, 15257, -15178, 15095, -15011
    275   .short 14924, -14834, 14741, -14647, 14549, -14449, 14347, -14242
    276   .short 14135, -14025, 13913, -13799, 13682, -13563, 13441, -13318
    277   .short 13192, -13063, 12933, -12800, 12665, -12528, 12389, -12247
    278   .short 12104, -11958, 11810, -11661, 11509, -11356, 11200, -11042
    279   .short 10883, -10722, 10559, -10394, 10227, -10059, 9889, -9717
    280   .short 9543, -9368, 9191, -9013, 8833, -8652, 8469, -8285
    281   .short 8099, -7912, 7723, -7534, 7342, -7150, 6957, -6762
    282   .short 6566, -6369, 6171, -5971, 5771, -5570, 5368, -5165
    283   .short 4961, -4756, 4550, -4344, 4137, -3929, 3720, -3511
    284   .short 3301, -3091, 2880, -2669, 2457, -2245, 2032, -1819
    285   .short 1606, -1392, 1179, -965, 750, -536, 322, -107
    286 
    287 @ Table kCosTab2 was removed since its data is redundant with kSinTab2.
    288 
    289 .align  8
    290 @ Sine table 1 in Q14
    291 WebRtcIsacfix_kSinTab1:
    292 _WebRtcIsacfix_kSinTab1:  @ Label for iOS
    293   .short 0, 214, 429, 643, 857, 1072, 1285, 1499
    294   .short 1713, 1926, 2139, 2351, 2563, 2775, 2986, 3196
    295   .short 3406, 3616, 3825, 4033, 4240, 4447, 4653, 4859
    296   .short 5063, 5266, 5469, 5671, 5872, 6071, 6270, 6467
    297   .short 6664, 6859, 7053, 7246, 7438, 7629, 7818, 8006
    298   .short 8192, 8377, 8561, 8743, 8923, 9102, 9280, 9456
    299   .short 9630, 9803, 9974, 10143, 10311, 10477, 10641, 10803
    300   .short 10963, 11121, 11278, 11433, 11585, 11736, 11885, 12031
    301   .short 12176, 12318, 12458, 12597, 12733, 12867, 12998, 13128
    302   .short 13255, 13380, 13502, 13623, 13741, 13856, 13970, 14081
    303   .short 14189, 14295, 14399, 14500, 14598, 14694, 14788, 14879
    304   .short 14968, 15053, 15137, 15218, 15296, 15371, 15444, 15515
    305   .short 15582, 15647, 15709, 15769, 15826, 15880, 15931, 15980
    306   .short 16026, 16069, 16110, 16147, 16182, 16214, 16244, 16270
    307   .short 16294, 16315, 16333, 16349, 16362, 16371, 16378, 16383
    308   .short 16384, 16383, 16378, 16371, 16362, 16349, 16333, 16315
    309   .short 16294, 16270, 16244, 16214, 16182, 16147, 16110, 16069
    310   .short 16026, 15980, 15931, 15880, 15826, 15769, 15709, 15647
    311   .short 15582, 15515, 15444, 15371, 15296, 15218, 15137, 15053
    312   .short 14968, 14879, 14788, 14694, 14598, 14500, 14399, 14295
    313   .short 14189, 14081, 13970, 13856, 13741, 13623, 13502, 13380
    314   .short 13255, 13128, 12998, 12867, 12733, 12597, 12458, 12318
    315   .short 12176, 12031, 11885, 11736, 11585, 11433, 11278, 11121
    316   .short 10963, 10803, 10641, 10477, 10311, 10143, 9974, 9803
    317   .short 9630, 9456, 9280, 9102, 8923, 8743, 8561, 8377
    318   .short 8192, 8006, 7818, 7629, 7438, 7246, 7053, 6859
    319   .short 6664, 6467, 6270, 6071, 5872, 5671, 5469, 5266
    320   .short 5063, 4859, 4653, 4447, 4240, 4033, 3825, 3616
    321   .short 3406, 3196, 2986, 2775, 2563, 2351, 2139, 1926
    322   .short 1713, 1499, 1285, 1072, 857, 643, 429, 214
    323 
    324 @ void WebRtcIsacfix_Spec2TimeNeon(int16_t *inreQ7,
    325 @                                  int16_t *inimQ7,
    326 @                                  int32_t *outre1Q16,
    327 @                                  int32_t *outre2Q16);
    328 
    329 DEFINE_FUNCTION WebRtcIsacfix_Spec2TimeNeon
    330 .align  2
    331   push {r4-r11,lr}
    332 
    333   sub sp, sp, #16
    334   str r0, [sp]                @ inreQ7
    335   str r1, [sp, #4]            @ inimQ7
    336   str r2, [sp, #8]            @ outre1Q16
    337   str r3, [sp, #12]           @ outre2Q16
    338 
    339   mov r8, #(FRAMESAMPLES - 16)
    340   add r12, r0, r8             @ &inreQ7[FRAMESAMPLES / 2 - 8]
    341   add r11, r1, r8             @ &inimQ7[FRAMESAMPLES / 2 - 8]
    342   add r4, r2, r8, lsl #1      @ &outRe1Q16[FRAMESAMPLES / 2 - 8]
    343   add r6, r3, r8, lsl #1      @ &outRe2Q16[FRAMESAMPLES / 2 - 8]
    344 
    345   mov r8, #(FRAMESAMPLES / 2) @ loop counter
    346   adr r10, WebRtcIsacfix_kSinTab2
    347   add r9, r10, #(120*2 - 16)  @ &WebRtcIsacfix_kSinTab2[119 - 8]
    348 
    349   vpush {q4-q7}
    350 
    351   mov r5, #-32
    352   mov r7, #-16
    353   vmov.u32 q6, #0             @ Initialize the maximum values for tmpInIm.
    354   vmov.u32 q7, #0             @ Initialize the maximum values for tmpInRe.
    355 
    356 TransformAndFindMax:
    357 @ Use ">> 5", instead of "<< 9" and then ">> 14" as in the C code.
    358 @ Bit-exact.
    359 
    360   subs r8, #16
    361 
    362   vld1.16 {q0}, [r9, :64]     @ kCosTab2[]
    363   sub r9, #16
    364   vld1.16 {q2}, [r0]!         @ inreQ7[]
    365   vneg.s16 q0, q0
    366   vld1.16 {q3}, [r1]!         @ inimQ7[]
    367   vrev64.16 d0, d0
    368   vrev64.16 d1, d1
    369   vld1.16 {q1}, [r10, :64]!   @ WebRtcIsacfix_kSinTab2[]
    370   vswp d0, d1
    371 
    372   vmull.s16 q8, d2, d6        @ WebRtcIsacfix_kSinTab2[k] * inimQ7[k]
    373   vmull.s16 q9, d3, d7        @ WebRtcIsacfix_kSinTab2[k] * inimQ7[k]
    374   vmlal.s16 q8, d0, d4        @ kCosTab2[k] * inreQ7[k]
    375   vmlal.s16 q9, d1, d5        @ kCosTab2[k] * inreQ7[k]
    376   vmull.s16 q12, d0, d6       @ kCosTab2[k] * inimQ7[k]
    377   vmull.s16 q13, d1, d7       @ kCosTab2[k] * inimQ7[k]
    378   vmlsl.s16 q12, d2, d4       @ WebRtcIsacfix_kSinTab2[k] * inreQ7[k]
    379   vmlsl.s16 q13, d3, d5       @ WebRtcIsacfix_kSinTab2[k] * inreQ7[k]
    380 
    381   vld1.16 {q2}, [r11], r7     @ inimQ7[FRAMESAMPLES / 2 - 8 + i]
    382   vld1.16 {q3}, [r12], r7     @ inreQ7[FRAMESAMPLES / 2 - 8 + i]
    383 
    384   vrev64.16 q2, q2            @ Reverse the order of the samples
    385   vrev64.16 q3, q3            @ Reverse the order of the samples
    386 
    387   vmull.s16 q14, d2, d5       @ WebRtcIsacfix_kSinTab2[k] * inimQ7[k]
    388   vmull.s16 q15, d3, d4       @ WebRtcIsacfix_kSinTab2[k] * inimQ7[k]
    389   vmlsl.s16 q14, d0, d7       @ q14 -= kCosTab2[k] * inreQ7[k]
    390   vmlsl.s16 q15, d1, d6       @ q15 -= kCosTab2[k] * inreQ7[k]
    391 
    392   vmull.s16 q10, d0, d5       @ kCosTab2[k] * inimQ7[]
    393   vmull.s16 q11, d1, d4       @ kCosTab2[k] * inimQ7[]
    394   vmlal.s16 q10, d2, d7       @ q10 += WebRtcIsacfix_kSinTab2[k] * inreQ7[]
    395   vmlal.s16 q11, d3, d6       @ q11 += WebRtcIsacfix_kSinTab2[k] * inreQ7[]
    396 
    397   vshr.s32 q8, q8, #5         @ xrQ16
    398   vshr.s32 q9, q9, #5         @ xrQ16
    399   vshr.s32 q12, q12, #5       @ xiQ16
    400   vshr.s32 q13, q13, #5       @ xiQ16
    401   vshr.s32 q14, q14, #5       @ yiQ16
    402   vshr.s32 q15, q15, #5       @ yiQ16
    403 
    404   vneg.s32 q10, q10
    405   vneg.s32 q11, q11
    406 
    407   @ xrQ16 - yiQ16
    408   vsub.s32 q0, q8, q14
    409   vsub.s32 q1, q9, q15
    410 
    411   vshr.s32 q10, q10, #5       @ yrQ16
    412   vshr.s32 q11, q11, #5       @ yrQ16
    413 
    414   @ xrQ16 + yiQ16
    415   vadd.s32 q3, q8, q14
    416   vadd.s32 q2, q9, q15
    417 
    418   @ yrQ16 + xiQ16
    419   vadd.s32 q4, q10, q12
    420   vadd.s32 q5, q11, q13
    421 
    422   @ yrQ16 - xiQ16
    423   vsub.s32 q8, q11, q13
    424   vsub.s32 q9, q10, q12
    425 
    426   @ Reverse the order of the samples
    427   vrev64.32 q2, q2
    428   vrev64.32 q3, q3
    429   vrev64.32 q8, q8
    430   vrev64.32 q9, q9
    431   vswp d4, d5
    432   vswp d6, d7
    433 
    434   vst1.32  {q0, q1}, [r2]!    @ outre1Q16[k]
    435   vswp d16, d17
    436   vswp d18, d19
    437   vst1.32  {q2, q3}, [r4], r5 @ outre1Q16[FRAMESAMPLES / 2 - 1 - k]
    438 
    439   @ Find the absolute maximum in the vectors and store them in q6 and q7.
    440   vabs.s32 q10, q0
    441   vabs.s32 q14, q4
    442   vabs.s32 q11, q1
    443   vabs.s32 q15, q5
    444   vabs.s32 q12, q2
    445   vmax.u32 q6, q10            @ Use u32 so we don't lose the value 0x80000000.
    446   vmax.u32 q7, q14            @ Maximum for outre2Q16[].
    447   vabs.s32 q0, q8
    448   vmax.u32 q6, q11            @ Maximum for outre1Q16[].
    449   vmax.u32 q7, q15
    450   vabs.s32 q13, q3
    451   vmax.u32 q6, q12
    452   vmax.u32 q7, q0
    453   vabs.s32 q1, q9
    454   vst1.32  {q4, q5}, [r3]!    @ outre2Q16[k]
    455   vst1.32  {q8, q9}, [r6], r5 @ outre2Q16[FRAMESAMPLES / 2 - 1 - k]
    456   vmax.u32 q6, q13
    457   vmax.u32 q7, q1
    458 
    459   bgt TransformAndFindMax
    460 
    461   adr r10, WebRtcIsacfix_kSinTab1
    462 #if defined(__APPLE__)
    463   mov r2, #:lower16:(WebRtcIsacfix_kSinTab1 - WebRtcIsacfix_kCosTab1)
    464 #else
    465   mov r2, #(WebRtcIsacfix_kSinTab1 - WebRtcIsacfix_kCosTab1)
    466 #endif
    467 
    468   sub r11, r10, r2            @ WebRtcIsacfix_kCosTab1
    469 
    470   @ Find the maximum value in the Neon registers
    471   vmax.u32 d12, d13
    472   vmax.u32 d14, d15
    473   vpmax.u32 d12, d12, d12     @ Both 32 bits words hold the same value tmpInIm.
    474   vpmax.u32 d14, d14, d14     @ Both 32 bits words hold the same value tmpInRe.
    475   vmax.s32 d0, d12, d14       @ if (tmpInIm>tmpInRe) tmpInRe = tmpInIm;
    476 
    477   vpop {q4-q7}
    478 
    479   ldr r4, [sp]                @ inreQ7
    480   vcls.s32  d1, d0            @ sh = WebRtcSpl_NormW32(tmpInRe);
    481   ldr r5, [sp, #4]            @ inimQ7
    482   vmov.i32  d0, #24           @ sh = sh-24;
    483   ldr r6, [sp, #8]            @ outre1Q16
    484   vsub.s32  d1, d1, d0
    485   ldr r7, [sp, #12]           @ outre2Q16
    486   vdup.s32  q8, d1[0]         @ sh
    487 
    488   mov r8, #(FRAMESAMPLES / 2)
    489 
    490 PreFftShift:
    491   subs r8, #16
    492   vld1.32 {q0, q1}, [r6]!     @ outre1Q16[]
    493   vld1.32 {q2, q3}, [r6]!     @ outre1Q16[]
    494   vrshl.s32 q0, q0, q8
    495   vrshl.s32 q1, q1, q8
    496   vrshl.s32 q2, q2, q8
    497   vrshl.s32 q3, q3, q8
    498   vld1.32 {q10, q11}, [r7]!   @ outre2Q16[]
    499   vld1.32 {q12, q13}, [r7]!   @ outre2Q16[]
    500   vrshl.s32 q10, q10, q8
    501   vrshl.s32 q11, q11, q8
    502   vrshl.s32 q12, q12, q8
    503   vrshl.s32 q13, q13, q8
    504 
    505   vmovn.s32 d0, q0
    506   vmovn.s32 d1, q1
    507   vmovn.s32 d2, q2
    508   vmovn.s32 d3, q3
    509   vmovn.s32 d4, q10
    510   vmovn.s32 d5, q11
    511   vmovn.s32 d6, q12
    512   vmovn.s32 d7, q13
    513 
    514   vst1.16 {q0, q1}, [r4]!     @ inreQ7[]
    515   vst1.16 {q2, q3}, [r5]!     @ inimQ7[]
    516 
    517   bgt PreFftShift
    518 
    519   vmov.s32 r8, d16[0]         @ Store value of sh.
    520   ldr r0, [sp]                @ inreQ7
    521   ldr r1, [sp, #4]            @ inimQ7
    522   mov r2, #1
    523   CALL_FUNCTION WebRtcIsacfix_FftRadix16Fastest
    524 
    525   vdup.s32 q8, r8             @ sh
    526   mov r9, r11                 @ WebRtcIsacfix_kCosTab1
    527   ldr r4, [sp]                @ inreQ7
    528   ldr r5, [sp, #4]            @ inimQ7
    529   ldr r6, [sp, #8]            @ outre1Q16
    530   ldr r7, [sp, #12]           @ outre2Q16
    531   mov r8, #(FRAMESAMPLES / 2)
    532   vneg.s32 q15, q8            @ -sh
    533   movw r0, #273
    534   lsl r0, #15                 @ Together with vqdmulh, net effect is ">> 16".
    535   vdup.s32 q14, r0
    536 
    537 PostFftShiftDivide:
    538   subs r8, #16
    539 
    540   vld1.16 {q0, q1}, [r4]!     @ inreQ7
    541   vmovl.s16 q10, d0
    542   vmovl.s16 q11, d1
    543   vld1.16 {q2, q3}, [r5]!     @ inimQ7
    544   vmovl.s16 q8, d2
    545   vmovl.s16 q9, d3
    546 
    547   vshl.s32 q10, q10, q15
    548   vshl.s32 q11, q11, q15
    549   vshl.s32 q8, q8, q15
    550   vshl.s32 q9, q9, q15
    551 
    552   vqdmulh.s32 q10, q10, q14
    553   vqdmulh.s32 q11, q11, q14
    554   vqdmulh.s32 q8, q8, q14
    555   vqdmulh.s32 q9, q9, q14
    556 
    557   vmovl.s16 q0, d4
    558   vmovl.s16 q1, d5
    559   vmovl.s16 q2, d6
    560   vmovl.s16 q3, d7
    561 
    562   vshl.s32 q0, q0, q15
    563   vshl.s32 q1, q1, q15
    564   vshl.s32 q2, q2, q15
    565   vshl.s32 q3, q3, q15
    566 
    567   @ WEBRTC_SPL_MUL_16_32_RSFT16(273, outre2Q16[k])
    568   vqdmulh.s32 q0, q0, q14
    569   vqdmulh.s32 q1, q1, q14
    570   vst1.32 {q10, q11}, [r6]!   @ outre1Q16[]
    571   vqdmulh.s32 q2, q2, q14
    572   vqdmulh.s32 q3, q3, q14
    573   vst1.32 {q8, q9}, [r6]!     @ outre1Q16[]
    574   vst1.32 {q0, q1}, [r7]!     @ outre2Q16[]
    575   vst1.32 {q2, q3}, [r7]!     @ outre2Q16[]
    576 
    577   bgt PostFftShiftDivide
    578 
    579   mov r8, #(FRAMESAMPLES / 2)
    580   ldr r2, [sp, #8]            @ outre1Q16
    581   ldr r3, [sp, #12]           @ outre2Q16
    582   movw r0, #31727
    583   lsl r0, #16                 @ With vqdmulh and vrshrn, net effect is ">> 25".
    584 
    585 DemodulateAndSeparate:
    586   subs r8, #8
    587 
    588   vld1.16 {q0}, [r9, :64]!    @ WebRtcIsacfix_kCosTab1[]
    589   vmovl.s16 q10, d0           @ WebRtcIsacfix_kCosTab1[]
    590   vld1.16 {q1}, [r10, :64]!   @ WebRtcIsacfix_kSinTab1[]
    591   vmovl.s16 q11, d1           @ WebRtcIsacfix_kCosTab1[]
    592   vld1.32 {q2, q3}, [r2]      @ outre1Q16
    593   vmovl.s16 q12, d2           @ WebRtcIsacfix_kSinTab1[]
    594   vld1.32 {q14, q15}, [r3]    @ outre2Q16
    595   vmovl.s16 q13, d3           @ WebRtcIsacfix_kSinTab1[]
    596 
    597   vmull.s32 q0, d20, d4       @ WebRtcIsacfix_kCosTab1[k] * outre1Q16[k]
    598   vmull.s32 q1, d21, d5       @ WebRtcIsacfix_kCosTab1[k] * outre1Q16[k]
    599   vmull.s32 q8, d22, d6       @ WebRtcIsacfix_kCosTab1[k] * outre1Q16[k]
    600   vmull.s32 q9, d23, d7       @ WebRtcIsacfix_kCosTab1[k] * outre1Q16[k]
    601 
    602   vmlsl.s32 q0, d24, d28      @ += WebRtcIsacfix_kSinTab1[k] * outre2Q16[k]
    603   vmlsl.s32 q1, d25, d29      @ += WebRtcIsacfix_kSinTab1[k] * outre2Q16[k]
    604   vmlsl.s32 q8, d26, d30      @ += WebRtcIsacfix_kSinTab1[k] * outre2Q16[k]
    605   vmlsl.s32 q9, d27, d31      @ += WebRtcIsacfix_kSinTab1[k] * outre2Q16[k]
    606 
    607   vrshrn.s64 d0, q0, #10      @ xrQ16
    608   vrshrn.s64 d1, q1, #10      @ xrQ16
    609   vrshrn.s64 d2, q8, #10      @ xrQ16
    610   vrshrn.s64 d3, q9, #10      @ xrQ16
    611 
    612   vmull.s32 q8, d20, d28      @ WebRtcIsacfix_kCosTab1[k] * outre2Q16[k]
    613   vmull.s32 q9, d21, d29      @ WebRtcIsacfix_kCosTab1[k] * outre2Q16[k]
    614   vmull.s32 q14, d22, d30     @ WebRtcIsacfix_kCosTab1[k] * outre2Q16[k]
    615   vmull.s32 q15, d23, d31     @ WebRtcIsacfix_kCosTab1[k] * outre2Q16[k]
    616 
    617   vmlal.s32 q8, d24, d4       @ += WebRtcIsacfix_kSinTab1[k] * outre1Q16[k]
    618   vmlal.s32 q9, d25, d5       @ += WebRtcIsacfix_kSinTab1[k] * outre1Q16[k]
    619   vmlal.s32 q14, d26, d6      @ += WebRtcIsacfix_kSinTab1[k] * outre1Q16[k]
    620   vmlal.s32 q15, d27, d7      @ += WebRtcIsacfix_kSinTab1[k] * outre1Q16[k]
    621 
    622   vdup.s32 q11, r0            @ generic -> Neon doesn't cost extra cycles.
    623 
    624   vrshrn.s64 d24, q8, #10     @ xiQ16
    625   vrshrn.s64 d25, q9, #10     @ xiQ16
    626   vqdmulh.s32 q0, q0, q11
    627   vrshrn.s64 d26, q14, #10    @ xiQ16
    628   vrshrn.s64 d27, q15, #10    @ xiQ16
    629 
    630   @ WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xrQ16)
    631   @ WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xiQ16)
    632 
    633   vqdmulh.s32 q1, q1, q11
    634   vqdmulh.s32 q2, q12, q11
    635   vqdmulh.s32 q3, q13, q11
    636 
    637   vst1.16 {q0, q1}, [r2]!     @ outre1Q16[]
    638   vst1.16 {q2, q3}, [r3]!     @ outre2Q16[]
    639 
    640   bgt DemodulateAndSeparate
    641 
    642   add sp, sp, #16
    643   pop {r4-r11,pc}
    644