1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ This file contains the function WebRtcSpl_FilterARFastQ12(), optimized for
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ ARMv7  platform. The description header can be found in
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ signal_processing_library.h
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ Output is bit-exact with the generic C code as in filter_ar_fast_q12.c, and
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ the reference C code at end of this file.
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ Assumptions:
19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ (1) data_length > 0
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ (2) coefficients_length > 1
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ Register usage:
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ r0:  &data_in[i]
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ r1:  &data_out[i], for result ouput
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ r2:  &coefficients[0]
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ r3:  coefficients_length
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ r4:  Iteration counter for the outer loop.
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ r5:  data_out[j] as multiplication inputs
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ r6:  Calculated value for output data_out[]; interation counter for inner loop
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ r7:  Partial sum of a filtering multiplication results
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ r8:  Partial sum of a filtering multiplication results
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ r9:  &data_out[], for filtering input; data_in[i]
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ r10: coefficients[j]
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ r11: Scratch
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ r12: &coefficients[j]
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
38b238acaca55b4b345f0e37b82f8bbd9851c8bb6dkma@webrtc.org#include "webrtc/system_wrappers/interface/asm_defines.h"
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
40b238acaca55b4b345f0e37b82f8bbd9851c8bb6dkma@webrtc.orgGLOBAL_FUNCTION WebRtcSpl_FilterARFastQ12
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org.align  2
42b238acaca55b4b345f0e37b82f8bbd9851c8bb6dkma@webrtc.orgDEFINE_FUNCTION WebRtcSpl_FilterARFastQ12
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  push {r4-r11}
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ldrsh r12, [sp, #32]         @ data_length
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  subs r4, r12, #1
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  beq ODD_LENGTH               @ jump if data_length == 1
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgLOOP_LENGTH:
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  add r12, r2, r3, lsl #1
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sub r12, #4                  @ &coefficients[coefficients_length - 2]
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sub r9, r1, r3, lsl #1
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  add r9, #2                   @ &data_out[i - coefficients_length + 1]
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ldr r5, [r9], #4             @ data_out[i - coefficients_length + {1,2}]
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  mov r7, #0                   @ sum1
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  mov r8, #0                   @ sum2
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  subs r6, r3, #3              @ Iteration counter for inner loop.
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  beq ODD_A_LENGTH             @ branch if coefficients_length == 3
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  blt POST_LOOP_A_LENGTH       @ branch if coefficients_length == 2
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgLOOP_A_LENGTH:
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ldr r10, [r12], #-4          @ coefficients[j - 1], coefficients[j]
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  subs r6, #2
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  smlatt r8, r10, r5, r8       @ sum2 += coefficients[j] * data_out[i - j + 1];
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  smlatb r7, r10, r5, r7       @ sum1 += coefficients[j] * data_out[i - j];
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  smlabt r7, r10, r5, r7       @ coefficients[j - 1] * data_out[i - j + 1];
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ldr r5, [r9], #4             @ data_out[i - j + 2],  data_out[i - j + 3]
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  smlabb r8, r10, r5, r8       @ coefficients[j - 1] * data_out[i - j + 2];
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bgt LOOP_A_LENGTH
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  blt POST_LOOP_A_LENGTH
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgODD_A_LENGTH:
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ldrsh r10, [r12, #2]         @ Filter coefficients coefficients[2]
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sub r12, #2                  @ &coefficients[0]
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  smlabb r7, r10, r5, r7       @ sum1 += coefficients[2] * data_out[i - 2];
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  smlabt r8, r10, r5, r8       @ sum2 += coefficients[2] * data_out[i - 1];
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ldr r5, [r9, #-2]            @ data_out[i - 1],  data_out[i]
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgPOST_LOOP_A_LENGTH:
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ldr r10, [r12]               @ coefficients[0], coefficients[1]
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  smlatb r7, r10, r5, r7       @ sum1 += coefficients[1] * data_out[i - 1];
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ldr r9, [r0], #4             @ data_in[i], data_in[i + 1]
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  smulbb r6, r10, r9           @ output1 = coefficients[0] * data_in[i];
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sub r6, r7                   @ output1 -= sum1;
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sbfx r11, r6, #12, #16
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ssat r7, #16, r6, asr #12
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  cmp r7, r11
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  addeq r6, r6, #2048
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ssat r6, #16, r6, asr #12
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  strh r6, [r1], #2            @ Store data_out[i]
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  smlatb r8, r10, r6, r8       @ sum2 += coefficients[1] * data_out[i];
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  smulbt r6, r10, r9           @ output2 = coefficients[0] * data_in[i + 1];
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sub r6, r8                   @ output1 -= sum1;
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sbfx r11, r6, #12, #16
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ssat r7, #16, r6, asr #12
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  cmp r7, r11
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  addeq r6, r6, #2048
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ssat r6, #16, r6, asr #12
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  strh r6, [r1], #2            @ Store data_out[i + 1]
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  subs r4, #2
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bgt LOOP_LENGTH
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  blt END                      @ For even data_length, it's done. Jump to END.
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@ Process i = data_length -1, for the case of an odd length.
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgODD_LENGTH:
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  add r12, r2, r3, lsl #1
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sub r12, #4                  @ &coefficients[coefficients_length - 2]
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sub r9, r1, r3, lsl #1
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  add r9, #2                   @ &data_out[i - coefficients_length + 1]
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  mov r7, #0                   @ sum1
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  mov r8, #0                   @ sum1
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  subs r6, r3, #2              @ inner loop counter
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  beq EVEN_A_LENGTH            @ branch if coefficients_length == 2
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgLOOP2_A_LENGTH:
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ldr r10, [r12], #-4          @ coefficients[j - 1], coefficients[j]
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ldr r5, [r9], #4             @ data_out[i - j],  data_out[i - j + 1]
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  subs r6, #2
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  smlatb r7, r10, r5, r7       @ sum1 += coefficients[j] * data_out[i - j];
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  smlabt r8, r10, r5, r8       @ coefficients[j - 1] * data_out[i - j + 1];
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bgt LOOP2_A_LENGTH
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  addlt r12, #2
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  blt POST_LOOP2_A_LENGTH
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgEVEN_A_LENGTH:
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ldrsh r10, [r12, #2]         @ Filter coefficients coefficients[1]
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ldrsh r5, [r9]               @ data_out[i - 1]
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  smlabb r7, r10, r5, r7       @ sum1 += coefficients[1] * data_out[i - 1];
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgPOST_LOOP2_A_LENGTH:
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ldrsh r10, [r12]             @ Filter coefficients coefficients[0]
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ldrsh r9, [r0]               @ data_in[i]
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  smulbb r6, r10, r9           @ output1 = coefficients[0] * data_in[i];
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sub r6, r7                   @ output1 -= sum1;
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sub r6, r8                   @ output1 -= sum1;
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sbfx r8, r6, #12, #16
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ssat r7, #16, r6, asr #12
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  cmp r7, r8
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  addeq r6, r6, #2048
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ssat r6, #16, r6, asr #12
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  strh r6, [r1]                @ Store the data_out[i]
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgEND:
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  pop {r4-r11}
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bx  lr
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@Reference C code:
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@void WebRtcSpl_FilterARFastQ12(int16_t* data_in,
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@                               int16_t* data_out,
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@                               int16_t* __restrict coefficients,
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@                               int coefficients_length,
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@                               int data_length) {
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@  int i = 0;
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@  int j = 0;
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@  for (i = 0; i < data_length - 1; i += 2) {
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    int32_t output1 = 0;
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    int32_t sum1 = 0;
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    int32_t output2 = 0;
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    int32_t sum2 = 0;
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    for (j = coefficients_length - 1; j > 2; j -= 2) {
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@      sum1 += coefficients[j]      * data_out[i - j];
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@      sum1 += coefficients[j - 1]  * data_out[i - j + 1];
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@      sum2 += coefficients[j]     * data_out[i - j + 1];
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@      sum2 += coefficients[j - 1] * data_out[i - j + 2];
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    }
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    if (j == 2) {
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@      sum1 += coefficients[2] * data_out[i - 2];
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@      sum2 += coefficients[2] * data_out[i - 1];
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    }
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    sum1 += coefficients[1] * data_out[i - 1];
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    output1 = coefficients[0] * data_in[i];
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    output1 -= sum1;
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    // Saturate and store the output.
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    output1 = WEBRTC_SPL_SAT(134215679, output1, -134217728);
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    data_out[i] = (int16_t)((output1 + 2048) >> 12);
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    sum2 += coefficients[1] * data_out[i];
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    output2 = coefficients[0] * data_in[i + 1];
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    output2 -= sum2;
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    // Saturate and store the output.
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    output2 = WEBRTC_SPL_SAT(134215679, output2, -134217728);
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    data_out[i + 1] = (int16_t)((output2 + 2048) >> 12);
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@  }
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@  if (i == data_length - 1) {
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    int32_t output1 = 0;
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    int32_t sum1 = 0;
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    for (j = coefficients_length - 1; j > 1; j -= 2) {
201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@      sum1 += coefficients[j]      * data_out[i - j];
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@      sum1 += coefficients[j - 1]  * data_out[i - j + 1];
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    }
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    if (j == 1) {
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@      sum1 += coefficients[1] * data_out[i - 1];
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    }
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    output1 = coefficients[0] * data_in[i];
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    output1 -= sum1;
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    // Saturate and store the output.
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    output1 = WEBRTC_SPL_SAT(134215679, output1, -134217728);
213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@    data_out[i] = (int16_t)((output1 + 2048) >> 12);
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@  }
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org@}
216