Il y avait des problèmes dans la libraire...
Dependencies: ST_FREQUENCY_DIVIDER ST_I2S USBDEVICE
Fork of X_NUCLEO_CCA02M1 by
Diff: Middlewares/OpenPDM2PCM/OpenPDMFilter.c
- Revision:
- 2:9f389fd8fb2e
- Child:
- 6:9b8bc842aeb3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Middlewares/OpenPDM2PCM/OpenPDMFilter.c Fri Apr 21 10:33:08 2017 +0200 @@ -0,0 +1,306 @@ +/** +****************************************************************************** +* @file OpenPDMFilter.h +* @author CL +* @version V1.0.0 +* @date 9-September-2015 +* @brief Open PDM audio software decoding Library. +* This Library is used to decode and reconstruct the audio signal +* produced by ST MEMS microphone (MP45Dxxx, MP34Dxxx). +****************************************************************************** +* @attention +* +* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2> +* +* Licensed under MCD-ST Image SW License Agreement V2, (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.st.com/software_license_agreement_image_v2 +* +* 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. +* +****************************************************************************** +*/ + + +/* Includes ------------------------------------------------------------------*/ + +#include "OpenPDMFilter.h" + + +/* Definitions ---------------------------------------------------------------*/ + +#define maxDecFactor 128 +#define maxVol 64 +#define FilterGain 16; +#define RoundDiv(a, b) (((a)>0)?(((a)+(b)/2)/(b)):(((a)-(b)/2)/(b))) +#define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N))) + + +/* Variables -----------------------------------------------------------------*/ + +uint32_t coef[5][maxDecFactor]; // Max sinc 5 with decimation 128 +uint32_t DivideConst = 0; +int64_t SubConst = 0; +uint32_t sinc1[maxDecFactor]; +uint32_t sinc2[maxDecFactor*2]; +uint32_t sinc3[maxDecFactor*3]; +uint32_t sinc4[maxDecFactor*4]; +uint32_t sinc[maxDecFactor*5]; +int64_t Z = 0; +uint16_t app; + + +/* Functions -----------------------------------------------------------------*/ + +int64_t filterTable(uint8_t *data, uint8_t table, TPDMFilter_InitStruct *Param); + +void convolve(uint32_t Signal[/* SignalLen */], unsigned short SignalLen, + uint32_t Kernel[/* KernelLen */], unsigned short KernelLen, + uint32_t Result[/* SignalLen + KernelLen - 1 */]); + +int64_t filterTable(uint8_t *data, uint8_t table, TPDMFilter_InitStruct *Param) +{ + uint16_t contatore = 0; + int64_t F = 0; + uint8_t c; + uint8_t i; + uint16_t internalBit = Param->bit[table]; + uint16_t internalBit_copy = internalBit; + uint16_t In_Mic = Param->In_MicChannels; + + c = data[0]; + for(i=0; i<Param->Decimation;i++) + { + if (c & (1<<((7-internalBit)))) + F += coef[table][i]; + internalBit++; + if(internalBit==8) + { + contatore+=In_Mic; + internalBit = 0; + c = data[contatore]; + } + } + Param->bit[table] = internalBit; + Param->byte = contatore; + + return F; +} + +void Open_PDM_Filter_Init(TPDMFilter_InitStruct *Param) +{ + uint16_t i,j; + int64_t sum = 0; + Param->Coef[0] = Param->Coef[1] = Param->Coef[2] = Param->Coef[3] = Param->Coef[4] = 0; + for(i=0;i<5;i++) + { + Param->bit[i]=0; + } + + for(i=0;i<Param->Decimation;i++) + { + sinc1[i]=1; + } + Param->OldOut = Param->OldIn = Param->OldZ = 0; + if(Param->LP_HZ!=0) + { + Param->LP_ALFA = (uint16_t)(Param->LP_HZ*256 / (Param->LP_HZ + Param->Fs/(2*3.14))); + }else + { + Param->LP_ALFA = 0; + } + + if(Param->HP_HZ!=0) + { + Param->HP_ALFA = (uint16_t)(Param->Fs*256 / (2*3.14*Param->HP_HZ + Param->Fs)); + }else + { + Param->HP_ALFA = 0; + } + + switch(Param->SincN) + { + case 1: + Param->FilterLen = Param->Decimation; + + for(i=0;i<Param->Decimation;i++) + { + coef[0][i]=1; + sum+= 1; + } + break; + case 2: + Param->FilterLen = Param->Decimation * 2; + + sinc[0] = 0; + + convolve(sinc1, Param->Decimation,sinc1,Param->Decimation,&sinc[1]); + + for(j=0;j<2;j++) + { + for(i=0;i<Param->Decimation;i++) + { + coef[j][i] = sinc[j*Param->Decimation+i]; + sum+= sinc[j*Param->Decimation+i]; + } + } + + break; + case 3: + Param->FilterLen = Param->Decimation * 3; + sinc[0] = 0; + sinc[Param->Decimation*3-1] = 0; + convolve(sinc1, Param->Decimation,sinc1,Param->Decimation,sinc2); + convolve(sinc2, Param->Decimation*2-1,sinc1,Param->Decimation,&sinc[1]); + for(j=0;j<3;j++) + { + for(i=0;i<Param->Decimation;i++) + { + coef[j][i] = sinc[j*Param->Decimation+i]; + sum+= sinc[j*Param->Decimation+i]; + } + } + break; + case 4: + Param->FilterLen = Param->Decimation * 4; + sinc[0] = 0; + sinc[1] = 0; + sinc[Param->Decimation*4-1] = 0; + convolve(sinc1, Param->Decimation,sinc1,Param->Decimation,sinc2); + convolve(sinc2, Param->Decimation*2-1,sinc1,Param->Decimation,sinc3); + convolve(sinc3, Param->Decimation*3-2,sinc1,Param->Decimation,&sinc[2]); + for(j=0;j<4;j++) + { + for(i=0;i<Param->Decimation;i++) + { + coef[j][i] = sinc[j*Param->Decimation+i]; + sum+= sinc[j*Param->Decimation+i]; + } + } + + break; + case 5: + Param->FilterLen = Param->Decimation*5; // Dec * 5 - 2 + sinc[0] = 0; + sinc[1] = 0; + sinc[Param->Decimation*5-2] = 0; + sinc[Param->Decimation*5-1] = 0; + + convolve(sinc1, Param->Decimation,sinc1,Param->Decimation,sinc2); + convolve(sinc2, Param->Decimation*2-1,sinc1,Param->Decimation,sinc3); + convolve(sinc3, Param->Decimation*3-2,sinc1,Param->Decimation,sinc4); + convolve(sinc4, Param->Decimation*4-3,sinc1,Param->Decimation,&sinc[2]); + + for(j=0;j<5;j++) + { + for(i=0;i<Param->Decimation;i++) + { + coef[j][i] = sinc[j*Param->Decimation+i]; + sum+= sinc[j*Param->Decimation+i]; + } + } + break; + } + SubConst = sum / 2; + DivideConst = SubConst*maxVol/32768/FilterGain; + if(DivideConst == 0 ) DivideConst = 1; +} + +void convolve(uint32_t Signal[/* SignalLen */], unsigned short SignalLen, + uint32_t Kernel[/* KernelLen */], unsigned short KernelLen, + uint32_t Result[/* SignalLen + KernelLen - 1 */]) +{ + uint16_t n; + for (n = 0; n < SignalLen + KernelLen - 1; n++) + { + unsigned short kmin, kmax, k; + + Result[n] = 0; + + kmin = (n >= KernelLen - 1) ? n - (KernelLen - 1) : 0; + kmax = (n < SignalLen - 1) ? n : SignalLen - 1; + + for (k = kmin; k <= kmax; k++) + { + Result[n] += Signal[k] * Kernel[n - k]; + } + } +} + +void Open_PDM_Filter(uint8_t* data, uint16_t* dataOut, uint16_t MicGain, TPDMFilter_InitStruct *Param) +{ + uint32_t i; + int64_t OldOut, OldIn, OldZ; + OldOut=Param->OldOut; + OldIn=Param->OldIn; + OldZ=Param->OldZ; + + for (i = 0; i < Param->Fs/1000; i++) + { + switch(Param->SincN) + { + case 1: + Z = filterTable(data,0, Param); + break; + case 2: + Z = Param->Coef[0] + filterTable(data,1, Param); + Param->Coef[0] = filterTable(data,0, Param); + break; + case 3: + Z = Param->Coef[1] + filterTable(data,2, Param); + Param->Coef[1] = Param->Coef[0] + filterTable(data,1, Param); + Param->Coef[0] = filterTable(data,0, Param); + break; + case 4: + Z = Param->Coef[2] + filterTable(data,3, Param); + Param->Coef[2] = Param->Coef[1] + filterTable(data,2, Param); + Param->Coef[1] = Param->Coef[0] + filterTable(data,1, Param); + Param->Coef[0] = filterTable(data,0, Param); + break; + case 5: + Z = Param->Coef[3] + filterTable(data,4, Param); + Param->Coef[3] = Param->Coef[2] + filterTable(data,3, Param); + Param->Coef[2] = Param->Coef[1] + filterTable(data,2, Param); + Param->Coef[1] = Param->Coef[0] + filterTable(data,1, Param); + Param->Coef[0] = filterTable(data,0, Param); + break; + } + + Z-=SubConst; + + if(Param->HP_ALFA!= 0) + { + OldOut = (Param->HP_ALFA * (OldOut + Z - OldIn))/256; + OldIn=Z; + Z=OldOut; + } + + if(Param->LP_ALFA != 0) + { + OldZ = ((256-Param->LP_ALFA)*OldZ+Param->LP_ALFA*Z)/256; + Z = OldZ; + } + + // if(Param->SincN>=3){ + // Z = RoundDiv(Z, DivideConst); + // Z *= MicGain; + // }else{ + Z *= MicGain; + Z = RoundDiv(Z, DivideConst); + // } + Z = SaturaLH(Z, -32700, 32700); // saturation + dataOut[i*Param->Out_MicChannels] = Z ; + // data+=(Param->Decimation-app)/8 * Param->In_MicChannels; + data+=Param->byte; + // data+=Param->Decimation/8*Param->In_MicChannels; + } + Param->OldOut=OldOut; + Param->OldIn=OldIn; + Param->OldZ=OldZ; +}