LVDBE_Process.c revision c59c6fd7f859b4010d788db89b8d4d76bbb70e57
12c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* 22c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Copyright (C) 2004-2010 NXP Software 32c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Copyright (C) 2010 The Android Open Source Project 42c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * 52c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Licensed under the Apache License, Version 2.0 (the "License"); 62c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * you may not use this file except in compliance with the License. 72c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * You may obtain a copy of the License at 82c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * 92c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * http://www.apache.org/licenses/LICENSE-2.0 102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * 112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Unless required by applicable law or agreed to in writing, software 122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * distributed under the License is distributed on an "AS IS" BASIS, 132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * See the License for the specific language governing permissions and 152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * limitations under the License. 162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/**************************************************************************************** 192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 20c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent $Author: beq06068 $ 21c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent $Revision: 1400 $ 22c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent $Date: 2010-08-03 09:22:37 +0200 (Tue, 03 Aug 2010) $ 232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent*****************************************************************************************/ 252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/****************************************************************************************/ 272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* Includes */ 292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/****************************************************************************************/ 312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "LVDBE.h" 332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "LVDBE_Private.h" 342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "VectorArithmetic.h" 352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "AGC.h" 362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "LVDBE_Coeffs.h" /* Filter coefficients */ 372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/********************************************************************************************/ 402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* FUNCTION: LVDBE_Process */ 422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* DESCRIPTION: */ 442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* Process function for the Bass Enhancement module. */ 452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* Data can be processed in two formats, stereo or mono-in-stereo. Data in mono */ 472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* format is not supported, the calling routine must convert the mono stream to */ 482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* mono-in-stereo. */ 492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* ___________ */ 502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* ________ | | ________ */ 512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* | | _____ |------------------------->| | | | */ 522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* | 16-bit | | | | ________ | | | 32-bit | */ 532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* -+-->| to |-->| HPF |--| | | _____ | AGC Mixer |-->| to |--| */ 542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* | | 32-bit | |_____| | | Stereo | | | | | | 16-bit | | */ 552c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* | |________| |-->| to |-->| BPF |-->| | |________| 0 */ 562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* | | Mono | |_____| |___________| \--> */ 572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* | |________| */ 582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* | _________ 0 */ 592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* | | | | */ 602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* |----------------------------------------------------| Volume |-----------------| */ 612c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* | Control | */ 622c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* |_________| */ 632c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 642c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* PARAMETERS: */ 652c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* hInstance Instance handle */ 662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* pInData Pointer to the input data */ 672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* pOutData Pointer to the output data */ 682c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* NumSamples Number of samples in the input buffer */ 692c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 702c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* RETURNS: */ 712c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* LVDBE_SUCCESS Succeeded */ 722c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* LVDBE_TOOMANYSAMPLES NumSamples was larger than the maximum block size */ 732c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 742c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* NOTES: */ 752c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* 1. The input and output data must be 32-bit format. The input is scaled by a shift */ 762c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* when converting from 16-bit format, this scaling allows for internal headroom in the */ 772c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* bass enhancement algorithm. */ 782c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* 2. For a 16-bit implementation the converstion to 32-bit is removed and replaced with */ 792c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* the headroom loss. This headroom loss is compensated in the volume control so the */ 802c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* overall end to end gain is odB. */ 812c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* */ 822c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/********************************************************************************************/ 832c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 842c8e5cab3faa6d360e222b7a6c40a80083d021acEric LaurentLVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance, 852c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent const LVM_INT16 *pInData, 862c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT16 *pOutData, 872c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_UINT16 NumSamples) 882c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent{ 892c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 902c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance; 912c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT32 *pScratch = (LVM_INT32 *)pInstance->MemoryTable.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress; 92c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent LVM_INT32 *pMono; 932c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVM_INT16 *pInput = (LVM_INT16 *)pInData; 942c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 952c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 96c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent /* Scratch for Volume Control starts at offset of 2*NumSamples short values from pScratch */ 97c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent LVM_INT16 *pScratchVol = (LVM_INT16 *)(&pScratch[NumSamples]); 98c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent 99c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent /* Scratch for Mono path starts at offset of 2*NumSamples 32-bit values from pScratch */ 100c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent pMono = &pScratch[2*NumSamples]; 101c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent 1022c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1032c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Check the number of samples is not too large 1042c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 1052c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent if (NumSamples > pInstance->Capabilities.MaxBlockSize) 1062c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent { 1072c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent return(LVDBE_TOOMANYSAMPLES); 1082c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent } 1092c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Check if the algorithm is enabled 1122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 113c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent /* DBE path is processed when DBE is ON or during On/Off transitions */ 114c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent if ((pInstance->Params.OperatingMode == LVDBE_ON)|| 115c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[0]) 116c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[0]))) 1172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent { 1182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Convert 16-bit samples to 32-bit and scale 1212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * (For a 16-bit implementation apply headroom loss here) 1222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 123c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent Int16LShiftToInt32_16x32(pInput, /* Source 16-bit data */ 124c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent pScratch, /* Dest. 32-bit data */ 125c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVM_INT16)(2*NumSamples), /* Left and right */ 126c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent LVDBE_SCALESHIFT); /* Shift scale */ 1272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Apply the high pass filter if selected 1312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 1322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent if (pInstance->Params.HPFSelect == LVDBE_HPF_ON) 1332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent { 134c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance */ 135c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVM_INT32 *)pScratch, /* Source */ 136c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVM_INT32 *)pScratch, /* Destination */ 137c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVM_INT16)NumSamples); /* Number of samples */ 1382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent } 1392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Create the mono stream 1432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 144c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent From2iToMono_32(pScratch, /* Stereo source */ 145c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent pMono, /* Mono destination */ 146c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVM_INT16)NumSamples); /* Number of samples */ 1472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Apply the band pass filter 1512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 152c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance */ 153c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVM_INT32 *)pMono, /* Source */ 154c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVM_INT32 *)pMono, /* Destination */ 155c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVM_INT16)NumSamples); /* Number of samples */ 1562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Apply the AGC and mix 1602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 161c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer */ 162c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent pScratch, /* Stereo source */ 163c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent pMono, /* Mono band pass source */ 164c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent pScratch, /* Stereo destination */ 165c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent NumSamples); /* Number of samples */ 1662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1682c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Convert 32-bit samples to 16-bit and saturate 1692c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * (Not required for 16-bit implemenations) 1702c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 171c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent Int32RShiftToInt16_Sat_32x16(pScratch, /* Source 32-bit data */ 172c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVM_INT16 *)pScratch, /* Dest. 16-bit data */ 173c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVM_INT16)(2*NumSamples), /* Left and right */ 174c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent LVDBE_SCALESHIFT); /* Shift scale */ 1752c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1762c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent } 177c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent 178c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */ 179c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent if ((pInstance->Params.OperatingMode == LVDBE_OFF)|| 180c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[1]) 181c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[1]))) 1822c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent { 1832c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1842c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent /* 1852c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * The algorithm is disabled but volume management is required to compensate for 1862c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * headroom and volume (if enabled) 1872c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */ 1882c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume, 1892c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent pInData, 190c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent pScratchVol, 191c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVM_INT16)(2*NumSamples)); /* Left and right */ 1922c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 1932c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent } 1942c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 195c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent /* 196c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent * Mix DBE processed path and bypass volume path 197c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent */ 198c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer, 199c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVM_INT16 *) pScratch, 200c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent pScratchVol, 201c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent pOutData, 202c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent (LVM_INT16)(2*NumSamples)); 203c59c6fd7f859b4010d788db89b8d4d76bbb70e57Eric Laurent 2042c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent return(LVDBE_SUCCESS); 2052c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent} 2062c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 2072c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 2082c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 2092c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 2102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 2112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 2122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 2132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 2142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 2152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent 216