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 "Filter.h"
25
26/****************************************************************************************/
27/*                                                                                      */
28/* FUNCTION:                LVREV_ApplyNewSettings                                      */
29/*                                                                                      */
30/* DESCRIPTION:                                                                         */
31/*  Applies the new control parameters                                                  */
32/*                                                                                      */
33/* PARAMETERS:                                                                          */
34/*  pPrivate                Pointer to the instance private parameters                  */
35/*                                                                                      */
36/* RETURNS:                                                                             */
37/*  LVREV_Success           Succeeded                                                   */
38/*  LVREV_NULLADDRESS       When pPrivate is NULL                                       */
39/*                                                                                      */
40/* NOTES:                                                                               */
41/*                                                                                      */
42/****************************************************************************************/
43
44#ifndef BUILD_FLOAT
45LVREV_ReturnStatus_en LVREV_ApplyNewSettings (LVREV_Instance_st     *pPrivate)
46{
47
48    LVM_Mode_en  OperatingMode;
49    LVM_INT32    NumberOfDelayLines;
50
51
52    /* Check for NULL pointer */
53    if(pPrivate == LVM_NULL)
54    {
55        return LVREV_NULLADDRESS;
56    }
57
58    OperatingMode = pPrivate->NewParams.OperatingMode;
59
60    if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
61    {
62        NumberOfDelayLines = 4;
63    }
64    else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
65    {
66        NumberOfDelayLines = 2;
67    }
68    else
69    {
70        NumberOfDelayLines = 1;
71    }
72
73    /*
74     * Update the high pass filter coefficients
75     */
76    if((pPrivate->NewParams.HPF        != pPrivate->CurrentParams.HPF)        ||
77       (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
78       (pPrivate->bFirstControl        == LVM_TRUE))
79    {
80        LVM_INT32       Omega;
81        FO_C32_Coefs_t  Coeffs;
82
83        Omega = LVM_GetOmega(pPrivate->NewParams.HPF, pPrivate->NewParams.SampleRate);
84        LVM_FO_HPF(Omega, &Coeffs);
85        FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->HPCoefs, &pPrivate->pFastData->HPTaps, &Coeffs);
86        LoadConst_32(0,
87            (void *)&pPrivate->pFastData->HPTaps, /* Destination Cast to void: no dereferencing in function*/
88            sizeof(Biquad_1I_Order1_Taps_t)/sizeof(LVM_INT32));
89    }
90
91
92    /*
93     * Update the low pass filter coefficients
94     */
95    if((pPrivate->NewParams.LPF        != pPrivate->CurrentParams.LPF)        ||
96       (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
97       (pPrivate->bFirstControl        == LVM_TRUE))
98    {
99        LVM_INT32       Omega;
100        FO_C32_Coefs_t  Coeffs;
101
102
103        Coeffs.A0 = 0x7FFFFFFF;
104        Coeffs.A1 = 0;
105        Coeffs.B1 = 0;
106        if(pPrivate->NewParams.LPF <= (LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
107        {
108            Omega = LVM_GetOmega(pPrivate->NewParams.LPF, pPrivate->NewParams.SampleRate);
109
110            /*
111             * Do not apply filter if w =2*pi*fc/fs >= 2.9
112             */
113            if(Omega<=LVREV_2_9_INQ29)
114            {
115                LVM_FO_LPF(Omega, &Coeffs);
116            }
117        }
118        FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->LPCoefs, &pPrivate->pFastData->LPTaps, &Coeffs);
119        LoadConst_32(0,
120            (void *)&pPrivate->pFastData->LPTaps,        /* Destination Cast to void: no dereferencing in function*/
121            sizeof(Biquad_1I_Order1_Taps_t)/sizeof(LVM_INT32));
122    }
123
124
125    /*
126     * Calculate the room size parameter
127     */
128    if( pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize)
129    {
130        /* Room size range is 10ms to 200ms
131         * 0%   -- 10ms
132         * 50%  -- 65ms
133         * 100% -- 120ms
134         */
135        pPrivate->RoomSizeInms = 10 + (((pPrivate->NewParams.RoomSize*11) + 5)/10);
136    }
137
138
139    /*
140     * Update the T delay number of samples and the all pass delay number of samples
141     */
142    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
143        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
144        (pPrivate->bFirstControl        == LVM_TRUE))
145    {
146
147        LVM_UINT32  Temp;
148        LVM_INT32   APDelaySize;
149        LVM_INT32   Fs = LVM_GetFsFromTable(pPrivate->NewParams.SampleRate);
150        LVM_UINT32  DelayLengthSamples = (LVM_UINT32)(Fs * pPrivate->RoomSizeInms);
151        LVM_INT16   i;
152        LVM_INT16   ScaleTable[]  = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4, LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
153        LVM_INT16   MaxT_Delay[]  = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, LVREV_MAX_T2_DELAY, LVREV_MAX_T3_DELAY};
154        LVM_INT16   MaxAP_Delay[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY, LVREV_MAX_AP2_DELAY, LVREV_MAX_AP3_DELAY};
155
156
157        /*
158         * For each delay line
159         */
160        for (i=0; i<NumberOfDelayLines; i++)
161        {
162            if (i != 0)
163            {
164                LVM_INT32 Temp1;  /* to avoid QAC warning on type conversion */
165                LVM_INT32 Temp2;  /* to avoid QAC warning on type conversion */
166
167                Temp2=(LVM_INT32)DelayLengthSamples;
168                MUL32x16INTO32(Temp2, ScaleTable[i], Temp1, 15)
169                Temp=(LVM_UINT32)Temp1;
170            }
171            else
172            {
173               Temp = DelayLengthSamples;
174            }
175            APDelaySize = Temp  / 1500;
176
177
178            /*
179             * Set the fixed delay
180             */
181            Temp                  = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 48000;
182            pPrivate->Delay_AP[i] = pPrivate->T[i] - Temp;
183
184
185            /*
186             * Set the tap selection
187             */
188            if (pPrivate->AB_Selection)
189            {
190                /* Smooth from tap A to tap B */
191                pPrivate->pOffsetB[i]             = &pPrivate->pDelay_T[i][pPrivate->T[i] - Temp - APDelaySize];
192                pPrivate->B_DelaySize[i]          = APDelaySize;
193                pPrivate->Mixer_APTaps[i].Target1 = 0;
194                pPrivate->Mixer_APTaps[i].Target2 = 0x7fffffff;
195            }
196            else
197            {
198                /* Smooth from tap B to tap A */
199                pPrivate->pOffsetA[i]             = &pPrivate->pDelay_T[i][pPrivate->T[i] - Temp - APDelaySize];
200                pPrivate->A_DelaySize[i]          = APDelaySize;
201                pPrivate->Mixer_APTaps[i].Target2 = 0;
202                pPrivate->Mixer_APTaps[i].Target1 = 0x7fffffff;
203            }
204
205            /*
206             * Set the maximum block size to the smallest delay size
207             */
208            pPrivate->MaxBlkLen   = Temp;
209            if (pPrivate->MaxBlkLen > pPrivate->A_DelaySize[i])
210            {
211                pPrivate->MaxBlkLen = pPrivate->A_DelaySize[i];
212            }
213            if (pPrivate->MaxBlkLen > pPrivate->B_DelaySize[i])
214            {
215                pPrivate->MaxBlkLen = pPrivate->B_DelaySize[i];
216            }
217        }
218        if (pPrivate->AB_Selection)
219        {
220            pPrivate->AB_Selection = 0;
221        }
222        else
223        {
224            pPrivate->AB_Selection = 1;
225        }
226
227
228        /*
229         * Limit the maximum block length
230         */
231        pPrivate->MaxBlkLen=pPrivate->MaxBlkLen-2;                                  /* Just as a precausion, but no problem if we remove this line      */
232        if(pPrivate->MaxBlkLen > pPrivate->InstanceParams.MaxBlockSize)
233        {
234            pPrivate->MaxBlkLen = (LVM_INT32)pPrivate->InstanceParams.MaxBlockSize;
235        }
236    }
237
238
239    /*
240     * Update the low pass filter coefficient
241     */
242    if( (pPrivate->NewParams.Damping    != pPrivate->CurrentParams.Damping)    ||
243        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
244        (pPrivate->bFirstControl        == LVM_TRUE))
245    {
246
247        LVM_INT32       Temp;
248        LVM_INT32       Omega;
249        FO_C32_Coefs_t  Coeffs;
250        LVM_INT16       i;
251        LVM_INT16       Damping      = (LVM_INT16)((pPrivate->NewParams.Damping * 100) + 1000);
252        LVM_INT32       ScaleTable[] = {LVREV_T_3_Power_0_on_4, LVREV_T_3_Power_1_on_4, LVREV_T_3_Power_2_on_4, LVREV_T_3_Power_3_on_4};
253
254
255        /*
256         * For each filter
257         */
258        for (i=0; i<NumberOfDelayLines; i++)
259        {
260            if (i != 0)
261            {
262                MUL32x16INTO32(ScaleTable[i], Damping, Temp, 15)
263            }
264            else
265            {
266                Temp = Damping;
267            }
268            if(Temp <= (LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
269            {
270                Omega = LVM_GetOmega((LVM_UINT16)Temp, pPrivate->NewParams.SampleRate);
271                LVM_FO_LPF(Omega, &Coeffs);
272            }
273            else
274            {
275                Coeffs.A0 = 0x7FF00000;
276                Coeffs.A1 = 0;
277                Coeffs.B1 = 0;
278            }
279            FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->RevLPCoefs[i], &pPrivate->pFastData->RevLPTaps[i], &Coeffs);
280        }
281    }
282
283
284    /*
285     * Update All-pass filter mixer time constants
286     */
287    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
288        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
289        (pPrivate->NewParams.Density    != pPrivate->CurrentParams.Density))
290    {
291        LVM_INT16   i;
292        LVM_INT32   Alpha    = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_ALLPASS_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), 1);
293        LVM_INT32   AlphaTap = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_ALLPASS_TAP_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), 1);
294
295        for (i=0; i<4; i++)
296        {
297            pPrivate->Mixer_APTaps[i].Alpha1       = AlphaTap;
298            pPrivate->Mixer_APTaps[i].Alpha2       = AlphaTap;
299            pPrivate->Mixer_SGFeedback[i].Alpha    = Alpha;
300            pPrivate->Mixer_SGFeedforward[i].Alpha = Alpha;
301        }
302    }
303
304
305    /*
306     * Update the feed back gain
307     */
308    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
309        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
310        (pPrivate->NewParams.T60        != pPrivate->CurrentParams.T60)        ||
311        (pPrivate->bFirstControl        == LVM_TRUE))
312    {
313
314        LVM_INT32               G[4];                       /* Feedback gain (Q7.24) */
315
316        if(pPrivate->NewParams.T60 == 0)
317        {
318            G[3] = 0;
319            G[2] = 0;
320            G[1] = 0;
321            G[0] = 0;
322        }
323        else
324        {
325            LVM_INT32   Temp1;
326            LVM_INT32   Temp2;
327            LVM_INT16   i;
328            LVM_INT16   ScaleTable[] = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4, LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
329
330
331            /*
332             * For each delay line
333             */
334            for (i=0; i<NumberOfDelayLines; i++)
335            {
336                Temp1 = (3 * pPrivate->RoomSizeInms * ScaleTable[i]) / pPrivate->NewParams.T60;
337                if(Temp1 >= (4 << 15))
338                {
339                    G[i] = 0;
340                }
341                else if((Temp1 >= (2 << 15)))
342                {
343                    Temp2 = LVM_Power10(-(Temp1 << 14));
344                    Temp1 = LVM_Power10(-(Temp1 << 14));
345                    MUL32x32INTO32(Temp1,Temp2,Temp1,24)
346                }
347                else
348                {
349                    Temp1 = LVM_Power10(-(Temp1 << 15));
350                }
351                if (NumberOfDelayLines == 1)
352                {
353                    G[i] = Temp1;
354                }
355                else
356                {
357                    LVM_INT32   TempG;
358                    MUL32x16INTO32(Temp1,ONE_OVER_SQRT_TWO,TempG,15)
359                    G[i]=TempG;
360                }
361            }
362        }
363
364        /* Set up the feedback mixers for four delay lines */
365        pPrivate->FeedbackMixer[0].Target=G[0]<<7;
366        pPrivate->FeedbackMixer[1].Target=G[1]<<7;
367        pPrivate->FeedbackMixer[2].Target=G[2]<<7;
368        pPrivate->FeedbackMixer[3].Target=G[3]<<7;
369    }
370
371
372    /*
373     * Calculate the gain correction
374     */
375    if((pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
376       (pPrivate->NewParams.Level    != pPrivate->CurrentParams.Level)    ||
377       (pPrivate->NewParams.T60      != pPrivate->CurrentParams.T60) )
378    {
379        LVM_INT32 Index=0;
380        LVM_INT32 i=0;
381        LVM_INT32 Gain=0;
382        LVM_INT32 RoomSize=0;
383        LVM_INT32 T60;
384        LVM_INT32 Coefs[5];
385
386        if(pPrivate->NewParams.RoomSize==0)
387        {
388            RoomSize=1;
389        }
390        else
391        {
392            RoomSize=(LVM_INT32)pPrivate->NewParams.RoomSize;
393        }
394
395        if(pPrivate->NewParams.T60<100)
396        {
397            T60 = 100 * LVREV_T60_SCALE;
398        }
399        else
400        {
401            T60 = pPrivate->NewParams.T60 * LVREV_T60_SCALE;
402        }
403
404        /* Find the nearest room size in table */
405        for(i=0;i<24;i++)
406        {
407            if(RoomSize<= LVREV_GainPolyTable[i][0])
408            {
409                Index=i;
410                break;
411            }
412        }
413
414
415        if(RoomSize==LVREV_GainPolyTable[Index][0])
416        {
417            /* Take table values if the room size is in table */
418            for(i=1;i<5;i++)
419            {
420                Coefs[i-1]=LVREV_GainPolyTable[Index][i];
421            }
422            Coefs[4]=0;
423            Gain=LVM_Polynomial(3,Coefs,T60);       /* Q.24 result */
424        }
425        else
426        {
427            /* Interpolate the gain between nearest room sizes */
428
429            LVM_INT32 Gain1,Gain2;
430            LVM_INT32 Tot_Dist,Dist;
431
432            Tot_Dist=LVREV_GainPolyTable[Index][0]-LVREV_GainPolyTable[Index-1][0];
433            Dist=RoomSize-LVREV_GainPolyTable[Index-1][0];
434
435
436            /* Get gain for first */
437            for(i=1;i<5;i++)
438            {
439                Coefs[i-1]=LVREV_GainPolyTable[Index-1][i];
440            }
441            Coefs[4]=0;
442
443            Gain1=LVM_Polynomial(3,Coefs,T60);      /* Q.24 result */
444
445            /* Get gain for second */
446            for(i=1;i<5;i++)
447            {
448                Coefs[i-1]=LVREV_GainPolyTable[Index][i];
449            }
450            Coefs[4]=0;
451
452            Gain2=LVM_Polynomial(3,Coefs,T60);      /* Q.24 result */
453
454            /* Linear Interpolate the gain */
455            Gain = Gain1+ (((Gain2-Gain1)*Dist)/(Tot_Dist));
456        }
457
458
459        /*
460         * Get the inverse of gain: Q.15
461         * Gain is mostly above one except few cases, take only gains above 1
462         */
463        if(Gain < 16777216L)
464        {
465            pPrivate->Gain= 32767;
466        }
467        else
468        {
469            pPrivate->Gain=(LVM_INT16)(LVM_MAXINT_32/(Gain>>8));
470        }
471
472
473        Index=((32767*100)/(100+pPrivate->NewParams.Level));
474        pPrivate->Gain=(LVM_INT16)((pPrivate->Gain*Index)>>15);
475        pPrivate->GainMixer.Target = pPrivate->Gain*Index;
476    }
477
478
479    /*
480     * Update the all pass comb filter coefficient
481     */
482    if( (pPrivate->NewParams.Density != pPrivate->CurrentParams.Density) ||
483        (pPrivate->bFirstControl     == LVM_TRUE))
484    {
485        LVM_INT16   i;
486        LVM_INT32   b = pPrivate->NewParams.Density * LVREV_B_8_on_1000;
487
488        for (i=0;i<4; i++)
489        {
490            pPrivate->Mixer_SGFeedback[i].Target    = b;
491            pPrivate->Mixer_SGFeedforward[i].Target = b;
492        }
493    }
494
495
496    /*
497     * Update the bypass mixer time constant
498     */
499    if((pPrivate->NewParams.SampleRate   != pPrivate->CurrentParams.SampleRate)   ||
500       (pPrivate->bFirstControl          == LVM_TRUE))
501    {
502        LVM_UINT16   NumChannels = 1;                       /* Assume MONO format */
503        LVM_INT32    Alpha;
504
505        Alpha = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_FEEDBACKMIXER_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
506        pPrivate->FeedbackMixer[0].Alpha=Alpha;
507        pPrivate->FeedbackMixer[1].Alpha=Alpha;
508        pPrivate->FeedbackMixer[2].Alpha=Alpha;
509        pPrivate->FeedbackMixer[3].Alpha=Alpha;
510
511        NumChannels = 2;                                    /* Always stereo output */
512        pPrivate->BypassMixer.Alpha1 = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_BYPASSMIXER_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
513        pPrivate->BypassMixer.Alpha2 = pPrivate->BypassMixer.Alpha1;
514        pPrivate->GainMixer.Alpha    = pPrivate->BypassMixer.Alpha1;
515    }
516
517
518    /*
519     * Update the bypass mixer targets
520     */
521    if( (pPrivate->NewParams.Level != pPrivate->CurrentParams.Level) &&
522        (pPrivate->NewParams.OperatingMode == LVM_MODE_ON))
523    {
524        pPrivate->BypassMixer.Target2 = ((LVM_INT32)(pPrivate->NewParams.Level * 32767)/100)<<16;
525        pPrivate->BypassMixer.Target1 = 0x00000000;
526        if ((pPrivate->NewParams.Level == 0) && (pPrivate->bFirstControl == LVM_FALSE))
527        {
528            pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
529        }
530        if (pPrivate->NewParams.Level != 0)
531        {
532            pPrivate->bDisableReverb = LVM_FALSE;
533        }
534    }
535
536    if(pPrivate->NewParams.OperatingMode != pPrivate->CurrentParams.OperatingMode)
537    {
538        if(pPrivate->NewParams.OperatingMode == LVM_MODE_ON)
539        {
540            pPrivate->BypassMixer.Target2 = ((LVM_INT32)(pPrivate->NewParams.Level * 32767)/100)<<16;
541            pPrivate->BypassMixer.Target1 = 0x00000000;
542
543            pPrivate->BypassMixer.CallbackSet2 = LVM_FALSE;
544            OperatingMode                      = LVM_MODE_ON;
545            if (pPrivate->NewParams.Level == 0)
546            {
547                pPrivate->bDisableReverb = LVM_TRUE;
548            }
549            else
550            {
551                pPrivate->bDisableReverb = LVM_FALSE;
552            }
553        }
554        else if (pPrivate->bFirstControl == LVM_FALSE)
555        {
556            pPrivate->BypassMixer.Target2 = 0x00000000;
557            pPrivate->BypassMixer.Target1 = 0x00000000;
558            pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
559            pPrivate->GainMixer.Target    = 0x03FFFFFF;
560            OperatingMode = LVM_MODE_ON;
561        }
562        else
563        {
564            OperatingMode = LVM_MODE_OFF;
565        }
566    }
567
568
569    /*
570     * If it is the first call to ApplyNew settings force the current to the target to begin immediate playback of the effect
571     */
572    if(pPrivate->bFirstControl == LVM_TRUE)
573    {
574        pPrivate->BypassMixer.Current1 = pPrivate->BypassMixer.Target1;
575        pPrivate->BypassMixer.Current2 = pPrivate->BypassMixer.Target2;
576    }
577
578
579    /*
580     * Copy the new parameters
581     */
582    pPrivate->CurrentParams = pPrivate->NewParams;
583    pPrivate->CurrentParams.OperatingMode = OperatingMode;
584
585
586    /*
587     * Update flag
588     */
589    if(pPrivate->bFirstControl == LVM_TRUE)
590    {
591        pPrivate->bFirstControl = LVM_FALSE;
592    }
593
594
595    return LVREV_SUCCESS;
596}
597#else /* BUILD_FLOAT*/
598LVREV_ReturnStatus_en LVREV_ApplyNewSettings (LVREV_Instance_st     *pPrivate)
599{
600
601    LVM_Mode_en  OperatingMode;
602    LVM_INT32    NumberOfDelayLines;
603
604
605    /* Check for NULL pointer */
606    if(pPrivate == LVM_NULL)
607    {
608        return LVREV_NULLADDRESS;
609    }
610
611    OperatingMode = pPrivate->NewParams.OperatingMode;
612
613    if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
614    {
615        NumberOfDelayLines = 4;
616    }
617    else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
618    {
619        NumberOfDelayLines = 2;
620    }
621    else
622    {
623        NumberOfDelayLines = 1;
624    }
625
626    /*
627     * Update the high pass filter coefficients
628     */
629    if((pPrivate->NewParams.HPF        != pPrivate->CurrentParams.HPF)        ||
630       (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
631       (pPrivate->bFirstControl        == LVM_TRUE))
632    {
633        LVM_FLOAT       Omega;
634        FO_FLOAT_Coefs_t  Coeffs;
635
636        Omega = LVM_GetOmega(pPrivate->NewParams.HPF, pPrivate->NewParams.SampleRate);
637        LVM_FO_HPF(Omega, &Coeffs);
638        FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->HPCoefs,
639                                         &pPrivate->pFastData->HPTaps, &Coeffs);
640        LoadConst_Float(0,
641                        (void *)&pPrivate->pFastData->HPTaps, /* Destination Cast to void: \
642                                                                 no dereferencing in function*/
643                        sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
644    }
645
646
647    /*
648     * Update the low pass filter coefficients
649     */
650    if((pPrivate->NewParams.LPF        != pPrivate->CurrentParams.LPF)        ||
651       (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
652       (pPrivate->bFirstControl        == LVM_TRUE))
653    {
654        LVM_FLOAT       Omega;
655        FO_FLOAT_Coefs_t  Coeffs;
656
657        Coeffs.A0 = 1;
658        Coeffs.A1 = 0;
659        Coeffs.B1 = 0;
660        if(pPrivate->NewParams.LPF <= (LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
661        {
662            Omega = LVM_GetOmega(pPrivate->NewParams.LPF, pPrivate->NewParams.SampleRate);
663
664            /*
665             * Do not apply filter if w =2*pi*fc/fs >= 2.9
666             */
667            if(Omega <= (LVM_FLOAT)LVREV_2_9_INQ29)
668            {
669                LVM_FO_LPF(Omega, &Coeffs);
670            }
671        }
672        FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->LPCoefs,
673                                         &pPrivate->pFastData->LPTaps, &Coeffs);
674        LoadConst_Float(0,
675                        (void *)&pPrivate->pFastData->LPTaps, /* Destination Cast to void: \
676                                                                 no dereferencing in function*/
677                        sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
678    }
679
680
681    /*
682     * Calculate the room size parameter
683     */
684    if( pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize)
685    {
686        /* Room size range is 10ms to 200ms
687         * 0%   -- 10ms
688         * 50%  -- 65ms
689         * 100% -- 120ms
690         */
691        pPrivate->RoomSizeInms = 10 + (((pPrivate->NewParams.RoomSize*11) + 5) / 10);
692    }
693
694
695    /*
696     * Update the T delay number of samples and the all pass delay number of samples
697     */
698    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
699        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
700        (pPrivate->bFirstControl        == LVM_TRUE))
701    {
702
703        LVM_UINT32  Temp;
704        LVM_INT32   APDelaySize;
705        LVM_INT32   Fs = LVM_GetFsFromTable(pPrivate->NewParams.SampleRate);
706        LVM_UINT32  DelayLengthSamples = (LVM_UINT32)(Fs * pPrivate->RoomSizeInms);
707        LVM_INT16   i;
708        LVM_FLOAT   ScaleTable[]  = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4, \
709                                     LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
710        LVM_INT16   MaxT_Delay[]  = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, \
711                                     LVREV_MAX_T2_DELAY, LVREV_MAX_T3_DELAY};
712        LVM_INT16   MaxAP_Delay[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY, \
713                                     LVREV_MAX_AP2_DELAY, LVREV_MAX_AP3_DELAY};
714
715
716        /*
717         * For each delay line
718         */
719        for (i = 0; i < NumberOfDelayLines; i++)
720        {
721            if (i != 0)
722            {
723                LVM_FLOAT Temp1;  /* to avoid QAC warning on type conversion */
724
725                Temp1=(LVM_FLOAT)DelayLengthSamples;
726                Temp = (LVM_UINT32)(Temp1 * ScaleTable[i]);
727            }
728            else
729            {
730               Temp = DelayLengthSamples;
731            }
732            APDelaySize = Temp  / 1500;
733
734
735            /*
736             * Set the fixed delay
737             */
738
739#ifdef HIGHER_FS
740            Temp  = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 192000;
741#else
742            Temp  = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 48000;
743#endif
744            pPrivate->Delay_AP[i] = pPrivate->T[i] - Temp;
745
746
747            /*
748             * Set the tap selection
749             */
750            if (pPrivate->AB_Selection)
751            {
752                /* Smooth from tap A to tap B */
753                pPrivate->pOffsetB[i]             = &pPrivate->pDelay_T[i][pPrivate->T[i] - \
754                                                                           Temp - APDelaySize];
755                pPrivate->B_DelaySize[i]          = APDelaySize;
756                pPrivate->Mixer_APTaps[i].Target1 = 0;
757                pPrivate->Mixer_APTaps[i].Target2 = 1.0f;
758            }
759            else
760            {
761                /* Smooth from tap B to tap A */
762                pPrivate->pOffsetA[i]             = &pPrivate->pDelay_T[i][pPrivate->T[i] - \
763                                                                           Temp - APDelaySize];
764                pPrivate->A_DelaySize[i]          = APDelaySize;
765                pPrivate->Mixer_APTaps[i].Target2 = 0;
766                pPrivate->Mixer_APTaps[i].Target1 = 1.0f;
767            }
768
769            /*
770             * Set the maximum block size to the smallest delay size
771             */
772            pPrivate->MaxBlkLen   = Temp;
773            if (pPrivate->MaxBlkLen > pPrivate->A_DelaySize[i])
774            {
775                pPrivate->MaxBlkLen = pPrivate->A_DelaySize[i];
776            }
777            if (pPrivate->MaxBlkLen > pPrivate->B_DelaySize[i])
778            {
779                pPrivate->MaxBlkLen = pPrivate->B_DelaySize[i];
780            }
781        }
782        if (pPrivate->AB_Selection)
783        {
784            pPrivate->AB_Selection = 0;
785        }
786        else
787        {
788            pPrivate->AB_Selection = 1;
789        }
790
791
792        /*
793         * Limit the maximum block length
794         */
795        /* Just as a precausion, but no problem if we remove this line      */
796        pPrivate->MaxBlkLen = pPrivate->MaxBlkLen - 2;
797        if(pPrivate->MaxBlkLen > pPrivate->InstanceParams.MaxBlockSize)
798        {
799            pPrivate->MaxBlkLen = (LVM_INT32)pPrivate->InstanceParams.MaxBlockSize;
800        }
801    }
802
803
804
805    /*
806     * Update the low pass filter coefficient
807     */
808    if( (pPrivate->NewParams.Damping    != pPrivate->CurrentParams.Damping)    ||
809        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
810        (pPrivate->bFirstControl        == LVM_TRUE))
811    {
812
813        LVM_INT32       Temp;
814        LVM_FLOAT       Omega;
815        FO_FLOAT_Coefs_t  Coeffs;
816        LVM_INT16       i;
817        LVM_INT16       Damping      = (LVM_INT16)((pPrivate->NewParams.Damping * 100) + 1000);
818        LVM_FLOAT       ScaleTable[] = {LVREV_T_3_Power_0_on_4, LVREV_T_3_Power_1_on_4,
819                                        LVREV_T_3_Power_2_on_4, LVREV_T_3_Power_3_on_4};
820
821
822        /*
823         * For each filter
824         */
825        for (i = 0; i < NumberOfDelayLines; i++)
826        {
827            if (i != 0)
828            {
829                Temp = (LVM_INT32)(ScaleTable[i] * Damping);
830            }
831            else
832            {
833                Temp = Damping;
834            }
835            if(Temp <= (LVM_INT32)(LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
836            {
837                Omega = LVM_GetOmega(Temp, pPrivate->NewParams.SampleRate);
838                LVM_FO_LPF(Omega, &Coeffs);
839            }
840            else
841            {
842                Coeffs.A0 = 1;
843                Coeffs.A1 = 0;
844                Coeffs.B1 = 0;
845            }
846            FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->RevLPCoefs[i],
847                                            &pPrivate->pFastData->RevLPTaps[i], &Coeffs);
848        }
849    }
850
851
852    /*
853     * Update All-pass filter mixer time constants
854     */
855    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
856        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
857        (pPrivate->NewParams.Density    != pPrivate->CurrentParams.Density))
858    {
859        LVM_INT16   i;
860        LVM_FLOAT   Alpha;
861        LVM_FLOAT   AlphaTap;
862
863        Alpha = LVM_Mixer_TimeConstant(LVREV_ALLPASS_TC,
864                                       LVM_GetFsFromTable(pPrivate->NewParams.SampleRate),
865                                       1);
866
867        AlphaTap = LVM_Mixer_TimeConstant(LVREV_ALLPASS_TAP_TC,
868                                          LVM_GetFsFromTable(pPrivate->NewParams.SampleRate),
869                                          1);
870
871        for (i = 0; i < 4; i++)
872        {
873            pPrivate->Mixer_APTaps[i].Alpha1       = AlphaTap;
874            pPrivate->Mixer_APTaps[i].Alpha2       = AlphaTap;
875            pPrivate->Mixer_SGFeedback[i].Alpha    = Alpha;
876            pPrivate->Mixer_SGFeedforward[i].Alpha = Alpha;
877        }
878    }
879
880
881    /*
882     * Update the feed back gain
883     */
884    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
885        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
886        (pPrivate->NewParams.T60        != pPrivate->CurrentParams.T60)        ||
887        (pPrivate->bFirstControl        == LVM_TRUE))
888    {
889
890        LVM_FLOAT               G[4];                       /* Feedback gain (Q7.24) */
891
892        if(pPrivate->NewParams.T60 == 0)
893        {
894            G[3] = 0;
895            G[2] = 0;
896            G[1] = 0;
897            G[0] = 0;
898        }
899        else
900        {
901            LVM_FLOAT   Temp1;
902            LVM_FLOAT   Temp2;
903            LVM_INT16   i;
904            LVM_FLOAT   ScaleTable[] = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4,
905                                        LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
906
907
908            /*
909             * For each delay line
910             */
911            for (i = 0; i < NumberOfDelayLines; i++)
912            {
913                Temp1 = (3 * pPrivate->RoomSizeInms * ScaleTable[i]) / pPrivate->NewParams.T60;
914                if(Temp1 >= (4))
915                {
916                    G[i] = 0;
917                }
918                else if((Temp1 >= (2)))
919                {
920                    Temp2 = LVM_Power10(-(Temp1 / 2.0f));
921                    Temp1 = LVM_Power10(-(Temp1 / 2.0f));
922                    Temp1 = Temp1 * Temp2;
923                }
924                else
925                {
926                    Temp1 = LVM_Power10(-(Temp1));
927                }
928                if (NumberOfDelayLines == 1)
929                {
930                    G[i] = Temp1;
931                }
932                else
933                {
934                    LVM_FLOAT   TempG;
935                    TempG = Temp1 * ONE_OVER_SQRT_TWO;
936                    G[i]=TempG;
937                }
938            }
939        }
940
941        /* Set up the feedback mixers for four delay lines */
942        pPrivate->FeedbackMixer[0].Target=G[0];
943        pPrivate->FeedbackMixer[1].Target=G[1];
944        pPrivate->FeedbackMixer[2].Target=G[2];
945        pPrivate->FeedbackMixer[3].Target=G[3];
946    }
947
948
949    /*
950     * Calculate the gain correction
951     */
952    if((pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
953       (pPrivate->NewParams.Level    != pPrivate->CurrentParams.Level)    ||
954       (pPrivate->NewParams.T60      != pPrivate->CurrentParams.T60) )
955    {
956        LVM_INT32 Index=0;
957        LVM_FLOAT Index_FLOAT;
958        LVM_INT32 i=0;
959        LVM_FLOAT Gain=0;
960        LVM_INT32 RoomSize=0;
961        LVM_FLOAT T60;
962        LVM_FLOAT Coefs[5];
963
964
965        if(pPrivate->NewParams.RoomSize == 0)
966        {
967            RoomSize = 1;
968        }
969        else
970        {
971            RoomSize = (LVM_INT32)pPrivate->NewParams.RoomSize;
972        }
973
974
975        if(pPrivate->NewParams.T60 < 100)
976        {
977            T60 = 100 * LVREV_T60_SCALE;
978        }
979        else
980        {
981            T60 = pPrivate->NewParams.T60 * LVREV_T60_SCALE;
982        }
983
984        /* Find the nearest room size in table */
985        for(i = 0; i < 24; i++)
986        {
987            if(RoomSize <= LVREV_GainPolyTable[i][0])
988            {
989                Index = i;
990                break;
991            }
992        }
993
994
995        if(RoomSize == LVREV_GainPolyTable[Index][0])
996        {
997            /* Take table values if the room size is in table */
998            for(i = 1; i < 5; i++)
999            {
1000                Coefs[i-1] = LVREV_GainPolyTable[Index][i];
1001            }
1002            Coefs[4] = 0;
1003            Gain = LVM_Polynomial(3, Coefs, T60);       /* Q.24 result */
1004        }
1005        else
1006        {
1007            /* Interpolate the gain between nearest room sizes */
1008
1009            LVM_FLOAT Gain1,Gain2;
1010            LVM_INT32 Tot_Dist,Dist;
1011
1012            Tot_Dist = (LVM_UINT32)LVREV_GainPolyTable[Index][0] - \
1013                                            (LVM_UINT32)LVREV_GainPolyTable[Index-1][0];
1014            Dist = RoomSize - (LVM_UINT32)LVREV_GainPolyTable[Index - 1][0];
1015
1016
1017            /* Get gain for first */
1018            for(i = 1; i < 5; i++)
1019            {
1020                Coefs[i-1] = LVREV_GainPolyTable[Index-1][i];
1021            }
1022            Coefs[4] = 0;
1023
1024            Gain1 = LVM_Polynomial(3, Coefs, T60);      /* Q.24 result */
1025
1026            /* Get gain for second */
1027            for(i = 1; i < 5; i++)
1028            {
1029                Coefs[i-1] = LVREV_GainPolyTable[Index][i];
1030            }
1031            Coefs[4] = 0;
1032
1033            Gain2 = LVM_Polynomial(3, Coefs, T60);      /* Q.24 result */
1034
1035            /* Linear Interpolate the gain */
1036            Gain = Gain1 + (((Gain2 - Gain1) * Dist) / (Tot_Dist));
1037        }
1038
1039
1040        /*
1041         * Get the inverse of gain: Q.15
1042         * Gain is mostly above one except few cases, take only gains above 1
1043         */
1044        if(Gain < 1)
1045        {
1046            pPrivate->Gain = 1;
1047        }
1048        else
1049        {
1050            pPrivate->Gain = 1 / Gain;
1051        }
1052
1053        Index_FLOAT = 100.0f / (LVM_FLOAT)(100 + pPrivate->NewParams.Level);
1054        pPrivate->Gain = pPrivate->Gain * Index_FLOAT;
1055        pPrivate->GainMixer.Target = (pPrivate->Gain*Index_FLOAT) / 2;
1056    }
1057
1058
1059    /*
1060     * Update the all pass comb filter coefficient
1061     */
1062    if( (pPrivate->NewParams.Density != pPrivate->CurrentParams.Density) ||
1063        (pPrivate->bFirstControl     == LVM_TRUE))
1064    {
1065        LVM_INT16   i;
1066        LVM_FLOAT   b = (LVM_FLOAT)pPrivate->NewParams.Density * LVREV_B_8_on_1000;
1067
1068        for (i = 0; i < 4; i++)
1069        {
1070            pPrivate->Mixer_SGFeedback[i].Target    = b;
1071            pPrivate->Mixer_SGFeedforward[i].Target = b;
1072        }
1073    }
1074
1075
1076    /*
1077     * Update the bypass mixer time constant
1078     */
1079    if((pPrivate->NewParams.SampleRate   != pPrivate->CurrentParams.SampleRate)   ||
1080       (pPrivate->bFirstControl          == LVM_TRUE))
1081    {
1082        LVM_UINT16   NumChannels = 1;                       /* Assume MONO format */
1083        LVM_FLOAT    Alpha;
1084
1085        Alpha = LVM_Mixer_TimeConstant(LVREV_FEEDBACKMIXER_TC,
1086                                       LVM_GetFsFromTable(pPrivate->NewParams.SampleRate),
1087                                       NumChannels);
1088        pPrivate->FeedbackMixer[0].Alpha = Alpha;
1089        pPrivate->FeedbackMixer[1].Alpha = Alpha;
1090        pPrivate->FeedbackMixer[2].Alpha = Alpha;
1091        pPrivate->FeedbackMixer[3].Alpha = Alpha;
1092
1093        NumChannels = 2;                                    /* Always stereo output */
1094        pPrivate->BypassMixer.Alpha1 = LVM_Mixer_TimeConstant(LVREV_BYPASSMIXER_TC,
1095                             LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
1096        pPrivate->BypassMixer.Alpha2 = pPrivate->BypassMixer.Alpha1;
1097        pPrivate->GainMixer.Alpha    = pPrivate->BypassMixer.Alpha1;
1098    }
1099
1100
1101    /*
1102     * Update the bypass mixer targets
1103     */
1104    if( (pPrivate->NewParams.Level != pPrivate->CurrentParams.Level) &&
1105        (pPrivate->NewParams.OperatingMode == LVM_MODE_ON))
1106    {
1107        pPrivate->BypassMixer.Target2 = (LVM_FLOAT)(pPrivate->NewParams.Level ) / 100.0f;
1108        pPrivate->BypassMixer.Target1 = 0x00000000;
1109        if ((pPrivate->NewParams.Level == 0) && (pPrivate->bFirstControl == LVM_FALSE))
1110        {
1111            pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
1112        }
1113        if (pPrivate->NewParams.Level != 0)
1114        {
1115            pPrivate->bDisableReverb = LVM_FALSE;
1116        }
1117    }
1118
1119    if(pPrivate->NewParams.OperatingMode != pPrivate->CurrentParams.OperatingMode)
1120    {
1121        if(pPrivate->NewParams.OperatingMode == LVM_MODE_ON)
1122        {
1123            pPrivate->BypassMixer.Target2 = (LVM_FLOAT)(pPrivate->NewParams.Level ) / 100.0f;
1124            pPrivate->BypassMixer.Target1 = 0x00000000;
1125
1126            pPrivate->BypassMixer.CallbackSet2 = LVM_FALSE;
1127            OperatingMode                      = LVM_MODE_ON;
1128            if (pPrivate->NewParams.Level == 0)
1129            {
1130                pPrivate->bDisableReverb = LVM_TRUE;
1131            }
1132            else
1133            {
1134                pPrivate->bDisableReverb = LVM_FALSE;
1135            }
1136        }
1137        else if (pPrivate->bFirstControl == LVM_FALSE)
1138        {
1139            pPrivate->BypassMixer.Target2 = 0x00000000;
1140            pPrivate->BypassMixer.Target1 = 0x00000000;
1141            pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
1142            pPrivate->GainMixer.Target    = 0.03125f;
1143            OperatingMode = LVM_MODE_ON;
1144        }
1145        else
1146        {
1147            OperatingMode = LVM_MODE_OFF;
1148        }
1149    }
1150
1151
1152    /*  If it is the first call to ApplyNew settings force the current to the target \
1153        to begin immediate playback of the effect */
1154    if(pPrivate->bFirstControl == LVM_TRUE)
1155    {
1156        pPrivate->BypassMixer.Current1 = pPrivate->BypassMixer.Target1;
1157        pPrivate->BypassMixer.Current2 = pPrivate->BypassMixer.Target2;
1158    }
1159
1160
1161    /*
1162     * Copy the new parameters
1163     */
1164    pPrivate->CurrentParams = pPrivate->NewParams;
1165    pPrivate->CurrentParams.OperatingMode = OperatingMode;
1166
1167
1168    /*
1169     * Update flag
1170     */
1171    if(pPrivate->bFirstControl == LVM_TRUE)
1172    {
1173        pPrivate->bFirstControl = LVM_FALSE;
1174    }
1175
1176
1177    return LVREV_SUCCESS;
1178}
1179#endif /*BUILD_FLOAT*/
1180/****************************************************************************************/
1181/*                                                                                      */
1182/* FUNCTION:                BypassMixer_Callback                                        */
1183/*                                                                                      */
1184/* DESCRIPTION:                                                                         */
1185/*  Controls the On to Off operating mode transition                                    */
1186/*                                                                                      */
1187/* PARAMETERS:                                                                          */
1188/*  pPrivate                Pointer to the instance private parameters                  */
1189/*                                                                                      */
1190/* RETURNS:                                                                             */
1191/*  LVREV_Success           Succeeded                                                   */
1192/*  LVREV_NULLADDRESS       When pPrivate is NULL                                       */
1193/*                                                                                      */
1194/* NOTES:                                                                               */
1195/*                                                                                      */
1196/****************************************************************************************/
1197LVM_INT32 BypassMixer_Callback (void *pCallbackData,
1198                                void *pGeneralPurpose,
1199                                LVM_INT16 GeneralPurpose )
1200{
1201
1202    LVREV_Instance_st     *pLVREV_Private = (LVREV_Instance_st *)pCallbackData;
1203
1204
1205    /*
1206     * Avoid build warnings
1207     */
1208    (void)pGeneralPurpose;
1209    (void)GeneralPurpose;
1210
1211
1212    /*
1213     * Turn off
1214     */
1215    pLVREV_Private->CurrentParams.OperatingMode = LVM_MODE_OFF;
1216    pLVREV_Private->bDisableReverb              = LVM_TRUE;
1217    LVREV_ClearAudioBuffers((LVREV_Handle_t)pCallbackData);
1218
1219
1220    return 0;
1221}
1222
1223/* End of file */
1224
1225