From 2c8e5cab3faa6d360e222b7a6c40a80083d021ac Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 9 Jul 2010 12:28:50 -0700 Subject: First submission of audio effect library from NXP software. This CL contains the first open sourceable version of the audio effect library from NXP software. The effects implemented are: - Bass boost - Virtualizer (stereo widening) - Equalizer - Spectrum analyzer Source file for the effect engines are located under libeffects/lvm/lib The wrapper implementing the interface with the audio effect framework in under libeffects/lvm/wrapper The code of other effect libraries has also been reorganized fo clarity: - the effect factory is now under libeffects/factory - the test equalizer and reverb effects are under libeffect/testlibs - the visualizer is under libeffects/virtualizer Change-Id: I8d91e2181f81b89f8fc0c1e1e6bf552c5809b2eb --- media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c | 306 +++++++++++++ media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h | 106 +++++ media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c | 501 ++++++++++++++++++++++ media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c | 329 ++++++++++++++ media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h | 141 ++++++ media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c | 208 +++++++++ media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c | 203 +++++++++ 7 files changed, 1794 insertions(+) create mode 100755 media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c create mode 100755 media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h create mode 100755 media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c create mode 100755 media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c create mode 100755 media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h create mode 100755 media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c create mode 100755 media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c (limited to 'media/libeffects/lvm/lib/Eq/src') diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c new file mode 100755 index 0000000..4881049 --- /dev/null +++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c @@ -0,0 +1,306 @@ +/* + * Copyright (C) 2004-2010 NXP Software + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/********************************************************************************** + + $Author: beq07716 $ + $Revision: 1005 $ + $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $ + +***********************************************************************************/ + +/****************************************************************************************/ +/* */ +/* Includes */ +/* */ +/****************************************************************************************/ + +#include "LVEQNB_Private.h" + + +/****************************************************************************************/ +/* */ +/* Defines */ +/* */ +/****************************************************************************************/ + +#define PI 3.14159265358979 + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_DoublePrecCoefs */ +/* */ +/* DESCRIPTION: */ +/* Calculate double precision coefficients for a peaking filter */ +/* */ +/* PARAMETERS: */ +/* Fs Sampling frequency index */ +/* pFilterDefinition Pointer to the filter definition */ +/* pCoefficients Pointer to the coefficients */ +/* */ +/* RETURNS: */ +/* LVEQNB_SUCCESS Always succeeds */ +/* */ +/* NOTES: */ +/* 1. The equations used are as follows: */ +/* */ +/* G = 10^(GaindB/20) - 1 */ +/* t0 = 2 * Pi * Fc / Fs */ +/* D = 1 if GaindB >= 0 */ +/* D = 1 / (1 + G) if GaindB < 0 */ +/* */ +/* b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0) */ +/* b1 = (0.5 - b2) * (1 - coserr(t0)) */ +/* a0 = (0.5 + b2) / 2 */ +/* */ +/* Where: */ +/* GaindB is the gain in dBs, range -15dB to +15dB */ +/* Fc is the centre frequency, DC to Fs/50 */ +/* Fs is the sample frequency, 8000 to 48000 in descrete steps */ +/* Q is the Q factor, 0.25 to 12 (represented by 25 to 1200) */ +/* */ +/* 2. The double precision coefficients are only used when fc is less than fs/85, so */ +/* the cosine of t0 is always close to 1.0. Instead of calculating the cosine */ +/* itself the difference from the value 1.0 is calculated, this can be done with */ +/* lower precision maths. */ +/* */ +/* 3. The value of the B2 coefficient is only calculated as a single precision value, */ +/* small errors in this value have a combined effect on the Q and Gain but not the */ +/* the frequency of the filter. */ +/* */ +/****************************************************************************************/ + + +LVEQNB_ReturnStatus_en LVEQNB_DoublePrecCoefs(LVM_UINT16 Fs, + LVEQNB_BandDef_t *pFilterDefinition, + PK_C32_Coefs_t *pCoefficients) +{ + + extern LVM_INT16 LVEQNB_GainTable[]; + extern LVM_INT16 LVEQNB_TwoPiOnFsTable[]; + extern LVM_INT16 LVEQNB_DTable[]; + extern LVM_INT16 LVEQNB_DPCosCoef[]; + + /* + * Get the filter definition + */ + LVM_INT16 Gain = pFilterDefinition->Gain; + LVM_UINT16 Frequency = pFilterDefinition->Frequency; + LVM_UINT16 QFactor = pFilterDefinition->QFactor; + + /* + * Intermediate variables and temporary values + */ + LVM_INT32 T0; + LVM_INT16 D; + LVM_INT32 A0; + LVM_INT32 B1; + LVM_INT32 B2; + LVM_INT32 Dt0; + LVM_INT32 B2_Den; + LVM_INT32 B2_Num; + LVM_INT32 CosErr; + LVM_INT16 coef; + LVM_INT32 factor; + LVM_INT16 t0; + LVM_INT16 i; + + /* + * Calculating the intermediate values + */ + T0 = (LVM_INT32)Frequency * LVEQNB_TwoPiOnFsTable[Fs]; /* T0 = 2 * Pi * Fc / Fs */ + if (Gain >= 0) + { + D = LVEQNB_DTable[15]; /* D = 1 if GaindB >= 0 */ + } + else + { + D = LVEQNB_DTable[Gain+15]; /* D = 1 / (1 + G) if GaindB < 0 */ + } + + /* + * Calculate the B2 coefficient + */ + Dt0 = D * (T0 >> 10); + B2_Den = ((LVM_INT32)QFactor << 19) + (Dt0 >> 2); + B2_Num = (Dt0 >> 3) - ((LVM_INT32)QFactor << 18); + B2 = (B2_Num / (B2_Den >> 16)) << 15; + + /* + * Calculate the cosine error by a polynomial expansion using the equation: + * + * CosErr += coef(n) * t0^n For n = 0 to 4 + */ + T0 = (T0 >> 6) * 0x7f53; /* Scale to 1.0 in 16-bit for range 0 to fs/50 */ + t0 = (LVM_INT16)(T0 >> 16); + factor = 0x7fff; /* Initialise to 1.0 for the a0 coefficient */ + CosErr = 0; /* Initialise the error to zero */ + for (i=1; i<5; i++) + { + coef = LVEQNB_DPCosCoef[i]; /* Get the nth coefficient */ + CosErr += (factor * coef) >> 5; /* The nth partial sum */ + factor = (factor * t0) >> 15; /* Calculate t0^n */ + } + CosErr = CosErr << (LVEQNB_DPCosCoef[0]); /* Correct the scaling */ + + /* + * Calculate the B1 and A0 coefficients + */ + B1 = (0x40000000 - B2); /* B1 = (0.5 - b2/2) */ + A0 = ((B1 >> 16) * (CosErr >> 10)) >> 6; /* Temporary storage for (0.5 - b2/2) * coserr(t0) */ + B1 -= A0; /* B1 = (0.5 - b2/2) * (1 - coserr(t0)) */ + A0 = (0x40000000 + B2) >> 1; /* A0 = (0.5 + b2) */ + + /* + * Write coeff into the data structure + */ + pCoefficients->A0 = A0; + pCoefficients->B1 = B1; + pCoefficients->B2 = B2; + pCoefficients->G = LVEQNB_GainTable[Gain+15]; + + return(LVEQNB_SUCCESS); + +} + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_SinglePrecCoefs */ +/* */ +/* DESCRIPTION: */ +/* Calculate single precision coefficients for a peaking filter */ +/* */ +/* PARAMETERS: */ +/* Fs Sampling frequency index */ +/* pFilterDefinition Pointer to the filter definition */ +/* pCoefficients Pointer to the coefficients */ +/* */ +/* RETURNS: */ +/* LVEQNB_SUCCESS Always succeeds */ +/* */ +/* NOTES: */ +/* 1. The equations used are as follows: */ +/* */ +/* G = 10^(GaindB/20) - 1 */ +/* t0 = 2 * Pi * Fc / Fs */ +/* D = 1 if GaindB >= 0 */ +/* D = 1 / (1 + G) if GaindB < 0 */ +/* */ +/* b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0) */ +/* b1 = (0.5 - b2) * cos(t0) */ +/* a0 = (0.5 + b2) / 2 */ +/* */ +/* Where: */ +/* GaindB is the gain in dBs, range -15dB to +15dB */ +/* Fc is the centre frequency, DC to Nyquist */ +/* Fs is the sample frequency, 8000 to 48000 in descrete steps */ +/* Q is the Q factor, 0.25 to 12 */ +/* */ +/****************************************************************************************/ + + +LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16 Fs, + LVEQNB_BandDef_t *pFilterDefinition, + PK_C16_Coefs_t *pCoefficients) +{ + + extern LVM_INT16 LVEQNB_GainTable[]; + extern LVM_INT16 LVEQNB_TwoPiOnFsTable[]; + extern LVM_INT16 LVEQNB_DTable[]; + extern LVM_INT16 LVEQNB_CosCoef[]; + + + /* + * Get the filter definition + */ + LVM_INT16 Gain = pFilterDefinition->Gain; + LVM_UINT16 Frequency = pFilterDefinition->Frequency; + LVM_UINT16 QFactor = pFilterDefinition->QFactor; + + + /* + * Intermediate variables and temporary values + */ + LVM_INT32 T0; + LVM_INT16 D; + LVM_INT32 A0; + LVM_INT32 B1; + LVM_INT32 B2; + LVM_INT32 Dt0; + LVM_INT32 B2_Den; + LVM_INT32 B2_Num; + LVM_INT32 COS_T0; + LVM_INT16 coef; + LVM_INT32 factor; + LVM_INT16 t0; + LVM_INT16 i; + + /* + * Calculating the intermediate values + */ + T0 = (LVM_INT32)Frequency * LVEQNB_TwoPiOnFsTable[Fs]; /* T0 = 2 * Pi * Fc / Fs */ + if (Gain >= 0) + { + D = LVEQNB_DTable[15]; /* D = 1 if GaindB >= 0 */ + } + else + { + D = LVEQNB_DTable[Gain+15]; /* D = 1 / (1 + G) if GaindB < 0 */ + } + + /* + * Calculate the B2 coefficient + */ + Dt0 = D * (T0 >> 10); + B2_Den = ((LVM_INT32)QFactor << 19) + (Dt0 >> 2); + B2_Num = (Dt0 >> 3) - ((LVM_INT32)QFactor << 18); + B2 = (B2_Num / (B2_Den >> 16)) << 15; + + /* + * Calculate the cosine by a polynomial expansion using the equation: + * + * Cos += coef(n) * t0^n For n = 0 to 6 + */ + T0 = (T0 >> 10) * 20859; /* Scale to 1.0 in 16-bit for range 0 to fs/2 */ + t0 = (LVM_INT16)(T0 >> 16); + factor = 0x7fff; /* Initialise to 1.0 for the a0 coefficient */ + COS_T0 = 0; /* Initialise the error to zero */ + for (i=1; i<7; i++) + { + coef = LVEQNB_CosCoef[i]; /* Get the nth coefficient */ + COS_T0 += (factor * coef) >> 5; /* The nth partial sum */ + factor = (factor * t0) >> 15; /* Calculate t0^n */ + } + COS_T0 = COS_T0 << (LVEQNB_CosCoef[0]+6); /* Correct the scaling */ + + + B1 = ((0x40000000 - B2) >> 16) * (COS_T0 >> 16); /* B1 = (0.5 - b2/2) * cos(t0) */ + A0 = (0x40000000 + B2) >> 1; /* A0 = (0.5 + b2/2) */ + + /* + * Write coeff into the data structure + */ + pCoefficients->A0 = (LVM_INT16)(A0>>16); + pCoefficients->B1 = (LVM_INT16)(B1>>15); + pCoefficients->B2 = (LVM_INT16)(B2>>16); + pCoefficients->G = LVEQNB_GainTable[Gain+15]; + + + return(LVEQNB_SUCCESS); + +} diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h new file mode 100755 index 0000000..87d7145 --- /dev/null +++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2004-2010 NXP Software + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef __LVEQNB_COEFFS_H__ +#define __LVEQNB_COEFFS_H__ + + +/************************************************************************************/ +/* */ +/* Gain table for (10^(Gain/20) - 1) */ +/* */ +/************************************************************************************/ + +#define LVEQNB_GAINSHIFT 11 /* As a power of 2 */ +#define LVEQNB_Gain_Neg15_dB -1684 /* Floating point value -0.822172 */ +#define LVEQNB_Gain_Neg14_dB -1639 /* Floating point value -0.800474 */ +#define LVEQNB_Gain_Neg13_dB -1590 /* Floating point value -0.776128 */ +#define LVEQNB_Gain_Neg12_dB -1534 /* Floating point value -0.748811 */ +#define LVEQNB_Gain_Neg11_dB -1471 /* Floating point value -0.718162 */ +#define LVEQNB_Gain_Neg10_dB -1400 /* Floating point value -0.683772 */ +#define LVEQNB_Gain_Neg9_dB -1321 /* Floating point value -0.645187 */ +#define LVEQNB_Gain_Neg8_dB -1233 /* Floating point value -0.601893 */ +#define LVEQNB_Gain_Neg7_dB -1133 /* Floating point value -0.553316 */ +#define LVEQNB_Gain_Neg6_dB -1022 /* Floating point value -0.498813 */ +#define LVEQNB_Gain_Neg5_dB -896 /* Floating point value -0.437659 */ +#define LVEQNB_Gain_Neg4_dB -756 /* Floating point value -0.369043 */ +#define LVEQNB_Gain_Neg3_dB -598 /* Floating point value -0.292054 */ +#define LVEQNB_Gain_Neg2_dB -421 /* Floating point value -0.205672 */ +#define LVEQNB_Gain_Neg1_dB -223 /* Floating point value -0.108749 */ +#define LVEQNB_Gain_0_dB 0 /* Floating point value 0.000000 */ +#define LVEQNB_Gain_1_dB 250 /* Floating point value 0.122018 */ +#define LVEQNB_Gain_2_dB 530 /* Floating point value 0.258925 */ +#define LVEQNB_Gain_3_dB 845 /* Floating point value 0.412538 */ +#define LVEQNB_Gain_4_dB 1198 /* Floating point value 0.584893 */ +#define LVEQNB_Gain_5_dB 1594 /* Floating point value 0.778279 */ +#define LVEQNB_Gain_6_dB 2038 /* Floating point value 0.995262 */ +#define LVEQNB_Gain_7_dB 2537 /* Floating point value 1.238721 */ +#define LVEQNB_Gain_8_dB 3096 /* Floating point value 1.511886 */ +#define LVEQNB_Gain_9_dB 3724 /* Floating point value 1.818383 */ +#define LVEQNB_Gain_10_dB 4428 /* Floating point value 2.162278 */ +#define LVEQNB_Gain_11_dB 5219 /* Floating point value 2.548134 */ +#define LVEQNB_Gain_12_dB 6105 /* Floating point value 2.981072 */ +#define LVEQNB_Gain_13_dB 7100 /* Floating point value 3.466836 */ +#define LVEQNB_Gain_14_dB 8216 /* Floating point value 4.011872 */ +#define LVEQNB_Gain_15_dB 9469 /* Floating point value 4.623413 */ + + +/************************************************************************************/ +/* */ +/* Frequency table for 2*Pi/Fs */ +/* */ +/************************************************************************************/ + +#define LVEQNB_FREQSHIFT 25 /* As a power of 2 */ +#define LVEQNB_2PiOn_8000 26354 /* Floating point value 0.000785 */ +#define LVEQNB_2PiOn_11025 19123 /* Floating point value 0.000570 */ +#define LVEQNB_2PiOn_12000 17569 /* Floating point value 0.000524 */ +#define LVEQNB_2PiOn_16000 13177 /* Floating point value 0.000393 */ +#define LVEQNB_2PiOn_22050 9561 /* Floating point value 0.000285 */ +#define LVEQNB_2PiOn_24000 8785 /* Floating point value 0.000262 */ +#define LVEQNB_2PiOn_32000 6588 /* Floating point value 0.000196 */ +#define LVEQNB_2PiOn_44100 4781 /* Floating point value 0.000142 */ +#define LVEQNB_2PiOn_48000 4392 /* Floating point value 0.000131 */ + + +/************************************************************************************/ +/* */ +/* 50D table for 50 / ( 1 + Gain ) */ +/* */ +/************************************************************************************/ + +#define LVEQNB_100DSHIFT 5 /* As a power of 2 */ +#define LVEQNB_100D_Neg15_dB 17995 /* Floating point value 5.623413 */ +#define LVEQNB_100D_Neg14_dB 16038 /* Floating point value 5.011872 */ +#define LVEQNB_100D_Neg13_dB 14294 /* Floating point value 4.466836 */ +#define LVEQNB_100D_Neg12_dB 12739 /* Floating point value 3.981072 */ +#define LVEQNB_100D_Neg11_dB 11354 /* Floating point value 3.548134 */ +#define LVEQNB_100D_Neg10_dB 10119 /* Floating point value 3.162278 */ +#define LVEQNB_100D_Neg9_dB 9019 /* Floating point value 2.818383 */ +#define LVEQNB_100D_Neg8_dB 8038 /* Floating point value 2.511886 */ +#define LVEQNB_100D_Neg7_dB 7164 /* Floating point value 2.238721 */ +#define LVEQNB_100D_Neg6_dB 6385 /* Floating point value 1.995262 */ +#define LVEQNB_100D_Neg5_dB 5690 /* Floating point value 1.778279 */ +#define LVEQNB_100D_Neg4_dB 5072 /* Floating point value 1.584893 */ +#define LVEQNB_100D_Neg3_dB 4520 /* Floating point value 1.412538 */ +#define LVEQNB_100D_Neg2_dB 4029 /* Floating point value 1.258925 */ +#define LVEQNB_100D_Neg1_dB 3590 /* Floating point value 1.122018 */ +#define LVEQNB_100D_0_dB 3200 /* Floating point value 1.000000 */ + + +#endif diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c new file mode 100755 index 0000000..88f6fb0 --- /dev/null +++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c @@ -0,0 +1,501 @@ +/* + * Copyright (C) 2004-2010 NXP Software + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/********************************************************************************** + + $Author: nxp007753 $ + $Revision: 1223 $ + $Date: 2010-07-15 14:27:01 +0200 (Thu, 15 Jul 2010) $ + +***********************************************************************************/ + +/****************************************************************************************/ +/* */ +/* Includes */ +/* */ +/****************************************************************************************/ + +#include "LVEQNB.h" +#include "LVEQNB_Private.h" +#include "VectorArithmetic.h" +#include "BIQUAD.h" + + +/****************************************************************************************/ +/* */ +/* Defines */ +/* */ +/****************************************************************************************/ + +#define LOW_FREQ 298 /* 32768/110 for low test frequency */ +#define HIGH_FREQ 386 /* 32768/85 for high test frequency */ + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_GetParameters */ +/* */ +/* DESCRIPTION: */ +/* Request the N-Band equaliser parameters. The current parameter set is returned via */ +/* the parameter pointer. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* pParams Pointer to an empty parameter structure */ +/* */ +/* RETURNS: */ +/* LVEQNB_SUCCESS Succeeds */ +/* LVEQNB_NULLADDRESS Instance or pParams is NULL pointer */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVEQNB_Process function */ +/* */ +/****************************************************************************************/ + +LVEQNB_ReturnStatus_en LVEQNB_GetParameters(LVEQNB_Handle_t hInstance, + LVEQNB_Params_t *pParams) +{ + + LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance; + + /* + * Check for error conditions + */ + if((hInstance == LVM_NULL) || (pParams == LVM_NULL)) + { + return LVEQNB_NULLADDRESS; + } + + *pParams = pInstance->Params; + + return(LVEQNB_SUCCESS); +} + + +/************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_GetCapabilities */ +/* */ +/* DESCRIPTION: */ +/* Get the N-Band equaliser capabilities. The current capabilities are returned */ +/* via the pointer. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* pCapabilities Pointer to an empty capability structure */ +/* */ +/* RETURNS: */ +/* LVEQNB_Success Succeeds */ +/* LVEQNB_NULLADDRESS hInstance or pCapabilities is NULL */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVEQNB_Process function */ +/* */ +/************************************************************************************/ + +LVEQNB_ReturnStatus_en LVEQNB_GetCapabilities(LVEQNB_Handle_t hInstance, + LVEQNB_Capabilities_t *pCapabilities) +{ + + LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance; + + if((hInstance == LVM_NULL) || (pCapabilities == LVM_NULL)) + { + return LVEQNB_NULLADDRESS; + } + + *pCapabilities = pInstance->Capabilities; + + return(LVEQNB_SUCCESS); +} + + +/************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_SetFilters */ +/* */ +/* DESCRIPTION: */ +/* Sets the filter type based on the definition. */ +/* */ +/* PARAMETERS: */ +/* pInstance Pointer to the instance */ +/* pParams Initialisation parameters */ +/* */ +/* RETURNS: */ +/* void Nothing */ +/* */ +/* NOTES: */ +/* 1. To select the biquad type the follow rules are applied: */ +/* Double precision if (fc <= fs/110) */ +/* Double precision if (fs/110 < fc < fs/85) & (Q>3) */ +/* Single precision otherwise */ +/* */ +/************************************************************************************/ + +void LVEQNB_SetFilters(LVEQNB_Instance_t *pInstance, + LVEQNB_Params_t *pParams) +{ + + extern const LVM_UINT16 LVEQNB_SampleRateTab[]; /* Sample rate table */ + LVM_UINT16 i; /* Filter band index */ + LVM_UINT32 fs = (LVM_UINT32)LVEQNB_SampleRateTab[(LVM_UINT16)pParams->SampleRate]; /* Sample rate */ + LVM_UINT32 fc; /* Filter centre frequency */ + LVM_INT16 QFactor; /* Filter Q factor */ + + + pInstance->NBands = pParams->NBands; + + for (i=0; iNBands; i++) + { + /* + * Get the filter settings + */ + fc = (LVM_UINT32)pParams->pBandDefinition[i].Frequency; /* Get the band centre frequency */ + QFactor = (LVM_INT16)pParams->pBandDefinition[i].QFactor; /* Get the band Q factor */ + + + /* + * For each filter set the type of biquad required + */ + pInstance->pBiquadType[i] = LVEQNB_SinglePrecision; /* Default to single precision */ + if ((fc << 15) <= (LOW_FREQ * fs)) + { + /* + * fc <= fs/110 + */ + pInstance->pBiquadType[i] = LVEQNB_DoublePrecision; + } + else if (((fc << 15) <= (HIGH_FREQ * fs)) && (QFactor > 300)) + { + /* + * (fs/110 < fc < fs/85) & (Q>3) + */ + pInstance->pBiquadType[i] = LVEQNB_DoublePrecision; + } + + + /* + * Check for out of range frequencies + */ + if (fc > (fs >> 1)) + { + pInstance->pBiquadType[i] = LVEQNB_OutOfRange; + } + + + /* + * Copy the filter definition to persistant memory + */ + pInstance->pBandDefinitions[i] = pParams->pBandDefinition[i]; + + } +} + + +/************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_SetCoefficients */ +/* */ +/* DESCRIPTION: */ +/* Sets the filter coefficients. This uses the type to select single or double */ +/* precision coefficients. */ +/* */ +/* PARAMETERS: */ +/* pInstance Pointer to the instance */ +/* pParams Initialisation parameters */ +/* */ +/************************************************************************************/ + +void LVEQNB_SetCoefficients(LVEQNB_Instance_t *pInstance) +{ + + LVM_UINT16 i; /* Filter band index */ + LVEQNB_BiquadType_en BiquadType; /* Filter biquad type */ + + + /* + * Set the coefficients for each band by the init function + */ + for (i=0; iParams.NBands; i++) + { + + /* + * Check band type for correct initialisation method and recalculate the coefficients + */ + BiquadType = pInstance->pBiquadType[i]; + switch (BiquadType) + { + case LVEQNB_DoublePrecision: + { + PK_C32_Coefs_t Coefficients; + + /* + * Calculate the double precision coefficients + */ + LVEQNB_DoublePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate, + &pInstance->pBandDefinitions[i], + &Coefficients); + + /* + * Set the coefficients + */ + PK_2I_D32F32CllGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i], + &pInstance->pEQNB_Taps[i], + &Coefficients); + break; + } + + case LVEQNB_SinglePrecision: + { + PK_C16_Coefs_t Coefficients; + + /* + * Calculate the single precision coefficients + */ + LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate, + &pInstance->pBandDefinitions[i], + &Coefficients); + + /* + * Set the coefficients + */ + PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i], + &pInstance->pEQNB_Taps[i], + &Coefficients); + break; + } + default: + break; + } + } + +} + + +/************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_ClearFilterHistory */ +/* */ +/* DESCRIPTION: */ +/* Clears the filter data history */ +/* */ +/* PARAMETERS: */ +/* pInstance Pointer to the instance */ +/* */ +/************************************************************************************/ + +void LVEQNB_ClearFilterHistory(LVEQNB_Instance_t *pInstance) +{ + LVM_INT16 *pTapAddress; + LVM_INT16 NumTaps; + + + pTapAddress = (LVM_INT16 *)pInstance->pEQNB_Taps; + NumTaps = (LVM_INT16)((pInstance->Capabilities.MaxBands * sizeof(Biquad_2I_Order2_Taps_t))/sizeof(LVM_INT16)); + + if (NumTaps != 0) + { + LoadConst_16(0, /* Clear the history, value 0 */ + pTapAddress, /* Destination */ + NumTaps); /* Number of words */ + } +} + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_Control */ +/* */ +/* DESCRIPTION: */ +/* Sets or changes the LifeVibes module parameters. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* pParams Pointer to a parameter structure */ +/* */ +/* RETURNS: */ +/* LVEQNB_Success Always succeeds */ +/* LVEQNB_NULLADDRESS Instance or pParams is NULL pointer */ +/* LVEQNB_NULLADDRESS NULL address for the equaliser filter definitions and the */ +/* number of bands is non-zero */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVEQNB_Process function */ +/* */ +/****************************************************************************************/ + +LVEQNB_ReturnStatus_en LVEQNB_Control(LVEQNB_Handle_t hInstance, + LVEQNB_Params_t *pParams) +{ + + LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance; + LVM_INT16 bChange = LVM_FALSE; + LVM_INT16 i = 0; + LVEQNB_Mode_en OperatingModeSave ; + + /* + * Check for error conditions + */ + if((hInstance == LVM_NULL) || (pParams == LVM_NULL)) + { + return LVEQNB_NULLADDRESS; + } + + if((pParams->NBands !=0) && (pParams->pBandDefinition==LVM_NULL)) + { + return LVEQNB_NULLADDRESS; + } + + OperatingModeSave = pInstance->Params.OperatingMode; + + /* Set the alpha factor of the mixer */ + if (pParams->SampleRate != pInstance->Params.SampleRate) + { + LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2); + LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2); + } + + + if( (pInstance->Params.NBands != pParams->NBands ) || + (pInstance->Params.OperatingMode != pParams->OperatingMode ) || + (pInstance->Params.pBandDefinition != pParams->pBandDefinition ) || + (pInstance->Params.SampleRate != pParams->SampleRate ) || + (pInstance->Params.SourceFormat != pParams->SourceFormat )) + { + + bChange = LVM_TRUE; + } + else + { + for(i = 0; i < pParams->NBands; i++) + { + + if((pInstance->pBandDefinitions[i].Frequency != pParams->pBandDefinition[i].Frequency )|| + (pInstance->pBandDefinitions[i].Gain != pParams->pBandDefinition[i].Gain )|| + (pInstance->pBandDefinitions[i].QFactor != pParams->pBandDefinition[i].QFactor )) + { + + bChange = LVM_TRUE; + } + } + } + + + if(bChange){ + + /* + * If the sample rate has changed clear the history + */ + if (pInstance->Params.SampleRate != pParams->SampleRate) + { + LVEQNB_ClearFilterHistory(pInstance); /* Clear the history */ + } + + /* + * Update the instance parameters + */ + pInstance->Params = *pParams; + + + /* + * Reset the filters except if the algo is switched off + */ + if(pParams->OperatingMode != LVEQNB_BYPASS){ + /* + * Reset the filters as all parameters could have changed + */ + LVEQNB_SetFilters(pInstance, /* Instance pointer */ + pParams); /* New parameters */ + + /* + * Update the filters + */ + LVEQNB_SetCoefficients(pInstance); /* Instance pointer */ + } + + if(pParams->OperatingMode != OperatingModeSave) + { + if(pParams->OperatingMode == LVEQNB_ON) + { + LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],LVM_MAXINT_16); + LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],0); + + pInstance->BypassMixer.MixerStream[0].CallbackSet = 1; + pInstance->BypassMixer.MixerStream[1].CallbackSet = 1; + } + else + { + /* Stay on the ON operating mode until the transition is done */ + pInstance->Params.OperatingMode = LVEQNB_ON; + + LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],0); + LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],LVM_MAXINT_16); + pInstance->BypassMixer.MixerStream[0].CallbackSet = 1; + pInstance->BypassMixer.MixerStream[1].CallbackSet = 1; + } + LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2); + LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2); + + pInstance->bInOperatingModeTransition = LVM_TRUE; + } + + } + return(LVEQNB_SUCCESS); +} + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_BypassMixerCallBack */ +/* */ +/* DESCRIPTION: */ +/* CallBack function of the mixer */ +/* transition */ +/* */ +/****************************************************************************************/ +LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance, + void *pGeneralPurpose, + LVM_INT16 CallbackParam) +{ + LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance; + LVM_Callback CallBack = pInstance->Capabilities.CallBack; + + (void) pGeneralPurpose; + + /* + * Send an ALGOFF event if the ON->OFF switch transition is finished + */ + if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0x00000000) && + (CallbackParam == 0)){ + pInstance->Params.OperatingMode = LVEQNB_BYPASS; + if (CallBack != LVM_NULL){ + CallBack(pInstance->Capabilities.pBundleInstance, LVM_NULL, ALGORITHM_EQNB_ID|LVEQNB_EVENT_ALGOFF); + } + } + + /* + * Exit transition state + */ + pInstance->bInOperatingModeTransition = LVM_FALSE; + + return 1; +} + + + + + + diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c new file mode 100755 index 0000000..a29fe05 --- /dev/null +++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2004-2010 NXP Software + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/********************************************************************************** + + $Author: beq07716 $ + $Revision: 1005 $ + $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $ + +***********************************************************************************/ + + +/****************************************************************************************/ +/* */ +/* Includes */ +/* */ +/****************************************************************************************/ + +#include "LVEQNB.h" +#include "LVEQNB_Private.h" +#include "InstAlloc.h" + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_Memory */ +/* */ +/* DESCRIPTION: */ +/* This function is used for memory allocation and free. It can be called in */ +/* two ways: */ +/* */ +/* hInstance = NULL Returns the memory requirements */ +/* hInstance = Instance handle Returns the memory requirements and */ +/* allocated base addresses for the instance */ +/* */ +/* When this function is called for memory allocation (hInstance=NULL) the memory */ +/* base address pointers are NULL on return. */ +/* */ +/* When the function is called for free (hInstance = Instance Handle) the memory */ +/* table returns the allocated memory and base addresses used during initialisation. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance Handle */ +/* pMemoryTable Pointer to an empty memory definition table */ +/* pCapabilities Pointer to the instance capabilities */ +/* */ +/* RETURNS: */ +/* LVEQNB_SUCCESS Succeeded */ +/* LVEQNB_NULLADDRESS When any of pMemoryTable and pCapabilities is NULL address */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVEQNB_Process function */ +/* */ +/****************************************************************************************/ + +LVEQNB_ReturnStatus_en LVEQNB_Memory(LVEQNB_Handle_t hInstance, + LVEQNB_MemTab_t *pMemoryTable, + LVEQNB_Capabilities_t *pCapabilities) +{ + + INST_ALLOC AllocMem; + LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance; + + + if((pMemoryTable == LVM_NULL)|| (pCapabilities == LVM_NULL)) + { + return LVEQNB_NULLADDRESS; + } + + + /* + * Fill in the memory table + */ + if (hInstance == LVM_NULL) + { + /* + * Instance memory + */ + InstAlloc_Init(&AllocMem, + LVM_NULL); + InstAlloc_AddMember(&AllocMem, /* Low pass filter */ + sizeof(LVEQNB_Instance_t)); + pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Size = InstAlloc_GetTotal(&AllocMem); + pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Alignment = LVEQNB_INSTANCE_ALIGN; + pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Type = LVEQNB_PERSISTENT; + pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL; + + + /* + * Persistant data memory + */ + InstAlloc_Init(&AllocMem, + LVM_NULL); + InstAlloc_AddMember(&AllocMem, /* Low pass filter */ + sizeof(Biquad_2I_Order2_Taps_t)); + InstAlloc_AddMember(&AllocMem, /* High pass filter */ + sizeof(Biquad_2I_Order2_Taps_t)); + InstAlloc_AddMember(&AllocMem, + (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t))); /* Equaliser Biquad Taps */ + InstAlloc_AddMember(&AllocMem, + (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t))); /* Filter definitions */ + InstAlloc_AddMember(&AllocMem, + (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en))); /* Biquad types */ + pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Size = InstAlloc_GetTotal(&AllocMem); + pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Alignment = LVEQNB_DATA_ALIGN; + pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Type = LVEQNB_PERSISTENT_DATA; + pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL; + + /* + * Persistant coefficient memory + */ + InstAlloc_Init(&AllocMem, + LVM_NULL); + InstAlloc_AddMember(&AllocMem, /* Low pass filter */ + sizeof(Biquad_Instance_t)); + InstAlloc_AddMember(&AllocMem, /* High pass filter */ + sizeof(Biquad_Instance_t)); + InstAlloc_AddMember(&AllocMem, + pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */ + pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Size = InstAlloc_GetTotal(&AllocMem); + pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Alignment = LVEQNB_COEF_ALIGN; + pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Type = LVEQNB_PERSISTENT_COEF; + pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL; + + /* + * Scratch memory + */ + InstAlloc_Init(&AllocMem, + LVM_NULL); + InstAlloc_AddMember(&AllocMem, /* Low pass filter */ + LVEQNB_SCRATCHBUFFERS*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize); + pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Size = InstAlloc_GetTotal(&AllocMem); + pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Alignment = LVEQNB_SCRATCH_ALIGN; + pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Type = LVEQNB_SCRATCH; + pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL; + } + else + { + /* Read back memory allocation table */ + *pMemoryTable = pInstance->MemoryTable; + } + + return(LVEQNB_SUCCESS); +} + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_Init */ +/* */ +/* DESCRIPTION: */ +/* Create and initialisation function for the N-Band equaliser module */ +/* */ +/* This function can be used to create an algorithm instance by calling with */ +/* hInstance set to NULL. In this case the algorithm returns the new instance */ +/* handle. */ +/* */ +/* This function can be used to force a full re-initialisation of the algorithm */ +/* by calling with hInstance = Instance Handle. In this case the memory table */ +/* should be correct for the instance, this can be ensured by calling the function */ +/* DBE_Memory before calling this function. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* pMemoryTable Pointer to the memory definition table */ +/* pCapabilities Pointer to the instance capabilities */ +/* */ +/* RETURNS: */ +/* LVEQNB_SUCCESS Initialisation succeeded */ +/* LVEQNB_NULLADDRESS When pCapabilities or pMemoryTableis or phInstance are NULL */ +/* LVEQNB_NULLADDRESS One or more of the memory regions has a NULL base address */ +/* pointer for a memory region with a non-zero size. */ +/* */ +/* NOTES: */ +/* 1. The instance handle is the pointer to the base address of the first memory */ +/* region. */ +/* 2. This function must not be interrupted by the LVEQNB_Process function */ +/* */ +/****************************************************************************************/ + +LVEQNB_ReturnStatus_en LVEQNB_Init(LVEQNB_Handle_t *phInstance, + LVEQNB_MemTab_t *pMemoryTable, + LVEQNB_Capabilities_t *pCapabilities) +{ + + LVEQNB_Instance_t *pInstance; + LVM_UINT32 MemSize; + INST_ALLOC AllocMem; + LVM_INT32 i; + + /* + * Check for NULL pointers + */ + if((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pCapabilities == LVM_NULL)) + { + return LVEQNB_NULLADDRESS; + } + + /* + * Check the memory table for NULL pointers + */ + for (i = 0; i < LVEQNB_NR_MEMORY_REGIONS; i++) + { + if (pMemoryTable->Region[i].Size!=0) + { + if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL) + { + return(LVEQNB_NULLADDRESS); + } + } + } + + /* + * Set the instance handle if not already initialised + */ + + InstAlloc_Init(&AllocMem, pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress); + + if (*phInstance == LVM_NULL) + { + *phInstance = InstAlloc_AddMember(&AllocMem, sizeof(LVEQNB_Instance_t)); + } + pInstance =(LVEQNB_Instance_t *)*phInstance; + + + + /* + * Save the memory table in the instance structure + */ + pInstance->Capabilities = *pCapabilities; + + + /* + * Save the memory table in the instance structure and + * set the structure pointers + */ + pInstance->MemoryTable = *pMemoryTable; + + /* + * Allocate coefficient memory + */ + InstAlloc_Init(&AllocMem, + pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress); + + pInstance->pEQNB_FilterState = InstAlloc_AddMember(&AllocMem, + pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */ + + + + /* + * Allocate data memory + */ + InstAlloc_Init(&AllocMem, + pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress); + + MemSize = (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t)); + pInstance->pEQNB_Taps = (Biquad_2I_Order2_Taps_t *)InstAlloc_AddMember(&AllocMem, + MemSize); + MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t)); + pInstance->pBandDefinitions = (LVEQNB_BandDef_t *)InstAlloc_AddMember(&AllocMem, + MemSize); + MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en)); + pInstance->pBiquadType = (LVEQNB_BiquadType_en *)InstAlloc_AddMember(&AllocMem, + MemSize); + + + /* + * Internally map, structure and allign scratch memory + */ + InstAlloc_Init(&AllocMem, + pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress); + + pInstance->pFastTemporary = (LVM_INT16 *)InstAlloc_AddMember(&AllocMem, + sizeof(LVM_INT16)); + + /* + * Update the instance parameters + */ + pInstance->Params.NBands = 0; + pInstance->Params.OperatingMode = LVEQNB_BYPASS; + pInstance->Params.pBandDefinition = LVM_NULL; + pInstance->Params.SampleRate = LVEQNB_FS_8000; + pInstance->Params.SourceFormat = LVEQNB_STEREO; + + /* + * Initialise the filters + */ + LVEQNB_SetFilters(pInstance, /* Set the filter types */ + &pInstance->Params); + + LVEQNB_SetCoefficients(pInstance); /* Set the filter coefficients */ + + LVEQNB_ClearFilterHistory(pInstance); /* Clear the filter history */ + + /* + * Initialise the bypass variables + */ + pInstance->BypassMixer.MixerStream[0].CallbackSet = 0; + pInstance->BypassMixer.MixerStream[0].CallbackParam = 0; + pInstance->BypassMixer.MixerStream[0].pCallbackHandle = (void*)pInstance; + pInstance->BypassMixer.MixerStream[0].pCallBack = LVEQNB_BypassMixerCallBack; + LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[0],0,0); + LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],0,LVM_FS_8000,2); + + pInstance->BypassMixer.MixerStream[1].CallbackSet = 1; + pInstance->BypassMixer.MixerStream[1].CallbackParam = 0; + pInstance->BypassMixer.MixerStream[1].pCallbackHandle = LVM_NULL; + pInstance->BypassMixer.MixerStream[1].pCallBack = LVM_NULL; + LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[1],0,LVM_MAXINT_16); + LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],0,LVM_FS_8000,2); + + pInstance->bInOperatingModeTransition = LVM_FALSE; + + return(LVEQNB_SUCCESS); +} + diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h new file mode 100755 index 0000000..0ae84af --- /dev/null +++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2004-2010 NXP Software + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/********************************************************************************** + + $Author: beq07716 $ + $Revision: 1005 $ + $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $ + +***********************************************************************************/ + +#ifndef __LVEQNB_PRIVATE_H__ +#define __LVEQNB_PRIVATE_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/****************************************************************************************/ +/* */ +/* Includes */ +/* */ +/****************************************************************************************/ + +#include "LVEQNB.h" /* Calling or Application layer definitions */ +#include "BIQUAD.h" +#include "LVC_Mixer.h" + +/****************************************************************************************/ +/* */ +/* Defines */ +/* */ +/****************************************************************************************/ + +/* General */ +#define LVEQNB_INVALID 0xFFFF /* Invalid init parameter */ + +/* Memory */ +#define LVEQNB_INSTANCE_ALIGN 4 /* 32-bit alignment for instance structures */ +#define LVEQNB_DATA_ALIGN 4 /* 32-bit alignment for structures */ +#define LVEQNB_COEF_ALIGN 4 /* 32-bit alignment for long words */ +#define LVEQNB_SCRATCHBUFFERS 4 /* Number of buffers required for inplace processing */ +#define LVEQNB_SCRATCH_ALIGN 4 /* 32-bit alignment for long data */ + +#define LVEQNB_BYPASS_MIXER_TC 100 /* Bypass Mixer TC */ + +/****************************************************************************************/ +/* */ +/* Types */ +/* */ +/****************************************************************************************/ + +/* Filter biquad types */ +typedef enum +{ + LVEQNB_SinglePrecision = 0, + LVEQNB_DoublePrecision = 1, + LVEQNB_OutOfRange = 2, + LVEQNB_BIQUADTYPE_MAX = LVM_MAXINT_32 +} LVEQNB_BiquadType_en; + + +/****************************************************************************************/ +/* */ +/* Structures */ +/* */ +/****************************************************************************************/ + + + +/* Instance structure */ +typedef struct +{ + /* Public parameters */ + LVEQNB_MemTab_t MemoryTable; /* Instance memory allocation table */ + LVEQNB_Params_t Params; /* Instance parameters */ + LVEQNB_Capabilities_t Capabilities; /* Instance capabilities */ + + /* Aligned memory pointers */ + LVM_INT16 *pFastTemporary; /* Fast temporary data base address */ + + /* Process variables */ + Biquad_2I_Order2_Taps_t *pEQNB_Taps; /* Equaliser Taps */ + Biquad_Instance_t *pEQNB_FilterState; /* State for each filter band */ + + /* Filter definitions and call back */ + LVM_UINT16 NBands; /* Number of bands */ + LVEQNB_BandDef_t *pBandDefinitions; /* Filter band definitions */ + LVEQNB_BiquadType_en *pBiquadType; /* Filter biquad types */ + + /* Bypass variable */ + LVMixer3_2St_st BypassMixer; /* Bypass mixer used in transitions */ + LVM_INT16 bInOperatingModeTransition; /* Operating mode transition flag */ + +} LVEQNB_Instance_t; + + +/****************************************************************************************/ +/* */ +/* Function prototypes */ +/* */ +/****************************************************************************************/ + +void LVEQNB_SetFilters(LVEQNB_Instance_t *pInstance, + LVEQNB_Params_t *pParams); + +void LVEQNB_SetCoefficients(LVEQNB_Instance_t *pInstance); + +void LVEQNB_ClearFilterHistory(LVEQNB_Instance_t *pInstance); + +LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16 Fs, + LVEQNB_BandDef_t *pFilterDefinition, + PK_C16_Coefs_t *pCoefficients); + +LVEQNB_ReturnStatus_en LVEQNB_DoublePrecCoefs(LVM_UINT16 Fs, + LVEQNB_BandDef_t *pFilterDefinition, + PK_C32_Coefs_t *pCoefficients); + +LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance, void *pGeneralPurpose, LVM_INT16 CallbackParam); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __LVEQNB_PRIVATE_H__ */ + diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c new file mode 100755 index 0000000..e29e881 --- /dev/null +++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2004-2010 NXP Software + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/********************************************************************************** + + $Author: beq07716 $ + $Revision: 1005 $ + $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $ + +***********************************************************************************/ + +/****************************************************************************************/ +/* */ +/* Includes */ +/* */ +/****************************************************************************************/ + +#include "LVEQNB.h" +#include "LVEQNB_Private.h" +#include "VectorArithmetic.h" +#include "BIQUAD.h" + + +/****************************************************************************************/ +/* */ +/* Defines */ +/* */ +/****************************************************************************************/ + +#define SHIFT 13 + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_Process */ +/* */ +/* DESCRIPTION: */ +/* Process function for the N-Band Equaliser module. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* pInData Pointer to the input data */ +/* pOutData Pointer to the output data */ +/* NumSamples Number of samples in the input buffer */ +/* */ +/* RETURNS: */ +/* LVEQNB_SUCCESS Succeeded */ +/* LVEQNB_NULLADDRESS When hInstance, pInData or pOutData are NULL */ +/* LVEQNB_ALIGNMENTERROR When pInData or pOutData are not 32-bit aligned */ +/* LVEQNB_TOOMANYSAMPLES NumSamples was larger than the maximum block size */ +/* */ +/* NOTES: */ +/* */ +/****************************************************************************************/ + +LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t hInstance, + const LVM_INT16 *pInData, + LVM_INT16 *pOutData, + LVM_UINT16 NumSamples) +{ + + LVM_UINT16 i; + Biquad_Instance_t *pBiquad; + LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance; + LVM_INT32 *pScratch; + + + /* Check for NULL pointers */ + if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL)) + { + return LVEQNB_NULLADDRESS; + } + + /* Check if the input and output data buffers are 32-bit aligned */ + if ((((LVM_INT32)pInData % 4) != 0) || (((LVM_INT32)pOutData % 4) != 0)) + { + return LVEQNB_ALIGNMENTERROR; + } + + pScratch = (LVM_INT32 *)pInstance->pFastTemporary; + + /* + * Check the number of samples is not too large + */ + if (NumSamples > pInstance->Capabilities.MaxBlockSize) + { + return(LVEQNB_TOOMANYSAMPLES); + } + + if (pInstance->Params.OperatingMode == LVEQNB_ON) + { + /* + * Convert from 16-bit to 32-bit + */ + Int16LShiftToInt32_16x32((LVM_INT16 *)pInData, /* Source */ + pScratch, /* Destination */ + (LVM_INT16)(2*NumSamples), /* Left and Right */ + SHIFT); /* Scaling shift */ + + /* + * For each section execte the filter unless the gain is 0dB + */ + if (pInstance->NBands != 0) + { + for (i=0; iNBands; i++) + { + /* + * Check if band is non-zero dB gain + */ + if (pInstance->pBandDefinitions[i].Gain != 0) + { + /* + * Get the address of the biquad instance + */ + pBiquad = &pInstance->pEQNB_FilterState[i]; + + + /* + * Select single or double precision as required + */ + switch (pInstance->pBiquadType[i]) + { + case LVEQNB_SinglePrecision: + { + PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad, + (LVM_INT32 *)pScratch, + (LVM_INT32 *)pScratch, + (LVM_INT16)NumSamples); + break; + } + + case LVEQNB_DoublePrecision: + { + PK_2I_D32F32C30G11_TRC_WRA_01(pBiquad, + (LVM_INT32 *)pScratch, + (LVM_INT32 *)pScratch, + (LVM_INT16)NumSamples); + break; + } + default: + break; + } + } + } + } + + + if(pInstance->bInOperatingModeTransition == LVM_TRUE){ + /* + * Convert from 32-bit to 16- bit and saturate + */ + Int32RShiftToInt16_Sat_32x16(pScratch, /* Source */ + (LVM_INT16 *)pScratch, /* Destination */ + (LVM_INT16)(2*NumSamples), /* Left and Right */ + SHIFT); /* Scaling shift */ + + LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer, + (LVM_INT16 *)pScratch, + (LVM_INT16 *)pInData, + (LVM_INT16 *)pScratch, + (LVM_INT16)(2*NumSamples)); + + Copy_16((LVM_INT16*)pScratch, /* Source */ + pOutData, /* Destination */ + (LVM_INT16)(2*NumSamples)); /* Left and Right samples */ + } + else{ + + /* + * Convert from 32-bit to 16- bit and saturate + */ + Int32RShiftToInt16_Sat_32x16(pScratch, /* Source */ + pOutData, /* Destination */ + (LVM_INT16 )(2*NumSamples), /* Left and Right */ + SHIFT); /* Scaling shift */ + } + } + else + { + /* + * Mode is OFF so copy the data if necessary + */ + if (pInData != pOutData) + { + Copy_16(pInData, /* Source */ + pOutData, /* Destination */ + (LVM_INT16)(2*NumSamples)); /* Left and Right samples */ + } + } + + + + return(LVEQNB_SUCCESS); + +} diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c new file mode 100755 index 0000000..33c07da --- /dev/null +++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2004-2010 NXP Software + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/************************************************************************************ + + $Author: beq07716 $ + $Revision: 1005 $ + $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $ + +*************************************************************************************/ + + +/************************************************************************************/ +/* */ +/* Includes */ +/* */ +/************************************************************************************/ + +#include "LVEQNB.h" +#include "LVEQNB_Coeffs.h" + + +/************************************************************************************/ +/* */ +/* Sample rate table */ +/* */ +/************************************************************************************/ + +/* + * Sample rate table for converting between the enumerated type and the actual + * frequency + */ +const LVM_UINT16 LVEQNB_SampleRateTab[] = {8000, /* 8kS/s */ + 11025, + 12000, + 16000, + 22050, + 24000, + 32000, + 44100, + 48000}; /* 48kS/s */ + + +/************************************************************************************/ +/* */ +/* Coefficient calculation tables */ +/* */ +/************************************************************************************/ + +/* + * Table for 2 * Pi / Fs + */ +const LVM_INT16 LVEQNB_TwoPiOnFsTable[] = {LVEQNB_2PiOn_8000, /* 8kS/s */ + LVEQNB_2PiOn_11025, + LVEQNB_2PiOn_12000, + LVEQNB_2PiOn_16000, + LVEQNB_2PiOn_22050, + LVEQNB_2PiOn_24000, + LVEQNB_2PiOn_32000, + LVEQNB_2PiOn_44100, + LVEQNB_2PiOn_48000}; /* 48kS/s */ + +/* + * Gain table + */ +const LVM_INT16 LVEQNB_GainTable[] = {LVEQNB_Gain_Neg15_dB, /* -15dB gain */ + LVEQNB_Gain_Neg14_dB, + LVEQNB_Gain_Neg13_dB, + LVEQNB_Gain_Neg12_dB, + LVEQNB_Gain_Neg11_dB, + LVEQNB_Gain_Neg10_dB, + LVEQNB_Gain_Neg9_dB, + LVEQNB_Gain_Neg8_dB, + LVEQNB_Gain_Neg7_dB, + LVEQNB_Gain_Neg6_dB, + LVEQNB_Gain_Neg5_dB, + LVEQNB_Gain_Neg4_dB, + LVEQNB_Gain_Neg3_dB, + LVEQNB_Gain_Neg2_dB, + LVEQNB_Gain_Neg1_dB, + LVEQNB_Gain_0_dB, /* 0dB gain */ + LVEQNB_Gain_1_dB, + LVEQNB_Gain_2_dB, + LVEQNB_Gain_3_dB, + LVEQNB_Gain_4_dB, + LVEQNB_Gain_5_dB, + LVEQNB_Gain_6_dB, + LVEQNB_Gain_7_dB, + LVEQNB_Gain_8_dB, + LVEQNB_Gain_9_dB, + LVEQNB_Gain_10_dB, + LVEQNB_Gain_11_dB, + LVEQNB_Gain_12_dB, + LVEQNB_Gain_13_dB, + LVEQNB_Gain_14_dB, + LVEQNB_Gain_15_dB}; /* +15dB gain */ + + +/* + * D table for 100 / (Gain + 1) + */ +const LVM_INT16 LVEQNB_DTable[] = {LVEQNB_100D_Neg15_dB, /* -15dB gain */ + LVEQNB_100D_Neg14_dB, + LVEQNB_100D_Neg13_dB, + LVEQNB_100D_Neg12_dB, + LVEQNB_100D_Neg11_dB, + LVEQNB_100D_Neg10_dB, + LVEQNB_100D_Neg9_dB, + LVEQNB_100D_Neg8_dB, + LVEQNB_100D_Neg7_dB, + LVEQNB_100D_Neg6_dB, + LVEQNB_100D_Neg5_dB, + LVEQNB_100D_Neg4_dB, + LVEQNB_100D_Neg3_dB, + LVEQNB_100D_Neg2_dB, + LVEQNB_100D_Neg1_dB, + LVEQNB_100D_0_dB}; /* 0dB gain */ + + +/************************************************************************************/ +/* */ +/* Filter polynomial coefficients */ +/* */ +/************************************************************************************/ + +/* + * Coefficients for calculating the cosine with the equation: + * + * Cos(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5) + * + * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting + * a range of 0 to Pi. The output is in the range 32767 to -32768 representing the range + * +1.0 to -1.0 + */ +const LVM_INT16 LVEQNB_CosCoef[] = {3, /* Shifts */ + 4096, /* a0 */ + -36, /* a1 */ + -19725, /* a2 */ + -2671, /* a3 */ + 23730, /* a4 */ + -9490}; /* a5 */ + +/* + * Coefficients for calculating the cosine error with the equation: + * + * CosErr(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3) + * + * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting + * a range of 0 to Pi/25. The output is in the range 0 to 32767 representing the range + * 0.0 to 0.0078852986 + * + * This is used to give a double precision cosine over the range 0 to Pi/25 using the + * the equation: + * + * Cos(x) = 1.0 - CosErr(x) + */ +const LVM_INT16 LVEQNB_DPCosCoef[] = {1, /* Shifts */ + 0, /* a0 */ + -6, /* a1 */ + 16586, /* a2 */ + -44}; /* a3 */ + +/************************************************************************************/ +/* */ +/* Bypass mixer time constants (100ms) */ +/* */ +/************************************************************************************/ + +#define LVEQNB_MIX_TC_Fs8000 32580 /* Floating point value 0.994262695 */ +#define LVEQNB_MIX_TC_Fs11025 32632 /* Floating point value 0.995849609 */ +#define LVEQNB_MIX_TC_Fs12000 32643 /* Floating point value 0.996185303 */ +#define LVEQNB_MIX_TC_Fs16000 32674 /* Floating point value 0.997131348 */ +#define LVEQNB_MIX_TC_Fs22050 32700 /* Floating point value 0.997924805 */ +#define LVEQNB_MIX_TC_Fs24000 32705 /* Floating point value 0.998077393 */ +#define LVEQNB_MIX_TC_Fs32000 32721 /* Floating point value 0.998565674 */ +#define LVEQNB_MIX_TC_Fs44100 32734 /* Floating point value 0.998962402 */ +#define LVEQNB_MIX_TC_Fs48000 32737 /* Floating point value 0.999053955 */ + + +const LVM_INT16 LVEQNB_MixerTCTable[] = { + LVEQNB_MIX_TC_Fs8000, + LVEQNB_MIX_TC_Fs11025, + LVEQNB_MIX_TC_Fs12000, + LVEQNB_MIX_TC_Fs16000, + LVEQNB_MIX_TC_Fs22050, + LVEQNB_MIX_TC_Fs24000, + LVEQNB_MIX_TC_Fs32000, + LVEQNB_MIX_TC_Fs44100, + LVEQNB_MIX_TC_Fs48000}; -- cgit v1.1