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 /*                                                                                      */
20 /* Includes                                                                             */
21 /*                                                                                      */
22 /****************************************************************************************/
23 #include "LVREV_Private.h"
24 #include "VectorArithmetic.h"
25 
26 
27 /****************************************************************************************/
28 /*                                                                                      */
29 /* FUNCTION:                LVREV_Process                                               */
30 /*                                                                                      */
31 /* DESCRIPTION:                                                                         */
32 /*  Process function for the LVREV module.                                              */
33 /*                                                                                      */
34 /* PARAMETERS:                                                                          */
35 /*  hInstance               Instance handle                                             */
36 /*  pInData                 Pointer to the input data                                   */
37 /*  pOutData                Pointer to the output data                                  */
38 /*  NumSamples              Number of samples in the input buffer                       */
39 /*                                                                                      */
40 /* RETURNS:                                                                             */
41 /*  LVREV_Success           Succeeded                                                   */
42 /*  LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size           */
43 /*  LVREV_NULLADDRESS       When one of hInstance, pInData or pOutData is NULL          */
44 /*                                                                                      */
45 /* NOTES:                                                                               */
46 /*  1. The input and output buffers must be 32-bit aligned                              */
47 /*                                                                                      */
48 /****************************************************************************************/
LVREV_Process(LVREV_Handle_t hInstance,const LVM_INT32 * pInData,LVM_INT32 * pOutData,const LVM_UINT16 NumSamples)49 LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t      hInstance,
50                                     const LVM_INT32     *pInData,
51                                     LVM_INT32           *pOutData,
52                                     const LVM_UINT16    NumSamples)
53 {
54    LVREV_Instance_st     *pLVREV_Private = (LVREV_Instance_st *)hInstance;
55    LVM_INT32             *pInput  = (LVM_INT32 *)pInData;
56    LVM_INT32             *pOutput = pOutData;
57    LVM_INT32             SamplesToProcess, RemainingSamples;
58    LVM_INT32             format = 1;
59 
60     /*
61      * Check for error conditions
62      */
63 
64     /* Check for NULL pointers */
65     if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
66     {
67         return LVREV_NULLADDRESS;
68     }
69 
70     /*
71      * Apply the new controls settings if required
72      */
73     if(pLVREV_Private->bControlPending == LVM_TRUE)
74     {
75         LVREV_ReturnStatus_en   errorCode;
76 
77         /*
78          * Clear the pending flag and update the control settings
79          */
80         pLVREV_Private->bControlPending = LVM_FALSE;
81 
82         errorCode = LVREV_ApplyNewSettings (pLVREV_Private);
83 
84         if(errorCode != LVREV_SUCCESS)
85         {
86             return errorCode;
87         }
88     }
89 
90     /*
91      * Trap the case where the number of samples is zero.
92      */
93     if (NumSamples == 0)
94     {
95         return LVREV_SUCCESS;
96     }
97 
98     /*
99      * If OFF copy and reformat the data as necessary
100      */
101     if (pLVREV_Private->CurrentParams.OperatingMode == LVM_MODE_OFF)
102     {
103         if(pInput != pOutput)
104         {
105             /*
106              * Copy the data to the output buffer, convert to stereo is required
107              */
108 
109             if(pLVREV_Private->CurrentParams.SourceFormat == LVM_MONO){
110                 MonoTo2I_32(pInput, pOutput, NumSamples);
111             } else {
112                 Copy_16((LVM_INT16 *)pInput,
113                         (LVM_INT16 *)pOutput,
114                         (LVM_INT16)(NumSamples << 2)); // 32 bit data, stereo
115             }
116         }
117 
118         return LVREV_SUCCESS;
119     }
120 
121     RemainingSamples = (LVM_INT32)NumSamples;
122 
123     if (pLVREV_Private->CurrentParams.SourceFormat != LVM_MONO)
124     {
125         format = 2;
126     }
127 
128     while (RemainingSamples!=0)
129     {
130         /*
131          * Process the data
132          */
133 
134         if(RemainingSamples >  pLVREV_Private->MaxBlkLen)
135         {
136             SamplesToProcess =  pLVREV_Private->MaxBlkLen;
137             RemainingSamples = (LVM_INT16)(RemainingSamples - SamplesToProcess);
138         }
139         else
140         {
141             SamplesToProcess = RemainingSamples;
142             RemainingSamples = 0;
143         }
144 
145         ReverbBlock(pInput, pOutput, pLVREV_Private, (LVM_UINT16)SamplesToProcess);
146 
147         pInput  = (LVM_INT32 *)(pInput +(SamplesToProcess*format));
148         pOutput = (LVM_INT32 *)(pOutput+(SamplesToProcess*2));      // Always stereo output
149     }
150 
151     return LVREV_SUCCESS;
152 }
153 
154 
155 
156 /****************************************************************************************/
157 /*                                                                                      */
158 /* FUNCTION:                ReverbBlock                                                 */
159 /*                                                                                      */
160 /* DESCRIPTION:                                                                         */
161 /*  Process function for the LVREV module.                                              */
162 /*                                                                                      */
163 /* PARAMETERS:                                                                          */
164 /*  hInstance               Instance handle                                             */
165 /*  pInData                 Pointer to the input data                                   */
166 /*  pOutData                Pointer to the output data                                  */
167 /*  NumSamples              Number of samples in the input buffer                       */
168 /*                                                                                      */
169 /* RETURNS:                                                                             */
170 /*  LVREV_Success           Succeeded                                                   */
171 /*  LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size           */
172 /*  LVREV_NULLADDRESS       When one of hInstance, pInData or pOutData is NULL          */
173 /*                                                                                      */
174 /* NOTES:                                                                               */
175 /*  1. The input and output buffers must be 32-bit aligned                              */
176 /*                                                                                      */
177 /****************************************************************************************/
178 
ReverbBlock(LVM_INT32 * pInput,LVM_INT32 * pOutput,LVREV_Instance_st * pPrivate,LVM_UINT16 NumSamples)179 void ReverbBlock(LVM_INT32 *pInput, LVM_INT32 *pOutput, LVREV_Instance_st *pPrivate, LVM_UINT16 NumSamples)
180 {
181     LVM_INT16   j, size;
182     LVM_INT32   *pDelayLine;
183     LVM_INT32   *pDelayLineInput = pPrivate->pScratch;
184     LVM_INT32   *pScratch = pPrivate->pScratch;
185     LVM_INT32   *pIn;
186     LVM_INT32   *pTemp = pPrivate->pInputSave;
187     LVM_INT32   NumberOfDelayLines;
188 
189     /******************************************************************************
190      * All calculations will go into the buffer pointed to by pTemp, this will    *
191      * then be mixed with the original input to create the final output.          *
192      *                                                                            *
193      * When INPLACE processing is selected this must be a temporary buffer and    *
194      * hence this is the worst case, so for simplicity this will ALWAYS be so     *
195      *                                                                            *
196      * The input buffer will remain untouched until the output of the mixer if    *
197      * INPLACE processing is selected.                                            *
198      *                                                                            *
199      * The temp buffer will always be NumSamples in size regardless of MONO or    *
200      * STEREO input. In the case of stereo input all processing is done in MONO   *
201      * and the final output is converted to STEREO after the mixer                *
202      ******************************************************************************/
203 
204     if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4 )
205     {
206         NumberOfDelayLines = 4;
207     }
208     else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2 )
209     {
210         NumberOfDelayLines = 2;
211     }
212     else
213     {
214         NumberOfDelayLines = 1;
215     }
216 
217     if(pPrivate->CurrentParams.SourceFormat == LVM_MONO)
218     {
219         pIn = pInput;
220     }
221     else
222     {
223         /*
224          *  Stereo to mono conversion
225          */
226 
227         From2iToMono_32( pInput,
228                          pTemp,
229                          (LVM_INT16)NumSamples);
230 
231         pIn = pTemp;
232     }
233 
234     Mult3s_32x16(pIn,
235                  (LVM_INT16)LVREV_HEADROOM,
236                  pTemp,
237                  (LVM_INT16)NumSamples);
238 
239     /*
240      *  High pass filter
241      */
242     FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->HPCoefs,
243                                 pTemp,
244                                 pTemp,
245                                 (LVM_INT16)NumSamples);
246     /*
247      *  Low pass filter
248      */
249     FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->LPCoefs,
250                                 pTemp,
251                                 pTemp,
252                                 (LVM_INT16)NumSamples);
253 
254     /*
255      *  Process all delay lines
256      */
257 
258     for(j = 0; j < NumberOfDelayLines; j++)
259     {
260         pDelayLine = pPrivate->pScratchDelayLine[j];
261 
262         /*
263          * All-pass filter with pop and click suppression
264          */
265         /* Get the smoothed, delayed output. Put it in the output buffer */
266         MixSoft_2St_D32C31_SAT(&pPrivate->Mixer_APTaps[j],
267                                pPrivate->pOffsetA[j],
268                                pPrivate->pOffsetB[j],
269                                pDelayLine,
270                                (LVM_INT16)NumSamples);
271         /* Re-align the all pass filter delay buffer and copying the fixed delay data to the AP delay in the process */
272         Copy_16((LVM_INT16 *)&pPrivate->pDelay_T[j][NumSamples],
273                 (LVM_INT16 *)pPrivate->pDelay_T[j],
274                 (LVM_INT16)((pPrivate->T[j]-NumSamples) << 1));         /* 32-bit data */
275         /* Apply the smoothed feedback and save to fixed delay input (currently empty) */
276         MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedback[j],
277                                pDelayLine,
278                                &pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
279                                (LVM_INT16)NumSamples);
280         /* Sum into the AP delay line */
281         Mac3s_Sat_32x16(&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
282                         -0x7fff,                                        /* Invert since the feedback coefficient is negative */
283                         &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j]-NumSamples],
284                         (LVM_INT16)NumSamples);
285         /* Apply smoothed feedforward sand save to fixed delay input (currently empty) */
286         MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedforward[j],
287                                &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j]-NumSamples],
288                                &pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
289                                (LVM_INT16)NumSamples);
290         /* Sum into the AP output */
291         Mac3s_Sat_32x16(&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
292                         0x7fff,
293                         pDelayLine,
294                         (LVM_INT16)NumSamples);
295 
296         /*
297          *  Feedback gain
298          */
299         MixSoft_1St_D32C31_WRA(&pPrivate->FeedbackMixer[j], pDelayLine, pDelayLine, NumSamples);
300 
301         /*
302          *  Low pass filter
303          */
304         FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->RevLPCoefs[j],
305                                     pDelayLine,
306                                     pDelayLine,
307                                     (LVM_INT16)NumSamples);
308     }
309 
310     /*
311      *  Apply rotation matrix and delay samples
312      */
313     for(j = 0; j < NumberOfDelayLines; j++)
314     {
315 
316         Copy_16( (LVM_INT16*)(pTemp),
317                  (LVM_INT16*)(pDelayLineInput),
318                  (LVM_INT16)(NumSamples << 1));
319 
320         /*
321          *  Rotation matrix mix
322          */
323         switch(j)
324         {
325             case 3:
326                 /*
327                  *  Add delay line 1 and 2 contribution
328                  */
329                  Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
330                  Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[2], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
331 
332                 break;
333             case 2:
334 
335                 /*
336                  *  Add delay line 0 and 3 contribution
337                  */
338                  Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
339                  Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[3], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
340 
341                 break;
342             case 1:
343                 if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
344                 {
345                     /*
346                      *  Add delay line 0 and 3 contribution
347                      */
348                     Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
349                     Add2_Sat_32x32(pPrivate->pScratchDelayLine[3], pDelayLineInput, (LVM_INT16)NumSamples);
350 
351                 }
352                 else
353                 {
354                     /*
355                      *  Add delay line 0 and 1 contribution
356                      */
357                      Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
358                      Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
359 
360                 }
361                 break;
362             case 0:
363                 if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
364                 {
365                     /*
366                      *  Add delay line 1 and 2 contribution
367                      */
368                     Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
369                     Add2_Sat_32x32(pPrivate->pScratchDelayLine[2], pDelayLineInput, (LVM_INT16)NumSamples);
370 
371                 }
372                 else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
373                 {
374                     /*
375                      *  Add delay line 0 and 1 contribution
376                      */
377                     Add2_Sat_32x32(pPrivate->pScratchDelayLine[0], pDelayLineInput, (LVM_INT16)NumSamples);
378                     Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
379 
380                 }
381                 else
382                 {
383                     /*
384                      *  Add delay line 0 contribution
385                      */
386 
387                     /*             SOURCE                          DESTINATION*/
388                     Add2_Sat_32x32(pPrivate->pScratchDelayLine[0], pDelayLineInput, (LVM_INT16)NumSamples);
389                 }
390                 break;
391             default:
392                 break;
393         }
394 
395         /*
396          *  Delay samples
397          */
398         Copy_16((LVM_INT16 *)pDelayLineInput,
399                 (LVM_INT16 *)&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
400                 (LVM_INT16)(NumSamples << 1));              /* 32-bit data */
401 
402     }
403 
404 
405     /*
406      *  Create stereo output
407      */
408     switch(pPrivate->InstanceParams.NumDelays)
409     {
410         case LVREV_DELAYLINES_4:
411              Add2_Sat_32x32(pPrivate->pScratchDelayLine[3],
412                             pPrivate->pScratchDelayLine[0],
413                             (LVM_INT16)NumSamples);
414              Add2_Sat_32x32(pPrivate->pScratchDelayLine[2],
415                             pPrivate->pScratchDelayLine[1],
416                             (LVM_INT16)NumSamples);
417 
418 
419             JoinTo2i_32x32(pPrivate->pScratchDelayLine[0],
420                            pPrivate->pScratchDelayLine[1],
421                            pTemp,
422                            (LVM_INT16)NumSamples);
423 
424 
425             break;
426         case LVREV_DELAYLINES_2:
427 
428              Copy_16( (LVM_INT16*)pPrivate->pScratchDelayLine[1],
429                       (LVM_INT16*)pScratch,
430                       (LVM_INT16)(NumSamples << 1));
431 
432             Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0],
433                             -0x8000,
434                             pScratch,
435                             (LVM_INT16)NumSamples);
436 
437              Add2_Sat_32x32(pPrivate->pScratchDelayLine[1],
438                             pPrivate->pScratchDelayLine[0],
439                             (LVM_INT16)NumSamples);
440 
441 
442              JoinTo2i_32x32(pPrivate->pScratchDelayLine[0],
443                             pScratch,
444                             pTemp,
445                             (LVM_INT16)NumSamples);
446             break;
447         case LVREV_DELAYLINES_1:
448             MonoTo2I_32(pPrivate->pScratchDelayLine[0],
449                         pTemp,
450                         (LVM_INT16)NumSamples);
451             break;
452         default:
453             break;
454     }
455 
456 
457     /*
458      *  Dry/wet mixer
459      */
460 
461     size = (LVM_INT16)(NumSamples << 1);
462     MixSoft_2St_D32C31_SAT(&pPrivate->BypassMixer,
463                            pTemp,
464                            pTemp,
465                            pOutput,
466                            size);
467 
468     /* Apply Gain*/
469 
470     Shift_Sat_v32xv32 (LVREV_OUTPUTGAIN_SHIFT,
471                        pOutput,
472                        pOutput,
473                        size);
474 
475     MixSoft_1St_D32C31_WRA(&pPrivate->GainMixer,
476                            pOutput,
477                            pOutput,
478                            size);
479 
480     return;
481 }
482 
483 
484 /* End of file */
485 
486