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