1 /*
2 * Copyright (C) 2004-2010 NXP Software
3 * Copyright (C) 2010 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 /**********************************************************************************
19 INCLUDE FILES
20 ***********************************************************************************/
21
22 #include "LVC_Mixer_Private.h"
23 #include "LVM_Macros.h"
24
25 /**********************************************************************************
26 FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
27 ***********************************************************************************/
28 #ifdef BUILD_FLOAT
LVC_Core_MixInSoft_D16C31_SAT(LVMixer3_FLOAT_st * ptrInstance,const LVM_FLOAT * src,LVM_FLOAT * dst,LVM_INT16 n)29 void LVC_Core_MixInSoft_D16C31_SAT(LVMixer3_FLOAT_st *ptrInstance,
30 const LVM_FLOAT *src,
31 LVM_FLOAT *dst,
32 LVM_INT16 n)
33 {
34
35 LVM_INT16 OutLoop;
36 LVM_INT16 InLoop;
37 LVM_INT32 ii,jj;
38 Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)(ptrInstance->PrivateParams);
39 LVM_FLOAT Delta = pInstance->Delta;
40 LVM_FLOAT Current = pInstance->Current;
41 LVM_FLOAT Target = pInstance->Target;
42 LVM_FLOAT Temp;
43
44 InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
45 OutLoop = (LVM_INT16)(n - (InLoop << 2));
46
47 if(Current < Target){
48 if (OutLoop){
49 Temp = Current + Delta;
50 Current = Temp;
51 if (Current > Target)
52 Current = Target;
53
54 for (ii = OutLoop; ii != 0; ii--){
55 Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
56 if (Temp > 1.0f)
57 *dst++ = 1.0f;
58 else if (Temp < -1.0f)
59 *dst++ = -1.0f;
60 else
61 *dst++ = (LVM_FLOAT)Temp;
62 }
63 }
64
65 for (ii = InLoop; ii != 0; ii--){
66 Temp = Current + Delta;
67 Current = Temp;
68 if (Current > Target)
69 Current = Target;
70
71 for (jj = 4; jj != 0 ; jj--){
72 Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
73 if (Temp > 1.0f)
74 *dst++ = 1.0f;
75 else if (Temp < -1.0f)
76 *dst++ = -1.0f;
77 else
78 *dst++ = (LVM_FLOAT)Temp;
79 }
80 }
81 }
82 else{
83 if (OutLoop){
84 Current -= Delta;
85 if (Current < Target)
86 Current = Target;
87
88 for (ii = OutLoop; ii != 0; ii--){
89 Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
90 if (Temp > 1.0f)
91 *dst++ = 1.0f;
92 else if (Temp < -1.0f)
93 *dst++ = -1.0f;
94 else
95 *dst++ = (LVM_FLOAT)Temp;
96 }
97 }
98
99 for (ii = InLoop; ii != 0; ii--){
100 Current -= Delta;
101 if (Current < Target)
102 Current = Target;
103
104 for (jj = 4; jj != 0 ; jj--){
105 Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
106 if (Temp > 1.0f)
107 *dst++ = 1.0f;
108 else if (Temp < -1.0f)
109 *dst++ = -1.0f;
110 else
111 *dst++ = (LVM_FLOAT)Temp;
112 }
113 }
114 }
115 pInstance->Current = Current;
116 }
117 #ifdef SUPPORT_MC
118 /*
119 * FUNCTION: LVC_Core_MixInSoft_Mc_D16C31_SAT
120 *
121 * DESCRIPTION:
122 * Mixer function with support for processing multichannel input.
123 *
124 * PARAMETERS:
125 * ptrInstance Instance pointer
126 * src Source
127 * dst Destination
128 * NrFrames Number of frames
129 * NrChannels Number of channels
130 *
131 * RETURNS:
132 * void
133 *
134 */
LVC_Core_MixInSoft_Mc_D16C31_SAT(LVMixer3_FLOAT_st * ptrInstance,const LVM_FLOAT * src,LVM_FLOAT * dst,LVM_INT16 NrFrames,LVM_INT16 NrChannels)135 void LVC_Core_MixInSoft_Mc_D16C31_SAT(LVMixer3_FLOAT_st *ptrInstance,
136 const LVM_FLOAT *src,
137 LVM_FLOAT *dst,
138 LVM_INT16 NrFrames,
139 LVM_INT16 NrChannels)
140 {
141
142 LVM_INT16 OutLoop;
143 LVM_INT16 InLoop;
144 LVM_INT32 ii, jj;
145 Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)(ptrInstance->PrivateParams);
146 LVM_FLOAT Delta = pInstance->Delta;
147 LVM_FLOAT Current = pInstance->Current;
148 LVM_FLOAT Target = pInstance->Target;
149 LVM_FLOAT Temp;
150
151 /*
152 * Same operation is performed on consecutive frames.
153 * So two frames are processed in one iteration and
154 * the loop will run only for half the NrFrames value times.
155 */
156 InLoop = (LVM_INT16)(NrFrames >> 1);
157 /* OutLoop is calculated to handle cases where NrFrames value can be odd.*/
158 OutLoop = (LVM_INT16)(NrFrames - (InLoop << 1));
159
160 if (Current < Target) {
161 if (OutLoop) {
162 Temp = Current + Delta;
163 Current = Temp;
164 if (Current > Target)
165 Current = Target;
166
167 for (ii = OutLoop*NrChannels; ii != 0; ii--) {
168 Temp = (*dst) + (*(src++) * Current);
169 if (Temp > 1.0f)
170 *dst++ = 1.0f;
171 else if (Temp < -1.0f)
172 *dst++ = -1.0f;
173 else
174 *dst++ = Temp;
175 }
176 }
177
178 for (ii = InLoop; ii != 0; ii--) {
179 Temp = Current + Delta;
180 Current = Temp;
181 if (Current > Target)
182 Current = Target;
183
184 for (jj = NrChannels; jj != 0 ; jj--) {
185 Temp = (*dst) + (*(src++) * Current);
186 if (Temp > 1.0f)
187 *dst++ = 1.0f;
188 else if (Temp < -1.0f)
189 *dst++ = -1.0f;
190 else
191 *dst++ = Temp;
192
193 Temp = (*dst) + (*(src++) * Current);
194 if (Temp > 1.0f)
195 *dst++ = 1.0f;
196 else if (Temp < -1.0f)
197 *dst++ = -1.0f;
198 else
199 *dst++ = Temp;
200
201 }
202 }
203 }
204 else{
205 if (OutLoop) {
206 Current -= Delta;
207 if (Current < Target)
208 Current = Target;
209
210 for (ii = OutLoop*NrChannels; ii != 0; ii--) {
211 Temp = (*dst) + (*(src++) * Current);
212 if (Temp > 1.0f)
213 *dst++ = 1.0f;
214 else if (Temp < -1.0f)
215 *dst++ = -1.0f;
216 else
217 *dst++ = Temp;
218 }
219 }
220
221 for (ii = InLoop; ii != 0; ii--) {
222 Current -= Delta;
223 if (Current < Target)
224 Current = Target;
225
226 for (jj = NrChannels; jj != 0 ; jj--) {
227 Temp = (*dst) + (*(src++) * Current);
228 if (Temp > 1.0f)
229 *dst++ = 1.0f;
230 else if (Temp < -1.0f)
231 *dst++ = -1.0f;
232 else
233 *dst++ = Temp;
234
235 Temp = (*dst) + (*(src++) * Current);
236 if (Temp > 1.0f)
237 *dst++ = 1.0f;
238 else if (Temp < -1.0f)
239 *dst++ = -1.0f;
240 else
241 *dst++ = Temp;
242
243 }
244 }
245 }
246 pInstance->Current = Current;
247 }
248
249 #endif
250 #else
LVC_Core_MixInSoft_D16C31_SAT(LVMixer3_st * ptrInstance,const LVM_INT16 * src,LVM_INT16 * dst,LVM_INT16 n)251 void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_st *ptrInstance,
252 const LVM_INT16 *src,
253 LVM_INT16 *dst,
254 LVM_INT16 n)
255 {
256
257 LVM_INT16 OutLoop;
258 LVM_INT16 InLoop;
259 LVM_INT16 CurrentShort;
260 LVM_INT32 ii,jj;
261 Mix_Private_st *pInstance=(Mix_Private_st *)(ptrInstance->PrivateParams);
262 LVM_INT32 Delta=pInstance->Delta;
263 LVM_INT32 Current=pInstance->Current;
264 LVM_INT32 Target=pInstance->Target;
265 LVM_INT32 Temp;
266
267 InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
268 OutLoop = (LVM_INT16)(n - (InLoop << 2));
269
270 if(Current<Target){
271 if (OutLoop){
272 ADD2_SAT_32x32(Current,Delta,Temp); /* Q31 + Q31 into Q31*/
273 Current=Temp;
274 if (Current > Target)
275 Current = Target;
276
277 CurrentShort = (LVM_INT16)(Current>>16); /* From Q31 to Q15*/
278
279 for (ii = OutLoop; ii != 0; ii--){
280 Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15); /* Q15 + Q15*Q15>>15 into Q15 */
281 if (Temp > 0x00007FFF)
282 *dst++ = 0x7FFF;
283 else if (Temp < -0x00008000)
284 *dst++ = - 0x8000;
285 else
286 *dst++ = (LVM_INT16)Temp;
287 }
288 }
289
290 for (ii = InLoop; ii != 0; ii--){
291 ADD2_SAT_32x32(Current,Delta,Temp); /* Q31 + Q31 into Q31*/
292 Current=Temp;
293 if (Current > Target)
294 Current = Target;
295
296 CurrentShort = (LVM_INT16)(Current>>16); /* From Q31 to Q15*/
297
298 for (jj = 4; jj!=0 ; jj--){
299 Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15); /* Q15 + Q15*Q15>>15 into Q15 */
300 if (Temp > 0x00007FFF)
301 *dst++ = 0x7FFF;
302 else if (Temp < -0x00008000)
303 *dst++ = - 0x8000;
304 else
305 *dst++ = (LVM_INT16)Temp;
306 }
307 }
308 }
309 else{
310 if (OutLoop){
311 Current -= Delta; /* Q31 + Q31 into Q31*/
312 if (Current < Target)
313 Current = Target;
314
315 CurrentShort = (LVM_INT16)(Current>>16); /* From Q31 to Q15*/
316
317 for (ii = OutLoop; ii != 0; ii--){
318 Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15); /* Q15 + Q15*Q15>>15 into Q15 */
319 if (Temp > 0x00007FFF)
320 *dst++ = 0x7FFF;
321 else if (Temp < -0x00008000)
322 *dst++ = - 0x8000;
323 else
324 *dst++ = (LVM_INT16)Temp;
325 }
326 }
327
328 for (ii = InLoop; ii != 0; ii--){
329 Current -= Delta; /* Q31 + Q31 into Q31*/
330 if (Current < Target)
331 Current = Target;
332
333 CurrentShort = (LVM_INT16)(Current>>16); /* From Q31 to Q15*/
334
335 for (jj = 4; jj!=0 ; jj--){
336 Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15); /* Q15 + Q15*Q15>>15 into Q15 */
337 if (Temp > 0x00007FFF)
338 *dst++ = 0x7FFF;
339 else if (Temp < -0x00008000)
340 *dst++ = - 0x8000;
341 else
342 *dst++ = (LVM_INT16)Temp;
343 }
344 }
345 }
346 pInstance->Current=Current;
347 }
348 #endif
349 /**********************************************************************************/
350