From 92eeb0872c383fb3cda62c162c81357abdd5782a Mon Sep 17 00:00:00 2001 From: van Date: Fri, 24 Nov 2023 01:20:07 +0800 Subject: [PATCH 1/3] 1. Add pitch algorithm, include "PEF", "NCF", "LHS", "HPS" etc. --- src/mir/_pitch_cep.c | 528 ++++++++++++++++++++++ src/mir/_pitch_cep.h | 43 ++ src/mir/_pitch_hps.c | 575 ++++++++++++++++++++++++ src/mir/_pitch_hps.h | 46 ++ src/mir/_pitch_lhs.c | 584 +++++++++++++++++++++++++ src/mir/_pitch_lhs.h | 47 ++ src/mir/_pitch_ncf.c | 547 +++++++++++++++++++++++ src/mir/_pitch_ncf.h | 43 ++ src/mir/_pitch_pef.c | 850 ++++++++++++++++++++++++++++++++++++ src/mir/_pitch_pef.h | 49 +++ src/mir/pitch_algorithm.c | 891 -------------------------------------- src/mir/pitch_algorithm.h | 54 --- 12 files changed, 3312 insertions(+), 945 deletions(-) create mode 100644 src/mir/_pitch_cep.c create mode 100644 src/mir/_pitch_cep.h create mode 100644 src/mir/_pitch_hps.c create mode 100644 src/mir/_pitch_hps.h create mode 100644 src/mir/_pitch_lhs.c create mode 100644 src/mir/_pitch_lhs.h create mode 100644 src/mir/_pitch_ncf.c create mode 100644 src/mir/_pitch_ncf.h create mode 100644 src/mir/_pitch_pef.c create mode 100644 src/mir/_pitch_pef.h delete mode 100644 src/mir/pitch_algorithm.c delete mode 100644 src/mir/pitch_algorithm.h diff --git a/src/mir/_pitch_cep.c b/src/mir/_pitch_cep.c new file mode 100644 index 0000000..80cbda6 --- /dev/null +++ b/src/mir/_pitch_cep.c @@ -0,0 +1,528 @@ +// + +#include +#include + +#include "../vector/flux_vector.h" +#include "../vector/flux_vectorOp.h" +#include "../vector/flux_complex.h" + +#include "../util/flux_util.h" + +#include "../dsp/flux_window.h" +#include "../dsp/fft_algorithm.h" + +#include "_pitch_cep.h" + +struct OpaquePitchCEP{ + int isContinue; + + FFTObj fftObj; + + int fftLength; + int slideLength; + int radix2Exp; // fftLength + + int cepFFTLength; + int timeLength; + + int minIndex; // edge + int maxIndex; + + float *winDataArr; // fftLength + float *mCepArr; // timeLength*cepFFTLength + + // cache data + float *realArr1; // cepFFTLength + float *imageArr1; + + float *realArr2; + float *imageArr2; + + float *dataArr1; + + // continue + float *tailDataArr; // fftLength + int tailDataLength; + + float *curDataArr; + int curDataLength; + + int samplate; + WindowType winType; + + float lowFre; + float highFre; + + int isDebug; +}; + +static void __calTimeAndTailLen(int dataLength,int fftLength,int slideLength,int *timeLength,int *tailLength); + +static void __pitchCEPObj_initData(PitchCEPObj pitchCEPObj); +static int __pitchCEPObj_dealData(PitchCEPObj pitchCEPObj,float *dataArr,int dataLength); + +static void __pitchCEPObj_calCep(PitchCEPObj pitchCEPObj); +static void __pitchCEPObj_dealResult(PitchCEPObj pitchCEPObj,float *freArr); + +/*** + samplate 32000 + lowFre 32, + highFre 2000 + radix2Exp 12 + WindowType hamm + slideLength (1<0&&*samplate<=196000){ + _samplate=*samplate; + } + } + + if(lowFre){ + if(*lowFre>=27){ + _lowFre=*lowFre; + } + } + + if(highFre){ + if(*highFre>_lowFre&&*highFre<_samplate/2){ + _highFre=*highFre; + } + else{ + _lowFre=32; + _highFre=2000; + } + } + + if(radix2Exp){ + if(*radix2Exp>=1&&*radix2Exp<=30){ + _radix2Exp=*radix2Exp; + } + } + + if(windowType){ + if(*windowType<=Window_Hamm){ + _winType=*windowType; + } + } + + fftLength=1<<_radix2Exp; + _slideLength=fftLength/4; + if(slideLength){ + if(*slideLength>0){ // &&*slideLength<=fftLength support not overlap + _slideLength=*slideLength; + } + } + + if(isContinue){ + _isContinue=*isContinue; + } + + fftObj_new(&fftObj, _radix2Exp+1); + + pitch->fftObj=fftObj; + + pitch->fftLength=fftLength; + pitch->slideLength=_slideLength; + pitch->radix2Exp=_radix2Exp; + + pitch->cepFFTLength=fftLength*2; + + pitch->samplate=_samplate; + pitch->winType=_winType; + + pitch->lowFre=_lowFre; + pitch->highFre=_highFre; + + pitch->isContinue=_isContinue; + + __pitchCEPObj_initData(pitch); + + return status; +} + +int pitchCEPObj_calTimeLength(PitchCEPObj pitchCEPObj,int dataLength){ + int fftLength=0; + int slideLength=0; + int tailDataLength=0; + + int isContinue=0; + + int timeLength=0; + + fftLength=pitchCEPObj->fftLength; + slideLength=pitchCEPObj->slideLength; + tailDataLength=pitchCEPObj->tailDataLength; + + isContinue=pitchCEPObj->isContinue; + + if(isContinue){ + dataLength+=tailDataLength; // outTimeLength + } + + if(dataLengthfftLength; + cepFFTLength=pitchCEPObj->cepFFTLength; + + samplate=pitchCEPObj->samplate; + winType=pitchCEPObj->winType; + + lowFre=pitchCEPObj->lowFre; + highFre=pitchCEPObj->highFre; + + minIndex=roundf(samplate/highFre); + maxIndex=roundf(samplate/lowFre); + + winDataArr=window_calFFTWindow(winType, fftLength); + + pitchCEPObj->minIndex=minIndex; + pitchCEPObj->maxIndex=maxIndex; + + pitchCEPObj->winDataArr=winDataArr; + + pitchCEPObj->realArr1=__vnew(cepFFTLength, NULL); + pitchCEPObj->imageArr1=__vnew(cepFFTLength, NULL); + + pitchCEPObj->realArr2=__vnew(cepFFTLength, NULL); + pitchCEPObj->imageArr2=__vnew(cepFFTLength, NULL); + + pitchCEPObj->dataArr1=__vnew(cepFFTLength, NULL); + pitchCEPObj->tailDataArr=__vnew(fftLength, NULL); +} + +static int __pitchCEPObj_dealData(PitchCEPObj pitchCEPObj,float *dataArr,int dataLength){ + int status=1; + + int fftLength=0; + int slideLength=0; + + int isContinue=0; + + float *tailDataArr=NULL; + int tailDataLength=0; + + float *curDataArr=NULL; + int curDataLength=0; + + int timeLength=0; + int cepFFTLength=0; + + int timeLen=0; + int tailLen=0; + + int totalLength=0; + + fftLength=pitchCEPObj->fftLength; + slideLength=pitchCEPObj->slideLength; + + isContinue=pitchCEPObj->isContinue; + + tailDataArr=pitchCEPObj->tailDataArr; + tailDataLength=pitchCEPObj->tailDataLength; + + curDataArr=pitchCEPObj->curDataArr; + curDataLength=pitchCEPObj->curDataLength; + + timeLength=pitchCEPObj->timeLength; + cepFFTLength=pitchCEPObj->cepFFTLength; + + if(isContinue){ + totalLength=tailDataLength+dataLength; + } + else{ + totalLength=dataLength; + } + + if(totalLengthcurDataLength|| + curDataLength>2*totalLength){ + + free(curDataArr); + curDataArr=(float *)calloc(totalLength+fftLength, sizeof(float )); + } + + curDataLength=0; + if(isContinue&&tailDataLength<0){ + memcpy(curDataArr, dataArr-tailDataLength, (dataLength+tailDataLength)*sizeof(float )); + curDataLength=(dataLength+tailDataLength); + } + else{ + if(isContinue&&tailDataLength>0){ // has & tail + memcpy(curDataArr, tailDataArr, tailDataLength*sizeof(float )); + curDataLength+=tailDataLength; + } + + memcpy(curDataArr+curDataLength, dataArr, dataLength*sizeof(float )); + curDataLength+=dataLength; + } + + // tailDataArr + tailDataLength=0; // reset !!! + if(isContinue){ + if(tailLen>0){ + memcpy(tailDataArr,curDataArr+(curDataLength-tailLen),tailLen*sizeof(float )); + } + + tailDataLength=tailLen; + } + + // update cache + if(pitchCEPObj->timeLengthtimeLength>timeLen*2){ + free(pitchCEPObj->mCepArr); + + pitchCEPObj->mCepArr=__vnew(timeLen*cepFFTLength,NULL); + } + } + else{ + if(isContinue){ + if(tailLen>0){ + if(tailDataLength>=0){ + memcpy(tailDataArr+tailDataLength,dataArr,dataLength*sizeof(float )); + } + else{ + memcpy(tailDataArr,dataArr-tailDataLength,(dataLength+tailDataLength)*sizeof(float )); + } + } + + tailDataLength=tailLen; + } + else{ + tailDataLength=0; + } + } + + pitchCEPObj->tailDataLength=tailDataLength; + + pitchCEPObj->curDataArr=curDataArr; + pitchCEPObj->curDataLength=curDataLength; + + pitchCEPObj->timeLength=timeLen; + + return status; +} + +void pitchCEPObj_pitch(PitchCEPObj pitchCEPObj,float *dataArr,int dataLength, + float *freArr){ + int status=0; + + if(!dataArr||dataLength<=0){ + return; + } + + // 1. deal data + status=__pitchCEPObj_dealData(pitchCEPObj,dataArr,dataLength); + if(!status){ + return; + } + + // 2. cep + __pitchCEPObj_calCep(pitchCEPObj); + + // 3. peak pick + __pitchCEPObj_dealResult(pitchCEPObj,freArr); +} + +static void __pitchCEPObj_calCep(PitchCEPObj pitchCEPObj){ + FFTObj fftObj=NULL; + + int fftLength=0; + int slideLength=0; + int timeLength=0; + + WindowType winType=Window_Rect; + float *winDataArr=NULL; // fftLength + + int minIndex=0; // edge + int maxIndex=0; + + int cepFFTLength=0; + + float *mCepArr=NULL; + + float *realArr1=NULL; + float *imageArr1=NULL; + + float *realArr2=NULL; + + float *dataArr1=NULL; + float *curDataArr=NULL; + + fftObj=pitchCEPObj->fftObj; + + fftLength=pitchCEPObj->fftLength; + slideLength=pitchCEPObj->slideLength; + timeLength=pitchCEPObj->timeLength; + + winType=pitchCEPObj->winType; + winDataArr=pitchCEPObj->winDataArr; + + minIndex=pitchCEPObj->minIndex; + maxIndex=pitchCEPObj->maxIndex; + + cepFFTLength=pitchCEPObj->cepFFTLength; + + mCepArr=pitchCEPObj->mCepArr; + + realArr1=pitchCEPObj->realArr1; + imageArr1=pitchCEPObj->imageArr1; + + realArr2=pitchCEPObj->realArr2; + + dataArr1=pitchCEPObj->dataArr1; + curDataArr=pitchCEPObj->curDataArr; + + for(int i=0;itimeLength; + cepFFTLength=pitchCEPObj->cepFFTLength; + + minIndex=pitchCEPObj->minIndex; + maxIndex=pitchCEPObj->maxIndex; + + samplate=pitchCEPObj->samplate; + mCepArr=pitchCEPObj->mCepArr; + for(int i=0;iisDebug=isDebug; +} + +void pitchCEPObj_free(PitchCEPObj pitchCEPObj){ + + if(pitchCEPObj){ + fftObj_free(pitchCEPObj->fftObj); + + free(pitchCEPObj->winDataArr); + free(pitchCEPObj->mCepArr); + + free(pitchCEPObj->realArr1); + free(pitchCEPObj->imageArr1); + + free(pitchCEPObj->realArr2); + free(pitchCEPObj->imageArr2); + + free(pitchCEPObj->dataArr1); + free(pitchCEPObj->tailDataArr); + + free(pitchCEPObj->curDataArr); + + free(pitchCEPObj); + } +} + +static void __calTimeAndTailLen(int dataLength,int fftLength,int slideLength,int *timeLength,int *tailLength){ + int timeLen=0; + int tailLen=0; + + timeLen=(dataLength-fftLength)/slideLength+1; + tailLen=(dataLength-fftLength)%slideLength+(fftLength-slideLength); + + if(timeLength){ + *timeLength=timeLen; + } + + if(tailLength){ + *tailLength=tailLen; + } +} + + + + + + + + + + diff --git a/src/mir/_pitch_cep.h b/src/mir/_pitch_cep.h new file mode 100644 index 0000000..c4f87dc --- /dev/null +++ b/src/mir/_pitch_cep.h @@ -0,0 +1,43 @@ + + +#ifndef _PITCH_CEP_H +#define _PITCH_CEP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "../flux_base.h" + +typedef struct OpaquePitchCEP *PitchCEPObj; + +/*** + samplate 32000 + lowFre 32, + highFre 2000 + radix2Exp 12 + WindowType Hamm + slideLength (1< +#include + +#include "../vector/flux_vector.h" +#include "../vector/flux_vectorOp.h" +#include "../vector/flux_complex.h" + +#include "../util/flux_util.h" + +#include "../dsp/flux_window.h" +#include "../dsp/fft_algorithm.h" + +#include "_pitch_hps.h" + +struct OpaquePitchHPS{ + int isContinue; + + FFTObj fftObj; + + int fftLength; + int slideLength; + int radix2Exp; // fftLength + + int interpFFTLength; + int timeLength; + + int minIndex; // edge + int maxIndex; + + int harmonicCount; + float *winDataArr; // fftLength + + float *mHpsArr; // timeLength*interpFFTLength + + // cache data + float *realArr1; // interpFFTLength + float *imageArr1; + + float *realArr2; + float *imageArr2; + + float *dataArr1; + + // continue + float *tailDataArr; // fftLength + int tailDataLength; + + float *curDataArr; + int curDataLength; + + int samplate; + WindowType winType; + + float lowFre; + float highFre; + + int isDebug; +}; + +static void __calTimeAndTailLen(int dataLength,int fftLength,int slideLength,int *timeLength,int *tailLength); + +static void __pitchHPSObj_initData(PitchHPSObj pitchHPSObj); +static int __pitchHPSObj_dealData(PitchHPSObj pitchHPSObj,float *dataArr,int dataLength); + +static void __pitchHPSObj_calHps(PitchHPSObj pitchHPSObj); +static void __pitchHPSObj_dealResult(PitchHPSObj pitchHPSObj,float *freArr); + +/*** + samplate 32000 + lowFre 32, + highFre 2000 + radix2Exp 12 + WindowType Hamm + slideLength (1<0 + isContinue 0 +****/ +int pitchHPSObj_new(PitchHPSObj *pitchHPSObj, + int *samplate,float *lowFre,float *highFre, + int *radix2Exp,int *slideLength,WindowType *windowType, + int *harmonicCount, + int *isContinue){ + int status=0; + + float _lowFre=32; // 27.5 + float _highFre=2000; // 2093/4186 + + int _samplate=32000; + int _radix2Exp=12; + int _slideLength=0; + WindowType _winType=Window_Hamm; + int _isContinue=0; + + int fftLength=0; + int interpFFTLength=0; + int radix2Exp2=0; + + int _hc=5; + + FFTObj fftObj=NULL; + PitchHPSObj pitch=NULL; + + pitch=*pitchHPSObj=(PitchHPSObj )calloc(1,sizeof(struct OpaquePitchHPS )); + + if(samplate){ + if(*samplate>0&&*samplate<=196000){ + _samplate=*samplate; + } + } + + if(lowFre){ + if(*lowFre>=27){ + _lowFre=*lowFre; + } + } + + if(highFre){ + if(*highFre>_lowFre&&*highFre<_samplate/2){ + _highFre=*highFre; + } + else{ + _lowFre=32; + _highFre=2000; + } + } + + if(radix2Exp){ + if(*radix2Exp>=1&&*radix2Exp<=30){ + _radix2Exp=*radix2Exp; + } + } + + if(harmonicCount){ + if(*harmonicCount>0){ + _hc=*harmonicCount; + } + } + + if(windowType){ + if(*windowType<=Window_Hamm){ + _winType=*windowType; + } + } + + fftLength=1<<_radix2Exp; + _slideLength=fftLength/4; + if(slideLength){ + if(*slideLength>0){ // &&*slideLength<=fftLength support not overlap + _slideLength=*slideLength; + } + } + + if(isContinue){ + _isContinue=*isContinue; + } + + interpFFTLength=util_roundPowerTwo(_samplate); + radix2Exp2=util_powerTwoBit(interpFFTLength); + + fftObj_new(&fftObj, radix2Exp2); + + pitch->fftObj=fftObj; + + pitch->fftLength=fftLength; + pitch->slideLength=_slideLength; + pitch->radix2Exp=_radix2Exp; + + pitch->interpFFTLength=interpFFTLength; + + pitch->samplate=_samplate; + pitch->winType=_winType; + + pitch->lowFre=_lowFre; + pitch->highFre=_highFre; + + pitch->harmonicCount=_hc; + pitch->isContinue=_isContinue; + + __pitchHPSObj_initData(pitch); + + return status; +} + +int pitchHPSObj_calTimeLength(PitchHPSObj pitchHPSObj,int dataLength){ + int fftLength=0; + int slideLength=0; + int tailDataLength=0; + + int isContinue=0; + + int timeLength=0; + + fftLength=pitchHPSObj->fftLength; + slideLength=pitchHPSObj->slideLength; + tailDataLength=pitchHPSObj->tailDataLength; + + isContinue=pitchHPSObj->isContinue; + + if(isContinue){ + dataLength+=tailDataLength; // outTimeLength + } + + if(dataLengthfftLength; + interpFFTLength=pitchHPSObj->interpFFTLength; + + samplate=pitchHPSObj->samplate; + winType=pitchHPSObj->winType; + + lowFre=pitchHPSObj->lowFre; + highFre=pitchHPSObj->highFre; + + harmonicCount=pitchHPSObj->harmonicCount; + + minIndex=ceilf(lowFre); + maxIndex=floorf(highFre); + + _k=samplate/(maxIndex+1); + if(harmonicCount>_k){ + harmonicCount=_k; + if(!harmonicCount){ + harmonicCount=1; + } + } + + winDataArr=window_calFFTWindow(winType, fftLength); + + pitchHPSObj->minIndex=minIndex; + pitchHPSObj->maxIndex=maxIndex; + + pitchHPSObj->winDataArr=winDataArr; + + pitchHPSObj->realArr1=__vnew(interpFFTLength, NULL); + pitchHPSObj->imageArr1=__vnew(interpFFTLength, NULL); + + pitchHPSObj->realArr2=__vnew(interpFFTLength, NULL); + pitchHPSObj->imageArr2=__vnew(interpFFTLength, NULL); + + pitchHPSObj->dataArr1=__vnew(interpFFTLength, NULL); + pitchHPSObj->tailDataArr=__vnew(fftLength, NULL); +} + +static int __pitchHPSObj_dealData(PitchHPSObj pitchHPSObj,float *dataArr,int dataLength){ + int status=1; + + int fftLength=0; + int slideLength=0; + + int isContinue=0; + + float *tailDataArr=NULL; + int tailDataLength=0; + + float *curDataArr=NULL; + int curDataLength=0; + + int timeLength=0; + int interpFFTLength=0; + + int timeLen=0; + int tailLen=0; + + int totalLength=0; + + fftLength=pitchHPSObj->fftLength; + slideLength=pitchHPSObj->slideLength; + + isContinue=pitchHPSObj->isContinue; + + tailDataArr=pitchHPSObj->tailDataArr; + tailDataLength=pitchHPSObj->tailDataLength; + + curDataArr=pitchHPSObj->curDataArr; + curDataLength=pitchHPSObj->curDataLength; + + timeLength=pitchHPSObj->timeLength; + interpFFTLength=pitchHPSObj->interpFFTLength; + + if(isContinue){ + totalLength=tailDataLength+dataLength; + } + else{ + totalLength=dataLength; + } + + if(totalLengthcurDataLength|| + curDataLength>2*totalLength){ + + free(curDataArr); + curDataArr=(float *)calloc(totalLength+fftLength, sizeof(float )); + } + + curDataLength=0; + if(isContinue&&tailDataLength<0){ + memcpy(curDataArr, dataArr-tailDataLength, (dataLength+tailDataLength)*sizeof(float )); + curDataLength=(dataLength+tailDataLength); + } + else{ + if(isContinue&&tailDataLength>0){ // has & tail + memcpy(curDataArr, tailDataArr, tailDataLength*sizeof(float )); + curDataLength+=tailDataLength; + } + + memcpy(curDataArr+curDataLength, dataArr, dataLength*sizeof(float )); + curDataLength+=dataLength; + } + + // tailDataArr + tailDataLength=0; // reset !!! + if(isContinue){ + if(tailLen>0){ + memcpy(tailDataArr,curDataArr+(curDataLength-tailLen),tailLen*sizeof(float )); + } + + tailDataLength=tailLen; + } + + // update cache + if(pitchHPSObj->timeLengthtimeLength>timeLen*2){ + free(pitchHPSObj->mHpsArr); + + pitchHPSObj->mHpsArr=__vnew(timeLen*interpFFTLength,NULL); + } + } + else{ + if(isContinue){ + if(tailLen>0){ + if(tailDataLength>=0){ + memcpy(tailDataArr+tailDataLength,dataArr,dataLength*sizeof(float )); + } + else{ + memcpy(tailDataArr,dataArr-tailDataLength,(dataLength+tailDataLength)*sizeof(float )); + } + } + + tailDataLength=tailLen; + } + else{ + tailDataLength=0; + } + } + + pitchHPSObj->tailDataLength=tailDataLength; + + pitchHPSObj->curDataArr=curDataArr; + pitchHPSObj->curDataLength=curDataLength; + + pitchHPSObj->timeLength=timeLen; + + return status; +} + + +void pitchHPSObj_pitch(PitchHPSObj pitchHPSObj,float *dataArr,int dataLength, + float *freArr){ + int status=0; + + if(!dataArr||dataLength<=0){ + return; + } + + // 1. deal data + status=__pitchHPSObj_dealData(pitchHPSObj,dataArr,dataLength); + if(!status){ + return; + } + + // 1. calHps + __pitchHPSObj_calHps(pitchHPSObj); + + // 2. peak pick + __pitchHPSObj_dealResult(pitchHPSObj,freArr); + +} + +static void __pitchHPSObj_calHps(PitchHPSObj pitchHPSObj){ + FFTObj fftObj=NULL; + + int fftLength=0; + int slideLength=0; + int timeLength=0; + + WindowType winType=Window_Hamm; + float *winDataArr=NULL; // fftLength + + int interpFFTLength=0; + int harmonicCount=0; + + int minIndex=0; + int maxIndex=0; + + float *mHpsArr=NULL; + float hps=0; + + float *realArr1=NULL; + float *imageArr1=NULL; + + float *realArr2=NULL; + + float *dataArr1=NULL; + float *curDataArr=NULL; + + fftObj=pitchHPSObj->fftObj; + + fftLength=pitchHPSObj->fftLength; + slideLength=pitchHPSObj->slideLength; + timeLength=pitchHPSObj->timeLength; + + winType=pitchHPSObj->winType; + winDataArr=pitchHPSObj->winDataArr; + + interpFFTLength=pitchHPSObj->interpFFTLength; + harmonicCount=pitchHPSObj->harmonicCount; + + minIndex=pitchHPSObj->minIndex; + maxIndex=pitchHPSObj->maxIndex; + + mHpsArr=pitchHPSObj->mHpsArr; + + realArr1=pitchHPSObj->realArr1; + imageArr1=pitchHPSObj->imageArr1; + + realArr2=pitchHPSObj->realArr2; + + dataArr1=pitchHPSObj->dataArr1; + curDataArr=pitchHPSObj->curDataArr; + + for(int i=0;itimeLength; + interpFFTLength=pitchHPSObj->interpFFTLength; + + minIndex=pitchHPSObj->minIndex; + maxIndex=pitchHPSObj->maxIndex; + + samplate=pitchHPSObj->samplate; + mHpsArr=pitchHPSObj->mHpsArr; + for(int i=0;iisDebug=isDebug; +} + +void pitchHPSObj_free(PitchHPSObj pitchHPSObj){ + + if(pitchHPSObj){ + fftObj_free(pitchHPSObj->fftObj); + + free(pitchHPSObj->winDataArr); + free(pitchHPSObj->mHpsArr); + + free(pitchHPSObj->realArr1); + free(pitchHPSObj->imageArr1); + + free(pitchHPSObj->realArr2); + free(pitchHPSObj->imageArr2); + + free(pitchHPSObj->dataArr1); + free(pitchHPSObj->tailDataArr); + + free(pitchHPSObj->curDataArr); + + free(pitchHPSObj); + } +} + +static void __calTimeAndTailLen(int dataLength,int fftLength,int slideLength,int *timeLength,int *tailLength){ + int timeLen=0; + int tailLen=0; + + timeLen=(dataLength-fftLength)/slideLength+1; + tailLen=(dataLength-fftLength)%slideLength+(fftLength-slideLength); + + if(timeLength){ + *timeLength=timeLen; + } + + if(tailLength){ + *tailLength=tailLen; + } +} + + + + + + + + + + + + + diff --git a/src/mir/_pitch_hps.h b/src/mir/_pitch_hps.h new file mode 100644 index 0000000..beb02b2 --- /dev/null +++ b/src/mir/_pitch_hps.h @@ -0,0 +1,46 @@ + + +#ifndef _PITCH_HPS_H +#define _PITCH_HPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "../flux_base.h" + +typedef struct OpaquePitchHPS *PitchHPSObj; + +/*** + samplate 32000 + lowFre 32, + highFre 2000 + radix2Exp 12 + WindowType Hamm + slideLength (1<0 + isContinue 0 +****/ +int pitchHPSObj_new(PitchHPSObj *pitchHPSObj, + int *samplate,float *lowFre,float *highFre, + int *radix2Exp,int *slideLength,WindowType *windowType, + int *harmonicCount, + int *isContinue); + +int pitchHPSObj_calTimeLength(PitchHPSObj pitchHPSObj,int dataLength); + +void pitchHPSObj_pitch(PitchHPSObj pitchHPSObj,float *dataArr,int dataLength, + float *freArr); + +void pitchHPSObj_enableDebug(PitchHPSObj pitchHPSObj,int isDebug); +void pitchHPSObj_free(PitchHPSObj pitchHPSObj); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/mir/_pitch_lhs.c b/src/mir/_pitch_lhs.c new file mode 100644 index 0000000..8715f76 --- /dev/null +++ b/src/mir/_pitch_lhs.c @@ -0,0 +1,584 @@ +// + +#include +#include + +#include "../vector/flux_vector.h" +#include "../vector/flux_vectorOp.h" +#include "../vector/flux_complex.h" + +#include "../util/flux_util.h" + +#include "../dsp/flux_window.h" +#include "../dsp/fft_algorithm.h" + +#include "_pitch_lhs.h" + +struct OpaquePitchLHS{ + int isContinue; + + FFTObj fftObj; + + int fftLength; + int slideLength; + int radix2Exp; // fftLength + + int interpFFTLength; // samplate + int timeLength; + + int minIndex; // edge + int maxIndex; + + int harmonicCount; + float *winDataArr; // fftLength + + float *mDbArr; // timeLength*interpFFTLength + float *mSumArr; + + // cache data + float *realArr1; // interpFFTLength + float *imageArr1; + + float *dataArr1; + + // continue + float *tailDataArr; // fftLength + int tailDataLength; + + float *curDataArr; + int curDataLength; + + int samplate; + WindowType winType; + + float lowFre; + float highFre; + + int isDebug; +}; + +static void __calTimeAndTailLen(int dataLength,int fftLength,int slideLength,int *timeLength,int *tailLength); + +static void __pitchLHSObj_initData(PitchLHSObj pitchLHSObj); +static int __pitchLHSObj_dealData(PitchLHSObj pitchLHSObj,float *dataArr,int dataLength); + +static void __pitchLHSObj_calDb(PitchLHSObj pitchLHSObj); +static void __pitchLHSObj_calSum(PitchLHSObj pitchLHSObj); +static void __pitchLHSObj_dealResult(PitchLHSObj pitchLHSObj,float *freArr); + +/*** + samplate 32000 + lowFre 32, + highFre 2000 + + radix2Exp 12 + WindowType hamm + slideLength (1<0 + isContinue 0 +****/ +int pitchLHSObj_new(PitchLHSObj *pitchLHSObj, + int *samplate,float *lowFre,float *highFre, + int *radix2Exp,int *slideLength,WindowType *windowType, + int *harmonicCount, + int *isContinue){ + int status=0; + + float _lowFre=32; // 27.5 + float _highFre=2000; // 2093/4186 + + int _samplate=32000; + int _radix2Exp=12; + int _slideLength=0; + WindowType _winType=Window_Hamm; + int _isContinue=0; + + int fftLength=0; + int interpFFTLength=0; + int radix2Exp2=0; + + int _hc=5; + + FFTObj fftObj=NULL; + PitchLHSObj pitch=NULL; + + pitch=*pitchLHSObj=(PitchLHSObj )calloc(1,sizeof(struct OpaquePitchLHS )); + + if(samplate){ + if(*samplate>0&&*samplate<=196000){ + _samplate=*samplate; + } + } + + if(lowFre){ + if(*lowFre>=27){ + _lowFre=*lowFre; + } + } + + if(highFre){ + if(*highFre>_lowFre&&*highFre<_samplate/2){ + _highFre=*highFre; + } + else{ + _lowFre=32; + _highFre=2000; + } + } + + if(radix2Exp){ + if(*radix2Exp>=1&&*radix2Exp<=30){ + _radix2Exp=*radix2Exp; + } + } + + if(harmonicCount){ + if(*harmonicCount>0){ + _hc=*harmonicCount; + } + } + + if(windowType){ + _winType=*windowType; + } + + fftLength=1<<_radix2Exp; + _slideLength=fftLength/4; + if(slideLength){ + if(*slideLength>0){ // &&*slideLength<=fftLength support not overlap + _slideLength=*slideLength; + } + } + + if(isContinue){ + _isContinue=*isContinue; + } + + interpFFTLength=util_roundPowerTwo(_samplate); + radix2Exp2=util_powerTwoBit(interpFFTLength); + + fftObj_new(&fftObj, radix2Exp2); + + pitch->fftObj=fftObj; + + pitch->fftLength=fftLength; + pitch->slideLength=_slideLength; + pitch->radix2Exp=_radix2Exp; + + pitch->interpFFTLength=interpFFTLength; + + pitch->samplate=_samplate; + pitch->winType=_winType; + + pitch->lowFre=_lowFre; + pitch->highFre=_highFre; + + pitch->harmonicCount=_hc; + pitch->isContinue=_isContinue; + + __pitchLHSObj_initData(pitch); + + return status; +} + +int pitchLHSObj_calTimeLength(PitchLHSObj pitchLHSObj,int dataLength){ + int fftLength=0; + int slideLength=0; + int tailDataLength=0; + + int isContinue=0; + + int timeLength=0; + + fftLength=pitchLHSObj->fftLength; + slideLength=pitchLHSObj->slideLength; + tailDataLength=pitchLHSObj->tailDataLength; + + isContinue=pitchLHSObj->isContinue; + + if(isContinue){ + dataLength+=tailDataLength; // outTimeLength + } + + if(dataLengthfftLength; + interpFFTLength=pitchLHSObj->interpFFTLength; + + samplate=pitchLHSObj->samplate; + winType=pitchLHSObj->winType; + + lowFre=pitchLHSObj->lowFre; + highFre=pitchLHSObj->highFre; + + harmonicCount=pitchLHSObj->harmonicCount; + + minIndex=ceilf(lowFre); + maxIndex=floorf(highFre); + + _k=samplate/(maxIndex+1); + if(harmonicCount>_k){ + harmonicCount=_k; + if(!harmonicCount){ + harmonicCount=1; + } + } + + winDataArr=window_calFFTWindow(winType, fftLength); + + pitchLHSObj->minIndex=minIndex; + pitchLHSObj->maxIndex=maxIndex; + + pitchLHSObj->harmonicCount=harmonicCount; + + pitchLHSObj->winDataArr=winDataArr; + + pitchLHSObj->realArr1=__vnew(interpFFTLength, NULL); + pitchLHSObj->imageArr1=__vnew(interpFFTLength, NULL); + + pitchLHSObj->dataArr1=__vnew(interpFFTLength, NULL); + pitchLHSObj->tailDataArr=__vnew(fftLength, NULL); +} + +static int __pitchLHSObj_dealData(PitchLHSObj pitchLHSObj,float *dataArr,int dataLength){ + int status=1; + + int fftLength=0; + int slideLength=0; + + int isContinue=0; + + float *tailDataArr=NULL; + int tailDataLength=0; + + float *curDataArr=NULL; + int curDataLength=0; + + int timeLength=0; + int interpFFTLength=0; + + int timeLen=0; + int tailLen=0; + + int totalLength=0; + + fftLength=pitchLHSObj->fftLength; + slideLength=pitchLHSObj->slideLength; + + isContinue=pitchLHSObj->isContinue; + + tailDataArr=pitchLHSObj->tailDataArr; + tailDataLength=pitchLHSObj->tailDataLength; + + curDataArr=pitchLHSObj->curDataArr; + curDataLength=pitchLHSObj->curDataLength; + + timeLength=pitchLHSObj->timeLength; + interpFFTLength=pitchLHSObj->interpFFTLength; + + if(isContinue){ + totalLength=tailDataLength+dataLength; + } + else{ + totalLength=dataLength; + } + + if(totalLengthcurDataLength|| + curDataLength>2*totalLength){ + + free(curDataArr); + curDataArr=(float *)calloc(totalLength+fftLength, sizeof(float )); + } + + curDataLength=0; + if(isContinue&&tailDataLength<0){ + memcpy(curDataArr, dataArr-tailDataLength, (dataLength+tailDataLength)*sizeof(float )); + curDataLength=(dataLength+tailDataLength); + } + else{ + if(isContinue&&tailDataLength>0){ // has & tail + memcpy(curDataArr, tailDataArr, tailDataLength*sizeof(float )); + curDataLength+=tailDataLength; + } + + memcpy(curDataArr+curDataLength, dataArr, dataLength*sizeof(float )); + curDataLength+=dataLength; + } + + // tailDataArr + tailDataLength=0; // reset !!! + if(isContinue){ + if(tailLen>0){ + memcpy(tailDataArr,curDataArr+(curDataLength-tailLen),tailLen*sizeof(float )); + } + + tailDataLength=tailLen; + } + + // update cache + if(pitchLHSObj->timeLengthtimeLength>timeLen*2){ + free(pitchLHSObj->mDbArr); + free(pitchLHSObj->mSumArr); + + pitchLHSObj->mDbArr=__vnew(timeLen*interpFFTLength,NULL); + pitchLHSObj->mSumArr=__vnew(timeLen*interpFFTLength,NULL); + } + } + else{ + if(isContinue){ + if(tailLen>0){ + if(tailDataLength>=0){ + memcpy(tailDataArr+tailDataLength,dataArr,dataLength*sizeof(float )); + } + else{ + memcpy(tailDataArr,dataArr-tailDataLength,(dataLength+tailDataLength)*sizeof(float )); + } + } + + tailDataLength=tailLen; + } + else{ + tailDataLength=0; + } + } + + pitchLHSObj->tailDataLength=tailDataLength; + + pitchLHSObj->curDataArr=curDataArr; + pitchLHSObj->curDataLength=curDataLength; + + pitchLHSObj->timeLength=timeLen; + + return status; +} + +void pitchLHSObj_pitch(PitchLHSObj pitchLHSObj,float *dataArr,int dataLength, + float *freArr){ + int status=0; + + if(!dataArr||dataLength<=0){ + return; + } + + // 1. deal data + status=__pitchLHSObj_dealData(pitchLHSObj,dataArr,dataLength); + if(!status){ + return; + } + + // 1. calDb + __pitchLHSObj_calDb(pitchLHSObj); + + // 2. calSum + __pitchLHSObj_calSum(pitchLHSObj); + + // 3. peak pick + __pitchLHSObj_dealResult(pitchLHSObj,freArr); + +} + +static void __pitchLHSObj_calDb(PitchLHSObj pitchLHSObj){ + FFTObj fftObj=NULL; + + int fftLength=0; + int slideLength=0; + int timeLength=0; + + float *winDataArr=NULL; // fftLength + + int interpFFTLength=0; + + float *mDbArr=NULL; + + float *realArr1=NULL; + float *imageArr1=NULL; + + float *dataArr1=NULL; + float *curDataArr=NULL; + + fftObj=pitchLHSObj->fftObj; + + fftLength=pitchLHSObj->fftLength; + slideLength=pitchLHSObj->slideLength; + timeLength=pitchLHSObj->timeLength; + + winDataArr=pitchLHSObj->winDataArr; + + interpFFTLength=pitchLHSObj->interpFFTLength; + + mDbArr=pitchLHSObj->mDbArr; + + realArr1=pitchLHSObj->realArr1; + imageArr1=pitchLHSObj->imageArr1; + + dataArr1=pitchLHSObj->dataArr1; + curDataArr=pitchLHSObj->curDataArr; + + for(int i=0;itimeLength; + interpFFTLength=pitchLHSObj->interpFFTLength; + + harmonicCount=pitchLHSObj->harmonicCount; + + minIndex=pitchLHSObj->minIndex; + maxIndex=pitchLHSObj->maxIndex; + + mDbArr=pitchLHSObj->mDbArr; + mSumArr=pitchLHSObj->mSumArr; + + for(int i=0;itimeLength; + interpFFTLength=pitchLHSObj->interpFFTLength; + + minIndex=pitchLHSObj->minIndex; + maxIndex=pitchLHSObj->maxIndex; + + samplate=pitchLHSObj->samplate; + mSumArr=pitchLHSObj->mSumArr; + for(int i=0;iisDebug=1; +} + +void pitchLHSObj_free(PitchLHSObj pitchLHSObj){ + + if(pitchLHSObj){ + fftObj_free(pitchLHSObj->fftObj); + + free(pitchLHSObj->winDataArr); + + free(pitchLHSObj->mDbArr); + free(pitchLHSObj->mSumArr); + + free(pitchLHSObj->realArr1); + free(pitchLHSObj->imageArr1); + + free(pitchLHSObj->dataArr1); + + free(pitchLHSObj->tailDataArr); + free(pitchLHSObj->curDataArr); + + free(pitchLHSObj); + } +} + +static void __calTimeAndTailLen(int dataLength,int fftLength,int slideLength,int *timeLength,int *tailLength){ + int timeLen=0; + int tailLen=0; + + timeLen=(dataLength-fftLength)/slideLength+1; + tailLen=(dataLength-fftLength)%slideLength+(fftLength-slideLength); + + if(timeLength){ + *timeLength=timeLen; + } + + if(tailLength){ + *tailLength=tailLen; + } +} + + + + + + + + + diff --git a/src/mir/_pitch_lhs.h b/src/mir/_pitch_lhs.h new file mode 100644 index 0000000..5de63a0 --- /dev/null +++ b/src/mir/_pitch_lhs.h @@ -0,0 +1,47 @@ + + +#ifndef _PITCH_LHS_H +#define _PITCH_LHS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "../flux_base.h" + +typedef struct OpaquePitchLHS *PitchLHSObj; + +/*** + samplate 32000 + lowFre 32, + highFre 2000 + + radix2Exp 12 + WindowType hamm + slideLength (1<0 + isContinue 0 +****/ +int pitchLHSObj_new(PitchLHSObj *pitchLHSObj, + int *samplate,float *lowFre,float *highFre, + int *radix2Exp,int *slideLength,WindowType *windowType, + int *harmonicCount, + int *isContinue); + +int pitchLHSObj_calTimeLength(PitchLHSObj pitchLHSObj,int dataLength); + +void pitchLHSObj_pitch(PitchLHSObj pitchLHSObj,float *dataArr,int dataLength, + float *freArr); + +void pitchLHSObj_enableDebug(PitchLHSObj pitchLHSObj,int isDebug); +void pitchLHSObj_free(PitchLHSObj pitchLHSObj); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/mir/_pitch_ncf.c b/src/mir/_pitch_ncf.c new file mode 100644 index 0000000..97c1be6 --- /dev/null +++ b/src/mir/_pitch_ncf.c @@ -0,0 +1,547 @@ +// + +#include +#include + +#include "../vector/flux_vector.h" +#include "../vector/flux_vectorOp.h" +#include "../vector/flux_complex.h" + +#include "../util/flux_util.h" + +#include "../dsp/flux_window.h" +#include "../dsp/fft_algorithm.h" + +#include "_pitch_ncf.h" + +struct OpaquePitchNCF{ + int isContinue; + + FFTObj fftObj; + + int fftLength; + int slideLength; + int radix2Exp; // fftLength + + int corrFFTLength; + int timeLength; + + int minIndex; // edge + int maxIndex; + + float *winDataArr; // fftLength + float *mCorrArr; // timeLength*corrFFTLength + + // cache data + float *realArr1; // corrFFTLength + float *imageArr1; + + float *realArr2; + float *imageArr2; + + float *dataArr1; + + // continue + float *tailDataArr; // fftLength + int tailDataLength; + + float *curDataArr; + int curDataLength; + + int samplate; + WindowType winType; + + float lowFre; + float highFre; + + int isDebug; +}; + +static void __calTimeAndTailLen(int dataLength,int fftLength,int slideLength,int *timeLength,int *tailLength); + +static void __pitchNCFObj_initData(PitchNCFObj pitchNCFObj); +static int __pitchNCFObj_dealData(PitchNCFObj pitchNCFObj,float *dataArr,int dataLength); + +static void __pitchNCFObj_calCorr(PitchNCFObj pitchNCFObj); +static void __pitchNCFObj_dealResult(PitchNCFObj pitchNCFObj,float *freArr); + +/*** + samplate 32000 + lowFre 32, + highFre 2000 + radix2Exp 12 + WindowType rect + slideLength (1<0&&*samplate<=196000){ + _samplate=*samplate; + } + } + + if(lowFre){ + if(*lowFre>=27){ + _lowFre=*lowFre; + } + } + + if(highFre){ + if(*highFre>_lowFre&&*highFre<_samplate/2){ + _highFre=*highFre; + } + else{ + _lowFre=32; + _highFre=2000; + } + } + + if(radix2Exp){ + if(*radix2Exp>=1&&*radix2Exp<=30){ + _radix2Exp=*radix2Exp; + } + } + + if(windowType){ + _winType=*windowType; + } + + fftLength=1<<_radix2Exp; + _slideLength=fftLength/4; + if(slideLength){ + if(*slideLength>0){ // &&*slideLength<=fftLength support not overlap + _slideLength=*slideLength; + } + } + + if(isContinue){ + _isContinue=*isContinue; + } + + fftObj_new(&fftObj, _radix2Exp+1); + + pitch->fftObj=fftObj; + + pitch->fftLength=fftLength; + pitch->slideLength=_slideLength; + pitch->radix2Exp=_radix2Exp; + + pitch->corrFFTLength=fftLength*2; + + pitch->samplate=_samplate; + pitch->winType=_winType; + + pitch->lowFre=_lowFre; + pitch->highFre=_highFre; + + pitch->isContinue=_isContinue; + + __pitchNCFObj_initData(pitch); + + return status; +} + +int pitchNCFObj_calTimeLength(PitchNCFObj pitchNCFObj,int dataLength){ + int fftLength=0; + int slideLength=0; + int tailDataLength=0; + + int isContinue=0; + + int timeLength=0; + + fftLength=pitchNCFObj->fftLength; + slideLength=pitchNCFObj->slideLength; + tailDataLength=pitchNCFObj->tailDataLength; + + isContinue=pitchNCFObj->isContinue; + + if(isContinue){ + dataLength+=tailDataLength; // outTimeLength + } + + if(dataLengthfftLength; + corrFFTLength=pitchNCFObj->corrFFTLength; + + samplate=pitchNCFObj->samplate; + winType=pitchNCFObj->winType; + + lowFre=pitchNCFObj->lowFre; + highFre=pitchNCFObj->highFre; + + minIndex=roundf(samplate/highFre); + maxIndex=roundf(samplate/lowFre); + + winDataArr=window_calFFTWindow(winType, fftLength); + + pitchNCFObj->minIndex=minIndex; + pitchNCFObj->maxIndex=maxIndex; + + pitchNCFObj->winDataArr=winDataArr; + + pitchNCFObj->realArr1=__vnew(corrFFTLength, NULL); + pitchNCFObj->imageArr1=__vnew(corrFFTLength, NULL); + + pitchNCFObj->realArr2=__vnew(corrFFTLength, NULL); + pitchNCFObj->imageArr2=__vnew(corrFFTLength, NULL); + + pitchNCFObj->dataArr1=__vnew(corrFFTLength, NULL); + pitchNCFObj->tailDataArr=__vnew(fftLength, NULL); +} + +static int __pitchNCFObj_dealData(PitchNCFObj pitchNCFObj,float *dataArr,int dataLength){ + int status=1; + + int fftLength=0; + int slideLength=0; + + int isContinue=0; + + float *tailDataArr=NULL; + int tailDataLength=0; + + float *curDataArr=NULL; + int curDataLength=0; + + int timeLength=0; + int corrFFTLength=0; + + int timeLen=0; + int tailLen=0; + + int totalLength=0; + + fftLength=pitchNCFObj->fftLength; + slideLength=pitchNCFObj->slideLength; + + isContinue=pitchNCFObj->isContinue; + + tailDataArr=pitchNCFObj->tailDataArr; + tailDataLength=pitchNCFObj->tailDataLength; + + curDataArr=pitchNCFObj->curDataArr; + curDataLength=pitchNCFObj->curDataLength; + + timeLength=pitchNCFObj->timeLength; + corrFFTLength=pitchNCFObj->corrFFTLength; + + if(isContinue){ + totalLength=tailDataLength+dataLength; + } + else{ + totalLength=dataLength; + } + + if(totalLengthcurDataLength|| + curDataLength>2*totalLength){ + + free(curDataArr); + curDataArr=(float *)calloc(totalLength+fftLength, sizeof(float )); + } + + curDataLength=0; + if(isContinue&&tailDataLength<0){ + memcpy(curDataArr, dataArr-tailDataLength, (dataLength+tailDataLength)*sizeof(float )); + curDataLength=(dataLength+tailDataLength); + } + else{ + if(isContinue&&tailDataLength>0){ // has & tail + memcpy(curDataArr, tailDataArr, tailDataLength*sizeof(float )); + curDataLength+=tailDataLength; + } + + memcpy(curDataArr+curDataLength, dataArr, dataLength*sizeof(float )); + curDataLength+=dataLength; + } + + // tailDataArr + tailDataLength=0; // reset !!! + if(isContinue){ + if(tailLen>0){ + memcpy(tailDataArr,curDataArr+(curDataLength-tailLen),tailLen*sizeof(float )); + } + + tailDataLength=tailLen; + } + + // update cache + if(pitchNCFObj->timeLengthtimeLength>timeLen*2){ + free(pitchNCFObj->mCorrArr); + + pitchNCFObj->mCorrArr=__vnew(timeLen*corrFFTLength,NULL); + } + } + else{ + if(isContinue){ + if(tailLen>0){ + if(tailDataLength>=0){ + memcpy(tailDataArr+tailDataLength,dataArr,dataLength*sizeof(float )); + } + else{ + memcpy(tailDataArr,dataArr-tailDataLength,(dataLength+tailDataLength)*sizeof(float )); + } + } + + tailDataLength=tailLen; + } + else{ + tailDataLength=0; + } + } + + pitchNCFObj->tailDataLength=tailDataLength; + + pitchNCFObj->curDataArr=curDataArr; + pitchNCFObj->curDataLength=curDataLength; + + pitchNCFObj->timeLength=timeLen; + + return status; +} + +void pitchNCFObj_pitch(PitchNCFObj pitchNCFObj,float *dataArr,int dataLength, + float *freArr){ + int status=0; + + if(!dataArr||dataLength<=0){ + return; + } + + // 1. deal data + status=__pitchNCFObj_dealData(pitchNCFObj,dataArr,dataLength); + if(!status){ + return; + } + + // 2. corr + __pitchNCFObj_calCorr(pitchNCFObj); + + // 3. peak pick + __pitchNCFObj_dealResult(pitchNCFObj,freArr); + +} + +static void __pitchNCFObj_calCorr(PitchNCFObj pitchNCFObj){ + FFTObj fftObj=NULL; + + int fftLength=0; + int slideLength=0; + int timeLength=0; + + WindowType winType=Window_Rect; + float *winDataArr=NULL; // fftLength + + int minIndex=0; // edge + int maxIndex=0; + + int corrFFTLength=0; + + float *mCorrArr=NULL; + + float *realArr1=NULL; + float *imageArr1=NULL; + + float *realArr2=NULL; + + float *dataArr1=NULL; + float *curDataArr=NULL; + + int len=0; + + int lagNum=0; + int padNum=0; + + fftObj=pitchNCFObj->fftObj; + + fftLength=pitchNCFObj->fftLength; + slideLength=pitchNCFObj->slideLength; + timeLength=pitchNCFObj->timeLength; + + winType=pitchNCFObj->winType; + winDataArr=pitchNCFObj->winDataArr; + + minIndex=pitchNCFObj->minIndex; + maxIndex=pitchNCFObj->maxIndex; + + corrFFTLength=pitchNCFObj->corrFFTLength; + + mCorrArr=pitchNCFObj->mCorrArr; + + realArr1=pitchNCFObj->realArr1; + imageArr1=pitchNCFObj->imageArr1; + + realArr2=pitchNCFObj->realArr2; + + dataArr1=pitchNCFObj->dataArr1; + curDataArr=pitchNCFObj->curDataArr; + + len=(maxIndextimeLength; + corrFFTLength=pitchNCFObj->corrFFTLength; + + minIndex=pitchNCFObj->minIndex; + maxIndex=pitchNCFObj->maxIndex; + + samplate=pitchNCFObj->samplate; + mCorrArr=pitchNCFObj->mCorrArr; + for(int i=0;iisDebug=isDebug; +} + +void pitchNCFObj_free(PitchNCFObj pitchNCFObj){ + + if(pitchNCFObj){ + fftObj_free(pitchNCFObj->fftObj); + + free(pitchNCFObj->winDataArr); + free(pitchNCFObj->mCorrArr); + + free(pitchNCFObj->realArr1); + free(pitchNCFObj->imageArr1); + + free(pitchNCFObj->realArr2); + free(pitchNCFObj->imageArr2); + + free(pitchNCFObj->dataArr1); + free(pitchNCFObj->tailDataArr); + + free(pitchNCFObj->curDataArr); + + free(pitchNCFObj); + } +} + +static void __calTimeAndTailLen(int dataLength,int fftLength,int slideLength,int *timeLength,int *tailLength){ + int timeLen=0; + int tailLen=0; + + timeLen=(dataLength-fftLength)/slideLength+1; + tailLen=(dataLength-fftLength)%slideLength+(fftLength-slideLength); + + if(timeLength){ + *timeLength=timeLen; + } + + if(tailLength){ + *tailLength=tailLen; + } +} + + + + + + + + + diff --git a/src/mir/_pitch_ncf.h b/src/mir/_pitch_ncf.h new file mode 100644 index 0000000..0cfa2f6 --- /dev/null +++ b/src/mir/_pitch_ncf.h @@ -0,0 +1,43 @@ + + +#ifndef _PITCH_NCF_H +#define _PITCH_NCF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "../flux_base.h" + +typedef struct OpaquePitchNCF *PitchNCFObj; + +/*** + samplate 32000 + lowFre 32, + highFre 2000 + radix2Exp 12 + WindowType rect + slideLength (1< +#include + +#include "../vector/flux_vector.h" +#include "../vector/flux_vectorOp.h" +#include "../vector/flux_complex.h" + +#include "../util/flux_util.h" + +#include "../dsp/flux_window.h" +#include "../dsp/fft_algorithm.h" + +#include "_pitch_pef.h" + +struct OpaquePitchPEF{ + int isContinue; + + FFTObj fftObj1; // 2*fftLength + FFTObj fftObj2; // (4||8)*fftLength ??? + + int fftLength; + int slideLength; + int radix2Exp; // fftLength + + int xcorrFFTLength; // (4||8)*fftLength ??? + + int timeLength; + + int minIndex; // edge + int maxIndex; + + float *winDataArr; // fftLength + + // freband + float *linearFreBandArr; // fftLength+1 + float *logFreBandArr; // fftLength*2 + float *bandWidthArr; // fftLength*2 + + // estimate filter + float alpha; // 10 + float beta; // 0.5 0~1 + float gamma; // 1.8 >1 + + float *filterArr; // fftLength*8 ->xcorrFFTLength + int filterPadNum; + + float *mPowerArr; // timeLength*(2*fftLength) + float *mInterpArr; // timeLength*(8*fftLength) ->xcorrFFTLength + float *mXcorrArr; // timeLength*(8*fftLength) ->xcorrFFTLength + + // cache data + float *realArr1; // fftLength*8 ->xcorrFFTLength + float *imageArr1; + + float *realArr2; + float *imageArr2; + + float *realArr3; + float *imageArr3; + + float *dataArr1; // fftLength*2 + + // continue + float *tailDataArr; // fftLength + int tailDataLength; + + float *curDataArr; + int curDataLength; + + int samplate; + WindowType winType; + + float lowFre; + float highFre; + float cutFre; // >highFre + + int isDebug; +}; + +static void __calTimeAndTailLen(int dataLength,int fftLength,int slideLength,int *timeLength,int *tailLength); + +static void __pitchPEFObj_initData(PitchPEFObj pitchPEFObj); +static void __pitchPEFObj_calEstimateFilter(PitchPEFObj pitchPEFObj); + +static int __pitchPEFObj_dealData(PitchPEFObj pitchPEFObj,float *dataArr,int dataLength); + +static void __pitchPEFObj_calInterp(PitchPEFObj pitchPEFObj); +static void __pitchPEFObj_calXcorr(PitchPEFObj pitchPEFObj); +static void __pitchPEFObj_dealResult(PitchPEFObj pitchPEFObj,float *freArr); + +/*** + samplate 32000 + lowFre 32, + highFre 2000 + cutFre 4000, >highFre + + radix2Exp 12 + WindowType hamm + slideLength (1<0, beta 0.5 0~1, gamma 1.8 >1 + + isContinue 0 +****/ +int pitchPEFObj_new(PitchPEFObj *pitchPEFObj, + int *samplate,float *lowFre,float *highFre,float *cutFre, + int *radix2Exp,int *slideLength,WindowType *windowType, + float *alpha,float *beta,float *gamma, + int *isContinue){ + int status=0; + + float _lowFre=32; // 27.5 + float _highFre=2000; // 2093/4186 + float _cutFre=4000; + + int _samplate=32000; + int _radix2Exp=12; + int _slideLength=0; + WindowType _winType=Window_Hamm; + int _isContinue=0; + + float _alpha=10; // 10 >1 + float _beta=0.5; // 0.5 0~1 + float _gamma=1.8; // 1.8 >1 + + int fftLength=0; + + FFTObj fftObj1=NULL; + + PitchPEFObj pitch=NULL; + + pitch=*pitchPEFObj=(PitchPEFObj )calloc(1,sizeof(struct OpaquePitchPEF )); + + if(samplate){ + if(*samplate>0&&*samplate<=196000){ + _samplate=*samplate; + } + } + + if(lowFre){ + if(*lowFre>=27){ + _lowFre=*lowFre; + } + } + + if(highFre){ + if(*highFre>_lowFre&&*highFre<_samplate/2){ + _highFre=*highFre; + } + else{ + _lowFre=32; + _highFre=2000; + } + } + + if(cutFre){ + if(*cutFre>=_highFre){ + _cutFre=*cutFre; + } + else{ + _cutFre=_highFre; + } + } + + if(radix2Exp){ + if(*radix2Exp>=1&&*radix2Exp<=30){ + _radix2Exp=*radix2Exp; + } + } + + if(windowType){ + _winType=*windowType; + } + + if(alpha){ + if(*alpha>0){ + _alpha=*alpha; + } + } + + if(beta){ + if(*beta>0){ + _beta=*beta; + } + } + + if(gamma){ + if(*gamma>1){ + _gamma=*gamma; + } + } + + fftLength=1<<_radix2Exp; + _slideLength=fftLength/4; + if(slideLength){ + if(*slideLength>0){ // &&*slideLength<=fftLength support not overlap + _slideLength=*slideLength; + } + } + + if(isContinue){ + _isContinue=*isContinue; + } + + fftObj_new(&fftObj1, _radix2Exp+1); + + pitch->fftObj1=fftObj1; + + pitch->fftLength=fftLength; + pitch->slideLength=_slideLength; + pitch->radix2Exp=_radix2Exp; + + pitch->alpha=_alpha; + pitch->beta=_beta; + pitch->gamma=_gamma; + + pitch->samplate=_samplate; + pitch->winType=_winType; + + pitch->lowFre=_lowFre; + pitch->highFre=_highFre; + pitch->cutFre=_cutFre; + + pitch->isContinue=_isContinue; + + __pitchPEFObj_initData(pitch); + __pitchPEFObj_calEstimateFilter(pitch); + + return status; +} + +void pitchPEFObj_pitch(PitchPEFObj pitchPEFObj,float *dataArr,int dataLength, + float *freArr){ + int status=0; + + if(!dataArr||dataLength<=0){ + return; + } + + // 1. deal data + status=__pitchPEFObj_dealData(pitchPEFObj,dataArr,dataLength); + if(!status){ + return; + } + + // 2. power&interp + __pitchPEFObj_calInterp(pitchPEFObj); + + // 3. cross correlation + __pitchPEFObj_calXcorr(pitchPEFObj); + + // 4. peak pick + __pitchPEFObj_dealResult(pitchPEFObj,freArr); + +} + +static void __pitchPEFObj_calInterp(PitchPEFObj pitchPEFObj){ + FFTObj fftObj1=NULL; + + int fftLength=0; + int slideLength=0; + int timeLength=0; + + float *winDataArr=NULL; // fftLength + + // freband + float *linearFreBandArr=NULL; // fftLength+1 + float *logFreBandArr=NULL; // fftLength*2 + float *bandWidthArr=NULL; // fftLength*2 + + int xcorrFFTLength=0; + int filterPadNum=0; + + float *mPowerArr=NULL; + float *mInterpArr=NULL; + + float *realArr1=NULL; + float *imageArr1=NULL; + + float *dataArr1=NULL; + float *curDataArr=NULL; + + fftObj1=pitchPEFObj->fftObj1; + + fftLength=pitchPEFObj->fftLength; + slideLength=pitchPEFObj->slideLength; + timeLength=pitchPEFObj->timeLength; + + winDataArr=pitchPEFObj->winDataArr; + + linearFreBandArr=pitchPEFObj->linearFreBandArr; + logFreBandArr=pitchPEFObj->logFreBandArr; + bandWidthArr=pitchPEFObj->bandWidthArr; + + xcorrFFTLength=pitchPEFObj->xcorrFFTLength; + filterPadNum=pitchPEFObj->filterPadNum; + + mPowerArr=pitchPEFObj->mPowerArr; + mInterpArr=pitchPEFObj->mInterpArr; + + realArr1=pitchPEFObj->realArr1; + imageArr1=pitchPEFObj->imageArr1; + + dataArr1=pitchPEFObj->dataArr1; + curDataArr=pitchPEFObj->curDataArr; + + for(int i=0;ifftObj2; + timeLength=pitchPEFObj->timeLength; + + filterArr=pitchPEFObj->filterArr; + filterPadNum=pitchPEFObj->filterPadNum; + + xcorrFFTLength=pitchPEFObj->xcorrFFTLength; + + mInterpArr=pitchPEFObj->mInterpArr; + mXcorrArr=pitchPEFObj->mXcorrArr; + + realArr1=pitchPEFObj->realArr1; + imageArr1=pitchPEFObj->imageArr1; + + realArr2=pitchPEFObj->realArr2; + imageArr2=pitchPEFObj->imageArr2; + + realArr3=pitchPEFObj->realArr3; + imageArr3=pitchPEFObj->imageArr3; + + fftObj_fft(fftObj2, filterArr, NULL, realArr2, imageArr2); + for(int i=0;itimeLength; + + fftLength=pitchPEFObj->fftLength; + xcorrFFTLength=pitchPEFObj->xcorrFFTLength; + filterPadNum=pitchPEFObj->filterPadNum; + + minIndex=pitchPEFObj->minIndex; + maxIndex=pitchPEFObj->maxIndex; + + logFreBandArr=pitchPEFObj->logFreBandArr; + mXcorrArr=pitchPEFObj->mXcorrArr; + + realArr3=pitchPEFObj->realArr3; + + len=(maxIndexfftLength; + + samplate=pitchPEFObj->samplate; + winType=pitchPEFObj->winType; + + lowFre=pitchPEFObj->lowFre; + highFre=pitchPEFObj->highFre; + cutFre=pitchPEFObj->cutFre; + + winDataArr=window_calFFTWindow(winType, fftLength); + linearFreBandArr=__vlinspace(0, samplate/2, fftLength+1, 0); + + fre1=(samplate/2>cutFre?cutFre:samplate/2-1); + logFreBandArr=__vlogspace(1, log10f(fre1), fftLength*2, 0); + + for(int i=1;iminIndex=minIndex; + pitchPEFObj->maxIndex=maxIndex; + + pitchPEFObj->winDataArr=winDataArr; + + pitchPEFObj->linearFreBandArr=linearFreBandArr; + pitchPEFObj->logFreBandArr=logFreBandArr; + pitchPEFObj->bandWidthArr=bandWidthArr; + + pitchPEFObj->filterArr=__vnew(fftLength*8, NULL); + + pitchPEFObj->realArr1=__vnew(fftLength*8, NULL); + pitchPEFObj->imageArr1=__vnew(fftLength*8, NULL); + + pitchPEFObj->realArr2=__vnew(fftLength*8, NULL); + pitchPEFObj->imageArr2=__vnew(fftLength*8, NULL); + + pitchPEFObj->realArr3=__vnew(fftLength*8, NULL); + pitchPEFObj->imageArr3=__vnew(fftLength*8, NULL); + + pitchPEFObj->dataArr1=__vnew(fftLength*2, NULL); + + pitchPEFObj->tailDataArr=__vnew(fftLength, NULL); +} + +static int __pitchPEFObj_dealData(PitchPEFObj pitchPEFObj,float *dataArr,int dataLength){ + int status=1; + + int fftLength=0; + int slideLength=0; + + int isContinue=0; + + float *tailDataArr=NULL; + int tailDataLength=0; + + float *curDataArr=NULL; + int curDataLength=0; + + int timeLength=0; + + int xcorrFFTLength=0; // (4||8)*fftLength ??? + + float *mPowerArr=NULL; // timeLength*fftLength + float *mInterpArr=NULL; // timeLength*(2*fftLength) + float *mXcorrArr=NULL; // timeLength*(8*fftLength) + + int timeLen=0; + int tailLen=0; + + int totalLength=0; + + fftLength=pitchPEFObj->fftLength; + slideLength=pitchPEFObj->slideLength; + + isContinue=pitchPEFObj->isContinue; + + tailDataArr=pitchPEFObj->tailDataArr; + tailDataLength=pitchPEFObj->tailDataLength; + + curDataArr=pitchPEFObj->curDataArr; + curDataLength=pitchPEFObj->curDataLength; + + timeLength=pitchPEFObj->timeLength; + xcorrFFTLength=pitchPEFObj->xcorrFFTLength; + + mPowerArr=pitchPEFObj->mPowerArr; + mInterpArr=pitchPEFObj->mInterpArr; + mXcorrArr=pitchPEFObj->mXcorrArr; + + if(isContinue){ + totalLength=tailDataLength+dataLength; + } + else{ + totalLength=dataLength; + } + + if(totalLengthcurDataLength|| + curDataLength>2*totalLength){ + + free(curDataArr); + curDataArr=(float *)calloc(totalLength+fftLength, sizeof(float )); + } + + curDataLength=0; + if(isContinue&&tailDataLength<0){ + memcpy(curDataArr, dataArr-tailDataLength, (dataLength+tailDataLength)*sizeof(float )); + curDataLength=(dataLength+tailDataLength); + } + else{ + if(isContinue&&tailDataLength>0){ // has & tail + memcpy(curDataArr, tailDataArr, tailDataLength*sizeof(float )); + curDataLength+=tailDataLength; + } + + memcpy(curDataArr+curDataLength, dataArr, dataLength*sizeof(float )); + curDataLength+=dataLength; + } + + // tailDataArr + tailDataLength=0; // reset !!! + if(isContinue){ + if(tailLen>0){ + memcpy(tailDataArr,curDataArr+(curDataLength-tailLen),tailLen*sizeof(float )); + } + + tailDataLength=tailLen; + } + + // update cache + if(pitchPEFObj->timeLengthtimeLength>timeLen*2){ + free(pitchPEFObj->mPowerArr); + free(pitchPEFObj->mInterpArr); + free(pitchPEFObj->mXcorrArr); + + pitchPEFObj->mPowerArr=__vnew(timeLen*fftLength*2,NULL); + pitchPEFObj->mInterpArr=__vnew(timeLen*fftLength*8,NULL); + pitchPEFObj->mXcorrArr=__vnew(timeLen*fftLength*8,NULL); + } + } + else{ + if(isContinue){ + if(tailLen>0){ + if(tailDataLength>=0){ + memcpy(tailDataArr+tailDataLength,dataArr,dataLength*sizeof(float )); + } + else{ + memcpy(tailDataArr,dataArr-tailDataLength,(dataLength+tailDataLength)*sizeof(float )); + } + } + + tailDataLength=tailLen; + } + else{ + tailDataLength=0; + } + } + + pitchPEFObj->tailDataLength=tailDataLength; + + pitchPEFObj->curDataArr=curDataArr; + pitchPEFObj->curDataLength=curDataLength; + + pitchPEFObj->timeLength=timeLen; + + return status; +} + +int pitchPEFObj_calTimeLength(PitchPEFObj pitchPEFObj,int dataLength){ + int fftLength=0; + int slideLength=0; + int tailDataLength=0; + + int isContinue=0; + + int timeLength=0; + + fftLength=pitchPEFObj->fftLength; + slideLength=pitchPEFObj->slideLength; + tailDataLength=pitchPEFObj->tailDataLength; + + isContinue=pitchPEFObj->isContinue; + + if(isContinue){ + dataLength+=tailDataLength; // outTimeLength + } + + if(dataLength0&&beta>0&&gamma>1)){ + return; + } + + if(alpha!=pitchPEFObj->alpha||beta!=pitchPEFObj->beta||gamma!=pitchPEFObj->gamma){ + __pitchPEFObj_calEstimateFilter(pitchPEFObj); + } +} + +static void __pitchPEFObj_calEstimateFilter(PitchPEFObj pitchPEFObj){ + int fftLength=0; + + FFTObj fftObj2=NULL; + int radix2Exp=0; + + int xcorrFFTLength=0; + + float *filterArr=NULL; + int filterPadNum=0; + + float alpha=0; // 10 + float beta=0; // 0.5 0~1 + float gamma=0; // 1.8 >1 + + float *qArr=NULL; + float *hArr=NULL; + float *dArr=NULL; + + float value1=0; + float value2=0; + float det=0; + + fftLength=pitchPEFObj->fftLength; + + alpha=pitchPEFObj->alpha; + beta=pitchPEFObj->beta; + gamma=pitchPEFObj->gamma; + + filterArr=pitchPEFObj->filterArr; + + qArr=__vlogspace(log10f(beta), log10f(alpha+beta), fftLength, 0); + hArr=__vnew(fftLength, NULL); + dArr=__vnew(fftLength+1, NULL); + + // 1. hArr,filterPadNum + for(int i=0;iradix2Exp; + if(filterPadNum){ + radix2Exp+=3; + } + else{ + radix2Exp+=2; + } + + xcorrFFTLength=1<fftObj2); + + free(qArr); + free(hArr); + free(dArr); + + pitchPEFObj->fftObj2=fftObj2; + pitchPEFObj->xcorrFFTLength=xcorrFFTLength; + + pitchPEFObj->filterPadNum=filterPadNum; +} + +void pitchPEFObj_enableDebug(PitchPEFObj pitchPEFObj,int isDebug){ + + pitchPEFObj->isDebug=isDebug; +} + +void pitchPEFObj_free(PitchPEFObj pitchPEFObj){ + + if(pitchPEFObj){ + fftObj_free(pitchPEFObj->fftObj1); + fftObj_free(pitchPEFObj->fftObj2); + + free(pitchPEFObj->winDataArr); + + free(pitchPEFObj->linearFreBandArr); + free(pitchPEFObj->logFreBandArr); + free(pitchPEFObj->bandWidthArr); + + free(pitchPEFObj->filterArr); + + free(pitchPEFObj->mPowerArr); + free(pitchPEFObj->mInterpArr); + free(pitchPEFObj->mXcorrArr); + + free(pitchPEFObj->realArr1); + free(pitchPEFObj->imageArr1); + + free(pitchPEFObj->realArr2); + free(pitchPEFObj->imageArr2); + + free(pitchPEFObj->realArr3); + free(pitchPEFObj->imageArr3); + + free(pitchPEFObj->dataArr1); + + free(pitchPEFObj->tailDataArr); + free(pitchPEFObj->curDataArr); + + free(pitchPEFObj); + } +} + +static void __calTimeAndTailLen(int dataLength,int fftLength,int slideLength,int *timeLength,int *tailLength){ + int timeLen=0; + int tailLen=0; + + timeLen=(dataLength-fftLength)/slideLength+1; + tailLen=(dataLength-fftLength)%slideLength+(fftLength-slideLength); + + if(timeLength){ + *timeLength=timeLen; + } + + if(tailLength){ + *tailLength=tailLen; + } +} + + + + + + + + diff --git a/src/mir/_pitch_pef.h b/src/mir/_pitch_pef.h new file mode 100644 index 0000000..1b846bb --- /dev/null +++ b/src/mir/_pitch_pef.h @@ -0,0 +1,49 @@ + + +#ifndef _PITCH_PEF_H +#define _PITCH_PEF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "../flux_base.h" + +typedef struct OpaquePitchPEF *PitchPEFObj; + +/*** + samplate 32000 + lowFre 32, + highFre 2000 + cutFre 4000, >highFre + + radix2Exp 12 + WindowType hamm + slideLength (1<0, beta 0.5 0~1, gamma 1.8 >1 + + isContinue 0 +****/ +int pitchPEFObj_new(PitchPEFObj *pitchPEFObj, + int *samplate,float *lowFre,float *highFre,float *cutFre, + int *radix2Exp,int *slideLength,WindowType *windowType, + float *alpha,float *beta,float *gamma, + int *isContinue); + +int pitchPEFObj_calTimeLength(PitchPEFObj pitchPEFObj,int dataLength); +void pitchPEFObj_setFilterParams(PitchPEFObj pitchPEFObj,float alpha,float beta,float gamma); + +void pitchPEFObj_pitch(PitchPEFObj pitchPEFObj,float *dataArr,int dataLength, + float *freArr); + +void pitchPEFObj_enableDebug(PitchPEFObj pitchPEFObj,int isDebug); +void pitchPEFObj_free(PitchPEFObj pitchPEFObj); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/mir/pitch_algorithm.c b/src/mir/pitch_algorithm.c deleted file mode 100644 index 819dcff..0000000 --- a/src/mir/pitch_algorithm.c +++ /dev/null @@ -1,891 +0,0 @@ -// - -#include -#include - -#include "../vector/flux_vector.h" -#include "../vector/flux_vectorOp.h" -#include "../vector/flux_complex.h" - -#include "../util/flux_util.h" - -#include "../dsp/flux_window.h" -#include "../dsp/fft_algorithm.h" - -#include "pitch_algorithm.h" - -/*** - NCF 1960 自相关 - YIN 2002 差分函数自相关 - PYIN 2014 阈值概率分布+hmm-viterbi预测 - STFT/PEF 2011 基于stft的过滤算法 -****/ -struct OpaquePitch{ - PitchType type; - int isContinue; - - FFTObj fftObj; - - int fftLength; - int slideLength; - int autoLength; // autocorr length - - int minIndex; // min/maxFre - int maxIndex; - - // yinLength timeLength - float *mYinArr; // timeLength*yinLength - float *mInterpArr; - - float *mNumArr; // timeLength*yinLength - float *mDenArr; - - float *mDiffArr; // timeLength*diffLength - float *mMeanArr; // timeLength*maxIndex - - // cache data ->fftLength - float *realArr1; - float *imageArr1; - - float *realArr2; - float *imageArr2; - - float *realArr3; - float *imageArr3; - - float *energyArr1; - float *energyArr2; - - float *dataArr1; - - // continue相关数据 - float *tailDataArr; - int tailDataLength; - - float *curDataArr; - int curDataLength; - - int samplate; - float thresh; // 0.1 good - - int isDebug; -}; - -static void __calTimeAndTailLen(int dataLength,int fftLength,int slideLength,int *timeLength,int *tailLength); - -static void __pitchObj_initData(PitchObj pitchObj,int length); - -static int __pitchObj_dealData(PitchObj pitchObj,float *dataArr,int dataLength); -static void __pitchObj_pitch(PitchObj pitchObj,float *freArr,float *troughArr,float *minArr); - -static void __pitchObj_calDiff(PitchObj pitchObj); -static void __pitchObj_calInterp(PitchObj pitchObj); -static void __pitchObj_dealResult(PitchObj pitchObj,float *freArr,float *troughArr,float *minArr); - -int pitchObj_new(PitchObj *pitchObj,PitchType *type, - int *samplate,float *lowFre,float *highFre, - int *radix2Exp,int *slideLength,int *autoLength, - int *isContinue){ - int status=0; - - PitchType _type=Pitch_YIN; - - int _samplate=32000; - float _lowFre=27; // 27.5 - float _highFre=2093; // 2093 - int _radix2Exp=12; - int _slideLength=0; - int _autoLength=0; - int _isContinue=0; - - int fftLength=0; - int minIndex=0; // min/maxFre - int maxIndex=0; - - int diffLength=0; - int yinLength=0; - - float thresh=0.1; - - FFTObj fftObj=NULL; - PitchObj pitch=NULL; - - pitch=*pitchObj=(PitchObj )calloc(1,sizeof(struct OpaquePitch )); - - if(type){ - _type=*type; - } - - if(samplate){ - if(*samplate>0&&*samplate<=196000){ - _samplate=*samplate; - } - } - - if(lowFre){ - if(*lowFre>=27){ - _lowFre=*lowFre; - } - } - - if(highFre){ - if(*highFre>_lowFre&&*highFre<_samplate/2){ - _highFre=*highFre; - } - else{ - _lowFre=27; - _highFre=2093; - } - } - - if(radix2Exp){ - if(*radix2Exp>=1&&*radix2Exp<=30){ - _radix2Exp=*radix2Exp; - } - } - - fftLength=1<<_radix2Exp; - _slideLength=fftLength/4; - if(slideLength){ - if(*slideLength>0){ // &&*slideLength<=fftLength support not overlap - _slideLength=*slideLength; - } - } - - _autoLength=fftLength/2; - if(autoLength){ - if(*autoLength>=0&&*autoLengthdiffLength-1){ - maxIndex=diffLength-1; - } - - yinLength=maxIndex-minIndex+1; - - fftObj_new(&fftObj, _radix2Exp); - - pitch->type=_type; - pitch->isContinue=_isContinue; - - pitch->fftObj=fftObj; - - pitch->fftLength=fftLength; - pitch->slideLength=_slideLength; - pitch->autoLength=_autoLength; - - pitch->minIndex=minIndex; - pitch->maxIndex=maxIndex; - - pitch->diffLength=diffLength; - pitch->yinLength=yinLength; - - pitch->samplate=_samplate; - pitch->thresh=thresh; - - // cache data ->fftLength - __pitchObj_initData(pitch,fftLength); - - return status; -} - -static void __pitchObj_initData(PitchObj pitchObj,int length){ - - pitchObj->realArr1=__vnew(length, NULL); - pitchObj->imageArr1=__vnew(length, NULL); - - pitchObj->realArr2=__vnew(length, NULL); - pitchObj->imageArr2=__vnew(length, NULL); - - pitchObj->realArr3=__vnew(length, NULL); - pitchObj->imageArr3=__vnew(length, NULL); - - pitchObj->energyArr1=__vnew(length, NULL); - pitchObj->energyArr2=__vnew(length, NULL); - - pitchObj->dataArr1=__vnew(length, NULL); - - pitchObj->tailDataArr=__vnew(length, NULL); -} - -// default 0.1 thresh>0&&thresh<1 -void pitchObj_setThresh(PitchObj pitchObj,float thresh){ - - // if(thresh>0&&thresh<1){ - // pitchObj->thresh=thresh; - // } - - if(thresh>0){ - pitchObj->thresh=thresh; - } -} - -void pitchObj_pitch(PitchObj pitchObj,float *dataArr,int dataLength, - float *freArr,float *valueArr1,float *valueArr2){ - int status=0; - - if(!dataArr||dataLength<=0){ - return; - } - - // 1. 处理相关数据 - status=__pitchObj_dealData(pitchObj,dataArr,dataLength); - if(!status){ - return; - } - - // 2. yin - __pitchObj_pitch(pitchObj,freArr,valueArr1,valueArr2); -} - -static void __pitchObj_pitch(PitchObj pitchObj,float *freArr,float *troughArr,float *minArr){ - - __pitchObj_calDiff(pitchObj); - __pitchObj_calInterp(pitchObj); - __pitchObj_dealResult(pitchObj,freArr,troughArr,minArr); -} - -static void __pitchObj_calDiff(PitchObj pitchObj){ - FFTObj fftObj=NULL; - - int fftLength=0; - int slideLength=0; - int autoLength=0; // autocorr length - - int minIndex=0; // min/maxFre - int maxIndex=0; - - int diffLength=0; - int yinLength=0; - int timeLength=0; - - float *mYinArr=NULL; - float *mInterpArr=NULL; - - float *mNumArr=NULL; - float *mDenArr=NULL; - - float *mDiffArr=NULL; - float *mMeanArr=NULL; - - float *realArr1=NULL; - float *imageArr1=NULL; - - float *realArr2=NULL; - float *imageArr2=NULL; - - float *realArr3=NULL; - float *imageArr3=NULL; - - float *energyArr1=NULL; - float *energyArr2=NULL; - - float *dataArr1=NULL; - - float *curDataArr=NULL; - - fftObj=pitchObj->fftObj; - - fftLength=pitchObj->fftLength; - slideLength=pitchObj->slideLength; - autoLength=pitchObj->autoLength; - - minIndex=pitchObj->minIndex; - maxIndex=pitchObj->maxIndex; - - diffLength=pitchObj->diffLength; - yinLength=pitchObj->yinLength; - timeLength=pitchObj->timeLength; - - mYinArr=pitchObj->mYinArr; - mInterpArr=pitchObj->mInterpArr; - - mNumArr=pitchObj->mNumArr; - mDenArr=pitchObj->mDenArr; - - mDiffArr=pitchObj->mDiffArr; - mMeanArr=pitchObj->mMeanArr; - - realArr1=pitchObj->realArr1; - imageArr1=pitchObj->imageArr1; - - realArr2=pitchObj->realArr2; - imageArr2=pitchObj->imageArr2; - - realArr3=pitchObj->realArr3; - imageArr3=pitchObj->imageArr3; - - energyArr1=pitchObj->energyArr1; - energyArr2=pitchObj->energyArr2; - - dataArr1=pitchObj->dataArr1; - - curDataArr=pitchObj->curDataArr; - - for(int i=0;i realArr1 - fftObj_fft(fftObj,curDataArr+i*slideLength,NULL,realArr1,imageArr1); - - for(int j=0;j<=autoLength;j++){ - dataArr1[j]=curDataArr[i*slideLength+autoLength-j]; - } - fftObj_fft(fftObj,dataArr1,NULL,realArr2,imageArr2); - - __vcmul(realArr1, imageArr1, realArr2, imageArr2, fftLength, realArr3, imageArr3); - - memset(realArr1, 0, sizeof(float )*fftLength); - memset(imageArr1, 0, sizeof(float )*fftLength); - fftObj_ifft(fftObj, realArr3, imageArr3, realArr1, imageArr1); - - for(int j=autoLength,k=0;j=1e-6){ - realArr1[k]=_value; - } - else { - realArr1[k]=0; - } - } - - // 2. energy -->energyArr2 - for(int j=0;j=1e-6){ - energyArr2[j]=_value; - } - else { - energyArr2[j]=0; - } - } - - // 3. difference - for(int j=0;jtimeLength*yinLength - for(int j=minIndex,k=0;jtimeLength*maxIndex - for(int j=1,k=0;jtimeLength*yinLength - for(int j=minIndex-1,k=0;jyinLength; - timeLength=pitchObj->timeLength; - - mYinArr=pitchObj->mYinArr; - mInterpArr=pitchObj->mInterpArr; - - memset(mInterpArr, 0, sizeof(float )*timeLength*yinLength); - for(int i=0;iyinLength; - timeLength=pitchObj->timeLength; - - mYinArr=pitchObj->mYinArr; - mInterpArr=pitchObj->mInterpArr; - - minIndex=pitchObj->minIndex; - - samplate=pitchObj->samplate; - thresh=pitchObj->thresh; - - for(int i=0;iisDebug){ - float *minArr=NULL; - int *mIndexArr=NULL; - - float *troughArr=NULL; - int *tIndexArr=NULL; - float *freArr=NULL; - - int len=0; - - minArr=__vnew(timeLength, NULL); - mIndexArr=__vnewi(timeLength, NULL); - - troughArr=__vnew(yinLength/2+1, NULL); - tIndexArr=__vnewi(yinLength/2+1, NULL); - freArr=__vnew(yinLength/2+1, NULL); - - printf("pitch debug start ------\n"); - - for(int i=0;islideLength/pitchObj->samplate); - - if(len){ - printf(" "); - __vdebug(troughArr, len, 0); - - printf(" "); - __vdebugi(tIndexArr, len, 0); - - printf(" "); - __vdebug(freArr, len, 0); - } - - printf(" "); - printf("min:%d ,%f \n",mIndexArr[i],minArr[i]); - } - - printf("\n"); - printf("minArr:\n"); - - printf(" "); - __vdebug(minArr, timeLength, 0); - - printf(" "); - __vdebugi(mIndexArr, timeLength, 0); - - printf("pitch debug end ------\n"); - - free(minArr); - free(mIndexArr); - - free(troughArr); - free(tIndexArr); - free(freArr); - } -} - -int pitchObj_calTimeLength(PitchObj pitchObj,int dataLength){ - int fftLength=0; - int slideLength=0; - int tailDataLength=0; - - int isContinue=0; - - int timeLength=0; - - fftLength=pitchObj->fftLength; - slideLength=pitchObj->slideLength; - tailDataLength=pitchObj->tailDataLength; - - isContinue=pitchObj->isContinue; - - if(isContinue){ - dataLength+=tailDataLength; // outTimeLength - } - - if(dataLengthisDebug=isDebug; -} - -void pitchObj_free(PitchObj pitchObj){ - - if(pitchObj){ - fftObj_free(pitchObj->fftObj); - - free(pitchObj->mYinArr); - free(pitchObj->mInterpArr); - - free(pitchObj->mNumArr); - free(pitchObj->mDenArr); - - free(pitchObj->mDiffArr); - free(pitchObj->mMeanArr); - - free(pitchObj->realArr1); - free(pitchObj->imageArr1); - - free(pitchObj->realArr2); - free(pitchObj->imageArr2); - - free(pitchObj->realArr3); - free(pitchObj->imageArr3); - - free(pitchObj->energyArr1); - free(pitchObj->energyArr2); - - free(pitchObj->dataArr1); - - free(pitchObj->tailDataArr); - free(pitchObj->curDataArr); - - free(pitchObj); - } -} - -static int __pitchObj_dealData(PitchObj pitchObj,float *dataArr,int dataLength){ - int status=1; - - int fftLength=0; - int slideLength=0; - - int isContinue=0; - - float *tailDataArr=NULL; - int tailDataLength=0; - - float *curDataArr=NULL; - int curDataLength=0; - - int maxIndex=0; - - int diffLength=0; - int yinLength=0; - int timeLength=0; - - int timeLen=0; - int tailLen=0; - - int totalLength=0; - - fftLength=pitchObj->fftLength; - slideLength=pitchObj->slideLength; - - isContinue=pitchObj->isContinue; - - tailDataArr=pitchObj->tailDataArr; - tailDataLength=pitchObj->tailDataLength; - - curDataArr=pitchObj->curDataArr; - curDataLength=pitchObj->curDataLength; - - maxIndex=pitchObj->maxIndex; - - diffLength=pitchObj->diffLength; - yinLength=pitchObj->yinLength; - timeLength=pitchObj->timeLength; - - if(isContinue){ - totalLength=tailDataLength+dataLength; - } - else{ - totalLength=dataLength; - } - - if(totalLengthcurDataLength|| - curDataLength>2*totalLength){ - - free(curDataArr); - curDataArr=(float *)calloc(totalLength+fftLength, sizeof(float )); - } - - curDataLength=0; - if(isContinue&&tailDataLength<0){ - memcpy(curDataArr, dataArr-tailDataLength, (dataLength+tailDataLength)*sizeof(float )); - curDataLength=(dataLength+tailDataLength); - } - else{ - if(isContinue&&tailDataLength>0){ // 连续且存在尾数据 - memcpy(curDataArr, tailDataArr, tailDataLength*sizeof(float )); - curDataLength+=tailDataLength; - } - - memcpy(curDataArr+curDataLength, dataArr, dataLength*sizeof(float )); - curDataLength+=dataLength; - } - - // tailDataArr相关 - tailDataLength=0; // reset !!! - if(isContinue){ - if(tailLen>0){ - memcpy(tailDataArr,curDataArr+(curDataLength-tailLen),tailLen*sizeof(float )); - } - - tailDataLength=tailLen; - } - - // yin 相关 - if(pitchObj->timeLengthtimeLength>timeLen*2){ // 更新缓存 - free(pitchObj->mYinArr); - free(pitchObj->mInterpArr); - - free(pitchObj->mNumArr); - free(pitchObj->mDenArr); - - free(pitchObj->mDiffArr); - free(pitchObj->mMeanArr); - - pitchObj->mYinArr=__vnew(timeLen*yinLength,NULL); - pitchObj->mInterpArr=__vnew(timeLen*yinLength,NULL); - - pitchObj->mNumArr=__vnew(timeLen*yinLength,NULL); - pitchObj->mDenArr=__vnew(timeLen*yinLength,NULL); - - pitchObj->mDiffArr=__vnew(timeLen*diffLength,NULL); - pitchObj->mMeanArr=__vnew(timeLen*maxIndex,NULL); - } - } - else{ - if(isContinue){ - if(tailLen>0){ - if(tailDataLength>=0){ - memcpy(tailDataArr+tailDataLength,dataArr,dataLength*sizeof(float )); - } - else{ - memcpy(tailDataArr,dataArr-tailDataLength,(dataLength+tailDataLength)*sizeof(float )); - } - } - - tailDataLength=tailLen; - } - else{ - tailDataLength=0; - } - } - - pitchObj->tailDataLength=tailDataLength; - - pitchObj->curDataArr=curDataArr; - pitchObj->curDataLength=curDataLength; - - pitchObj->timeLength=timeLen; - - return status; -} - -static void __calTimeAndTailLen(int dataLength,int fftLength,int slideLength,int *timeLength,int *tailLength){ - int timeLen=0; - int tailLen=0; - - timeLen=(dataLength-fftLength)/slideLength+1; - tailLen=(dataLength-fftLength)%slideLength+(fftLength-slideLength); - - if(timeLength){ - *timeLength=timeLen; - } - - if(tailLength){ - *tailLength=tailLen; - } -} - - - - - - - - - diff --git a/src/mir/pitch_algorithm.h b/src/mir/pitch_algorithm.h deleted file mode 100644 index 4cad8c7..0000000 --- a/src/mir/pitch_algorithm.h +++ /dev/null @@ -1,54 +0,0 @@ - - -#ifndef PITCH_ALGORITHM_H -#define PITCH_ALGORITHM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -typedef enum{ - Pitch_YIN=0, - Pitch_STFT, - Pitch_NCF, - Pitch_PEF, - -} PitchType; - -typedef struct OpaquePitch *PitchObj; - -/*** - type None - samplate 32000 - lowFre 27 - highFre 2000 - - radix2Exp 12 - slideLength (1<0&&thresh<1 -void pitchObj_setThresh(PitchObj pitchObj,float thresh); -int pitchObj_calTimeLength(PitchObj pitchObj,int dataLength); - -void pitchObj_pitch(PitchObj pitchObj,float *dataArr,int dataLength, - float *freArr,float *valueArr1,float *valueArr2); - -void pitchObj_enableDebug(PitchObj pitchObj,int isDebug); -void pitchObj_free(PitchObj pitchObj); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file From d04a448f0f0b043bf3bec57e8db52f7d7c4afb8a Mon Sep 17 00:00:00 2001 From: van Date: Fri, 24 Nov 2023 11:41:00 +0800 Subject: [PATCH 2/3] 1. Update vector/util. --- src/util/flux_util.c | 20 ++++++++++++++++++++ src/util/flux_util.h | 3 +++ src/vector/flux_vector.c | 11 +++++++++++ src/vector/flux_vector.h | 1 + src/vector/flux_vectorOp.c | 33 +++++++++++++++++++++++++++++++++ src/vector/flux_vectorOp.h | 3 +++ 6 files changed, 71 insertions(+) diff --git a/src/util/flux_util.c b/src/util/flux_util.c index 1ce5dac..0f302cf 100644 --- a/src/util/flux_util.c +++ b/src/util/flux_util.c @@ -529,6 +529,26 @@ float util_qaudInterp(float value1,float value2,float value3,float *outValue){ return p; } +// peak pick +void util_peakPick(float *pArr,int length,int start,int end,int distance,int num,float *vArr,int *cArr){ + int index1=0; + int index2=0; + + if(distance<=0){ + distance=1; + } + + for(int i=0;istart?cArr[i]-distance:start); + index2=(cArr[i]+distancexArr1[index1+1]){ + index1++; + } + + if(index1 Date: Fri, 24 Nov 2023 11:54:05 +0800 Subject: [PATCH 3/3] 1. Add Cepstrum and Harmonic algorithm. --- src/cepstrogram_algorithm.c | 370 +++++++++++++ src/cepstrogram_algorithm.h | 45 ++ src/harmonic_algorithm.c | 1037 +++++++++++++++++++++++++++++++++++ src/harmonic_algorithm.h | 37 ++ 4 files changed, 1489 insertions(+) create mode 100644 src/cepstrogram_algorithm.c create mode 100644 src/cepstrogram_algorithm.h create mode 100644 src/harmonic_algorithm.c create mode 100644 src/harmonic_algorithm.h diff --git a/src/cepstrogram_algorithm.c b/src/cepstrogram_algorithm.c new file mode 100644 index 0000000..4bb998e --- /dev/null +++ b/src/cepstrogram_algorithm.c @@ -0,0 +1,370 @@ +// + +#include +#include + +#include "vector/flux_vector.h" +#include "vector/flux_complex.h" + +#include "util/flux_util.h" + +#include "dsp/fft_algorithm.h" + +#include "stft_algorithm.h" +#include "cepstrogram_algorithm.h" + +struct OpaqueCepstrogram{ + STFTObj stftObj; + FFTObj fftObj; + + int fftLength; // fftLength,timeLength + int timeLength; + + int radix2Exp; // stft + WindowType windowType; + int slideLength; + + // stft + float *mYArr1; // ifft(log(S)) + float *mRealArr1; // stft r,i(timeLength*fftLength) + float *mImageArr1; + float *mSArr1; // power + + float *mYArr2; // envelope + float *mRealArr2; + float *mImageArr2; + + float *mYArr3; // details + float *mRealArr3; + float *mImageArr3; + + int isDebug; + +}; + +static void __cepstrogramObj_spectrogram(CepstrogramObj cepstrogramObj,int cepNum,float *dataArr,int dataLength, + float *mRealArr,float *mImageArr,int nLength, + float *mDataArr1,float *mDataArr2,float *mDataArr3); + +/*** + radix2Exp 12 + samplate 32000 + WindowType "rect" + slideLength 1024 +****/ +int cepstrogramObj_new(CepstrogramObj *cepstrogramObj,int radix2Exp, + WindowType *windowType,int *slideLength){ + int status=0; + CepstrogramObj ceps=NULL; + + STFTObj stftObj=NULL; + FFTObj fftObj=NULL; + + int fftLength=0; + + WindowType _windowType=Window_Rect; + int _slideLength=0; + + if(radix2Exp<1||radix2Exp>30){ + status=-100; + printf("radix2Exp is error!\n"); + return status; + } + + fftLength=1<0){ // &&*slideLength<=fftLength ->support not overlap + _slideLength=*slideLength; + } + } + + ceps=*cepstrogramObj=(CepstrogramObj )calloc(1, sizeof(struct OpaqueCepstrogram )); + + stftObj_new(&stftObj,radix2Exp,&_windowType,&_slideLength,NULL); + fftObj_new(&fftObj, radix2Exp); + + ceps->stftObj=stftObj; + ceps->fftObj=fftObj; + + ceps->fftLength=fftLength; + + ceps->radix2Exp=radix2Exp; + ceps->windowType=_windowType; + ceps->slideLength=_slideLength; + + return status; +} + +int cepstrogramObj_calTimeLength(CepstrogramObj cepstrogramObj,int dataLength){ + int timeLength=0; + + timeLength=stftObj_calTimeLength(cepstrogramObj->stftObj,dataLength); + return timeLength; +} + +void cepstrogramObj_cepstrogram(CepstrogramObj cepstrogramObj,int cepNum,float *dataArr,int dataLength, + float *mDataArr1,float *mDataArr2,float *mDataArr3){ + + __cepstrogramObj_spectrogram(cepstrogramObj,cepNum,dataArr,dataLength, + NULL,NULL,0, + mDataArr1,mDataArr2,mDataArr3); +} + +void cepstrogramObj_cepstrogram2(CepstrogramObj cepstrogramObj,int cepNum,float *mRealArr,float *mImageArr,int nLength, + float *mDataArr1,float *mDataArr2,float *mDataArr3){ + + __cepstrogramObj_spectrogram(cepstrogramObj,cepNum,NULL,0, + mRealArr,mImageArr,nLength, + mDataArr1,mDataArr2,mDataArr3); +} + +static void __cepstrogramObj_spectrogram(CepstrogramObj cepstrogramObj,int cepNum,float *dataArr,int dataLength, + float *mRealArr,float *mImageArr,int nLength, + float *mDataArr1,float *mDataArr2,float *mDataArr3){ + STFTObj stftObj=NULL; + FFTObj fftObj=NULL; + + int fftLength=0; // fftLength,timeLength,num + int timeLength=0; + + float *mYArr1=NULL; // ifft(log(S)) + float *mRealArr1=NULL; // stft r,i(timeLength*fftLength) + float *mImageArr1=NULL; + float *mSArr1=NULL; // power + + float *mYArr2=NULL; // envelope + float *mRealArr2=NULL; + float *mImageArr2=NULL; + + float *mYArr3=NULL; // details + float *mRealArr3=NULL; + float *mImageArr3=NULL; + + int sFlag=0; + + stftObj=cepstrogramObj->stftObj; + fftObj=cepstrogramObj->fftObj; + + fftLength=cepstrogramObj->fftLength; + + if(dataArr&&dataLength){ + sFlag=1; + } + + if(sFlag){ + timeLength=stftObj_calTimeLength(stftObj,dataLength); + } + else{ + timeLength=nLength; + } + + if(cepstrogramObj->timeLengthtimeLength>timeLength*2){ // 更新缓存 + free(cepstrogramObj->mYArr1); + free(cepstrogramObj->mRealArr1); + free(cepstrogramObj->mImageArr1); + free(cepstrogramObj->mSArr1); + + free(cepstrogramObj->mYArr2); + free(cepstrogramObj->mRealArr2); + free(cepstrogramObj->mImageArr2); + + free(cepstrogramObj->mYArr3); + free(cepstrogramObj->mRealArr3); + free(cepstrogramObj->mImageArr3); + + cepstrogramObj->mYArr1=__vnew(timeLength*fftLength, NULL); + cepstrogramObj->mRealArr1=__vnew(timeLength*fftLength, NULL); + cepstrogramObj->mImageArr1=__vnew(timeLength*fftLength, NULL); + cepstrogramObj->mSArr1=__vnew(timeLength*fftLength, NULL); + + cepstrogramObj->mYArr2=__vnew(timeLength*fftLength, NULL); + cepstrogramObj->mRealArr2=__vnew(timeLength*fftLength, NULL); + cepstrogramObj->mImageArr2=__vnew(timeLength*fftLength, NULL); + + cepstrogramObj->mYArr3=__vnew(timeLength*fftLength, NULL); + cepstrogramObj->mRealArr3=__vnew(timeLength*fftLength, NULL); + cepstrogramObj->mImageArr3=__vnew(timeLength*fftLength, NULL); + } + + mYArr1=cepstrogramObj->mYArr1; + mRealArr1=cepstrogramObj->mRealArr1; + mImageArr1=cepstrogramObj->mImageArr1; + mSArr1=cepstrogramObj->mSArr1; + + mYArr2=cepstrogramObj->mYArr2; + mRealArr2=cepstrogramObj->mRealArr2; + mImageArr2=cepstrogramObj->mImageArr2; + + mYArr3=cepstrogramObj->mYArr3; + mRealArr3=cepstrogramObj->mRealArr3; + mImageArr3=cepstrogramObj->mImageArr3; + + // 1. stft + if(sFlag){ + stftObj_stft(stftObj,dataArr,dataLength,mRealArr1,mImageArr1); + } + else{ + memcpy(mRealArr, mRealArr1, sizeof(float )*nLength*fftLength); + memcpy(mImageArr, mImageArr1, sizeof(float )*nLength*fftLength); + } + + // logf + __vcsquare(mRealArr1,mImageArr1,timeLength*fftLength,mSArr1); + for(int i=0;i mYArr1, mYArr1 is even + for(int i=0;iisDebug){ + printf("mDataArr1 is :\n"); + __mdebug(mDataArr1, timeLength, fftLength/2+1, 1); + printf("\n"); + } + } + + // 3. deconv + if(mDataArr2){ // envelope + for(int i=0;iisDebug){ + printf("mDataArr2 is :\n"); + __mdebug(mDataArr2, timeLength, fftLength/2+1, 1); + printf("\n"); + } + } + + if(mDataArr3){ // details + for(int i=0;iisDebug){ + printf("mDataArr3 is :\n"); + __mdebug(mDataArr3, timeLength, fftLength/2+1, 1); + printf("\n"); + } + } + + cepstrogramObj->timeLength=timeLength; +} + +void cepstrogramObj_enableDebug(CepstrogramObj cepstrogramObj,int flag){ + + cepstrogramObj->isDebug=flag; +} + +void cepstrogramObj_free(CepstrogramObj cepstrogramObj){ + STFTObj stftObj=NULL; + FFTObj fftObj=NULL; + + // stft + float *mYArr1=NULL; // ifft(log(S)) + float *mRealArr1=NULL; // stft r,i(timeLength*fftLength) + float *mImageArr1=NULL; + float *mSArr1=NULL; // power + + float *mYArr2=NULL; // envelope + float *mRealArr2=NULL; + float *mImageArr2=NULL; + + float *mYArr3=NULL; // details + float *mRealArr3=NULL; + float *mImageArr3=NULL; + + if(!cepstrogramObj){ + return; + } + + stftObj=cepstrogramObj->stftObj; + fftObj=cepstrogramObj->fftObj; + + mYArr1=cepstrogramObj->mYArr1; + mRealArr1=cepstrogramObj->mRealArr1; + mImageArr1=cepstrogramObj->mImageArr1; + mSArr1=cepstrogramObj->mSArr1; + + mYArr2=cepstrogramObj->mYArr2; + mRealArr2=cepstrogramObj->mRealArr2; + mImageArr2=cepstrogramObj->mImageArr2; + + mYArr3=cepstrogramObj->mYArr3; + mRealArr3=cepstrogramObj->mRealArr3; + mImageArr3=cepstrogramObj->mImageArr3; + + stftObj_free(stftObj); + fftObj_free(fftObj); + + free(mYArr1); + free(mRealArr1); + free(mImageArr1); + free(mSArr1); + + free(mYArr2); + free(mRealArr2); + free(mImageArr2); + + free(mYArr3); + free(mRealArr3); + free(mImageArr3); + + free(cepstrogramObj); +} + + + + + + + + + + diff --git a/src/cepstrogram_algorithm.h b/src/cepstrogram_algorithm.h new file mode 100644 index 0000000..41d88fc --- /dev/null +++ b/src/cepstrogram_algorithm.h @@ -0,0 +1,45 @@ + + +#ifndef CEPSTROGRAM_ALGORITHM_H +#define CEPSTROGRAM_ALGORITHM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "flux_base.h" + +typedef struct OpaqueCepstrogram *CepstrogramObj; + +/*** + radix2Exp 12 + WindowType "rect" + slideLength 1024 +****/ +int cepstrogramObj_new(CepstrogramObj *cepstrogramObj,int radix2Exp,WindowType *windowType,int *slideLength); + +int cepstrogramObj_calTimeLength(CepstrogramObj cepstrogramObj,int dataLength); + +/*** + cepNum 4~128 ,formant estimate number + mDataArr1 cepstrums ,timeLength*(fftLength/2+1) + mDataArr2 envelope(formant) ,timeLength*(fftLength/2+1) + mDataArr3 details(tone) ,timeLength*(fftLength/2+1) +****/ +void cepstrogramObj_cepstrogram(CepstrogramObj cepstrogramObj,int cepNum,float *dataArr,int dataLength, + float *mDataArr1,float *mDataArr2,float *mDataArr3); + +void cepstrogramObj_cepstrogram2(CepstrogramObj cepstrogramObj,int cepNum,float *mRealArr,float *mImageArr,int nLength, + float *mDataArr1,float *mDataArr2,float *mDataArr3); + +void cepstrogramObj_enableDebug(CepstrogramObj cepstrogramObj,int flag); + +void cepstrogramObj_free(CepstrogramObj cepstrogramObj); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/harmonic_algorithm.c b/src/harmonic_algorithm.c new file mode 100644 index 0000000..9ccc269 --- /dev/null +++ b/src/harmonic_algorithm.c @@ -0,0 +1,1037 @@ +// + +#include +#include + +#include "vector/flux_vector.h" +#include "vector/flux_vectorOp.h" +#include "vector/flux_complex.h" + +#include "util/flux_util.h" + +#include "dsp/flux_window.h" +#include "dsp/flux_correct.h" +#include "dsp/fft_algorithm.h" + +#include "stft_algorithm.h" + +#include "harmonic_algorithm.h" + +struct OpaqueHarmonic{ + int isContinue; + + STFTObj stftObj; + + int fftLength; + int slideLength; + + int peakLength; // (maxIndex-minIndex+1)/2+1 + + int minIndex; // min/maxFre + int maxIndex; + + int timeLength; + + // stft result ->timeLength*(maxIndex-minIndex+1) + float *mPowerArr; + float *mDbArr; + + // timeLength*peakLength + float *mPeakDbArr; + float *mPeakFreArr; + float *mPeakHeightArr; + int *mIndexArr; + int *lenArr; + + // filter ->timeLength*peakLength + float *mFilterDbArr1; // height-filter + float *mFilterFreArr1; + float *mFilterHeightArr1; + int *mIndexArr1; + int *lenArr1; + + float *mFilterDbArr2; // near-filter + float *mFilterFreArr2; + float *mFilterHeightArr2; + int *mIndexArr2; + int *lenArr2; + + float *mFilterDbArr3; // dB-filter + float *mFilterFreArr3; + float *mFilterHeightArr3; + int *mIndexArr3; + int *lenArr3; + + float *maxDBArr; // timeLength + + // cache + float *mRealArr; // timeLength*fftLength + float *mImageArr; + + int samplate; + WindowType winType; + + int isDebug; +}; + +static void __harmonicObj_dealData(HarmonicObj harmonicObj,int dataLength); + +static void __harmonicObj_stft(HarmonicObj harmonicObj,float *dataArr,int dataLength); + +static void __harmonicObj_filter(HarmonicObj harmonicObj); + +static void __harmonicObj_filterHeight(HarmonicObj harmonicObj); +static void __harmonicObj_filterNear(HarmonicObj harmonicObj); +static void __harmonicObj_filterDB(HarmonicObj harmonicObj); + +static int __arr_maxIndex(float *arr,int length); + +int harmonicObj_new(HarmonicObj *harmonicObj, + int *samplate, + int *radix2Exp,WindowType *windowType,int *slideLength){ + int status=0; + + int _samplate=32000; + + int _radix2Exp=12; + int _slideLength=0; + WindowType _winType=Window_Hamm; + + int fftLength=0; + int peakLength=0; + + int minIndex=0; // min/maxFre + int maxIndex=0; + + STFTObj stftObj=NULL; + HarmonicObj hr=NULL; + + hr=*harmonicObj=(HarmonicObj )calloc(1,sizeof(struct OpaqueHarmonic )); + + if(samplate){ + if(*samplate>0&&*samplate<=196000){ + _samplate=*samplate; + } + } + + if(radix2Exp){ + if(*radix2Exp>=1&&*radix2Exp<=30){ + _radix2Exp=*radix2Exp; + } + } + + if(windowType){ + if(*windowType<=Window_Hamm){ + _winType=*windowType; + } + } + + fftLength=1<<_radix2Exp; + _slideLength=fftLength/4; + if(slideLength){ + if(*slideLength>0){ // &&*slideLength<=fftLength support not overlap + _slideLength=*slideLength; + } + } + + maxIndex=fftLength/2-1; + peakLength=(maxIndex-minIndex)/2+1; + + stftObj_new(&stftObj, _radix2Exp, &_winType, &_slideLength, NULL); + + hr->stftObj=stftObj; + + hr->fftLength=fftLength; + hr->slideLength=_slideLength; + + hr->peakLength=peakLength; + + hr->minIndex=minIndex; + hr->maxIndex=maxIndex; + + hr->samplate=_samplate; + hr->winType=_winType; + + return status; +} + +int harmonicObj_calTimeLength(HarmonicObj harmonicObj,int dataLength){ + int timeLen=0; + + timeLen=stftObj_calTimeLength(harmonicObj->stftObj, dataLength); + return timeLen; +} + +void harmonicObj_exec(HarmonicObj harmonicObj,float *dataArr,int dataLength){ + // 1. dealData + __harmonicObj_dealData(harmonicObj,dataLength); + // 2. stft + __harmonicObj_stft(harmonicObj, dataArr, dataLength); + // 3. filter + __harmonicObj_filter(harmonicObj); +} + +void harmonicObj_harmonicCount(HarmonicObj harmonicObj,float low,float high,int *countArr){ + int timeLength=0; + int peakLength=0; + + float *mFilterDbArr3=NULL; // dB-filter + float *mFilterFreArr3=NULL; + float *mFilterHeightArr3=NULL; + int *mIndexArr3=NULL; + int *lenArr3=NULL; + + float *freArr=NULL; + int len3=0; + + mFilterDbArr3=harmonicObj->mFilterDbArr3; + mFilterFreArr3=harmonicObj->mFilterFreArr3; + mFilterHeightArr3=harmonicObj->mFilterHeightArr3; + mIndexArr3=harmonicObj->mIndexArr3; + lenArr3=harmonicObj->lenArr3; + + timeLength=harmonicObj->timeLength; + peakLength=harmonicObj->peakLength; + + for(int i=0;i=high){ + break; + } + + if(freArr[j]>low&&freArr[j]fftLength; + peakLength=harmonicObj->peakLength; + + minIndex=harmonicObj->minIndex; + maxIndex=harmonicObj->maxIndex; + + bLen=maxIndex-minIndex+1; + timeLen=stftObj_calTimeLength(harmonicObj->stftObj, dataLength); + if(harmonicObj->timeLengthtimeLength>timeLen*2){ + + free(harmonicObj->mPowerArr); + free(harmonicObj->mDbArr); + + free(harmonicObj->mPeakDbArr); + free(harmonicObj->mPeakFreArr); + free(harmonicObj->mPeakHeightArr); + free(harmonicObj->mIndexArr); + free(harmonicObj->lenArr); + + free(harmonicObj->mFilterDbArr1); + free(harmonicObj->mFilterFreArr1); + free(harmonicObj->mFilterHeightArr1); + free(harmonicObj->mIndexArr1); + free(harmonicObj->lenArr1); + + free(harmonicObj->mFilterDbArr2); + free(harmonicObj->mFilterFreArr2); + free(harmonicObj->mFilterHeightArr2); + free(harmonicObj->mIndexArr2); + free(harmonicObj->lenArr2); + + free(harmonicObj->mFilterDbArr3); + free(harmonicObj->mFilterFreArr3); + free(harmonicObj->mFilterHeightArr3); + free(harmonicObj->mIndexArr3); + free(harmonicObj->lenArr3); + + free(harmonicObj->maxDBArr); + + harmonicObj->mPowerArr=__vnew(timeLen*bLen, NULL); + harmonicObj->mDbArr=__vnew(timeLen*bLen, NULL); + + harmonicObj->mPeakDbArr=__vnew(timeLen*peakLength, NULL); + harmonicObj->mPeakFreArr=__vnew(timeLen*peakLength, NULL); + harmonicObj->mPeakHeightArr=__vnew(timeLen*peakLength, NULL); + harmonicObj->mIndexArr=__vnewi(timeLen*peakLength, NULL); + harmonicObj->lenArr=__vnewi(timeLen, NULL); + + harmonicObj->mFilterDbArr1=__vnew(timeLen*peakLength, NULL); + harmonicObj->mFilterFreArr1=__vnew(timeLen*peakLength, NULL); + harmonicObj->mFilterHeightArr1=__vnew(timeLen*peakLength, NULL); + harmonicObj->mIndexArr1=__vnewi(timeLen*peakLength, NULL); + harmonicObj->lenArr1=__vnewi(timeLen, NULL); + + harmonicObj->mFilterDbArr2=__vnew(timeLen*peakLength, NULL); + harmonicObj->mFilterFreArr2=__vnew(timeLen*peakLength, NULL); + harmonicObj->mFilterHeightArr2=__vnew(timeLen*peakLength, NULL); + harmonicObj->mIndexArr2=__vnewi(timeLen*peakLength, NULL); + harmonicObj->lenArr2=__vnewi(timeLen, NULL); + + harmonicObj->mFilterDbArr3=__vnew(timeLen*peakLength, NULL); + harmonicObj->mFilterFreArr3=__vnew(timeLen*peakLength, NULL); + harmonicObj->mFilterHeightArr3=__vnew(timeLen*peakLength, NULL); + harmonicObj->mIndexArr3=__vnewi(timeLen*peakLength, NULL); + harmonicObj->lenArr3=__vnewi(timeLen, NULL); + + harmonicObj->maxDBArr=__vnew(timeLen, NULL); + + harmonicObj->mRealArr=__vnew(timeLen*fftLength, NULL); + harmonicObj->mImageArr=__vnew(timeLen*fftLength, NULL); + } + + harmonicObj->timeLength=timeLen; +} + +static void __harmonicObj_stft(HarmonicObj harmonicObj,float *dataArr,int dataLength){ + STFTObj stftObj=NULL; + + int fftLength=0; + int slideLength=0; + int samplate=0; + + int peakLength=0; + + int minIndex=0; // min/maxFre + int maxIndex=0; + + int timeLength=0; + + // stft result ->->timeLength*(maxIndex-minIndex+1) + float *mPowerArr=NULL; + float *mDbArr=NULL; + + // timeLength*peakLength + float *mPeakDbArr=NULL; + float *mPeakFreArr=NULL; + float *mPeakHeightArr=NULL; + int *mIndexArr=NULL; + int *lenArr=NULL; + + float *maxDBArr=NULL; + + // cache + float *mRealArr=NULL; // timeLength*fftLength + float *mImageArr=NULL; + + int len=0; + int fLen=0; + int rLen=0; + + float pre=0; + float cur=0; + float nex=0; + + float left=0; + float right=0; + + float v1=0; + float v2=0; + + float minHeight=15; + float cutDB=-50; + + WindowType winType=Window_Rect; + void (*func)(float cur,float left,float right,float *det,float *value); + + stftObj=harmonicObj->stftObj; + + fftLength=harmonicObj->fftLength; + slideLength=harmonicObj->slideLength; + samplate=harmonicObj->samplate; + + peakLength=harmonicObj->peakLength; + + minIndex=harmonicObj->minIndex; + maxIndex=harmonicObj->maxIndex; + + timeLength=harmonicObj->timeLength; + + mPowerArr=harmonicObj->mPowerArr; + mDbArr=harmonicObj->mDbArr; + + mPeakDbArr=harmonicObj->mPeakDbArr; + mPeakFreArr=harmonicObj->mPeakFreArr; + mPeakHeightArr=harmonicObj->mPeakHeightArr; + mIndexArr=harmonicObj->mIndexArr; + lenArr=harmonicObj->lenArr; + + maxDBArr=harmonicObj->maxDBArr; + + mRealArr=harmonicObj->mRealArr; + mImageArr=harmonicObj->mImageArr; + + winType=harmonicObj->winType; + if(winType==Window_Hann){ + func=correct_hann; + } + else if(winType==Window_Hamm){ + func=correct_hamm; + } + else{ // rect + func=correct_rect; + } + + // 1. stft + stftObj_stft(stftObj, dataArr, dataLength, mRealArr, mImageArr); + + // 2. power&dB + rLen=maxIndex-minIndex+1; + for(int i=0;ipre&&cur>nex){ // peak + float scale=0; + + float _fre=0; + float _db=0; + + float _h1=0; + float _h2=0; + float _height=0; + + int _index=0; + + int xFlag=0; + int eFlag=0; + + // float _cur=0; + // float _pre=0; + // float _nex=0; + + // _cur=sqrtf(cur); + // _pre=sqrtf(pre); + // _nex=sqrtf(nex); + + // func(_cur,_pre,_nex,&scale,NULL); + + _index=j+1; + + /*** + _db ->j is matrix + _fre ->j+minIndex is fft'bin + ****/ + _fre=(j+minIndex+scale)/fftLength*samplate; + _db=mDbArr[i*rLen+j]; + + // dB + pre=mDbArr[i*rLen+j-1]; + cur=mDbArr[i*rLen+j]; + nex=mDbArr[i*rLen+j+1]; + + // left height + left=pre; + if(j-2>=0){ + left=mDbArr[i*rLen+j-2]; + + if(leftpre&&leftcutDB)){ + if(j-3>=0){ + pre=mDbArr[i*rLen+j-3]; + if(premDbArr[i*rLen+j-1]&& + mDbArr[i*rLen+j-2]=0&&_db-leftcutDB){ + if(mDbArr[i*rLen+j-4]nex&&rightcutDB)){ + if(j+3cutDB){ + if(mDbArr[i*rLen+j+4]minHeight&&xFlag&&_h1<_h2){ + mPeakDbArr[i*peakLength+len-1]=_db; + mPeakFreArr[i*peakLength+len-1]=_fre; + mPeakHeightArr[i*peakLength+len-1]=_height; + mIndexArr[i*peakLength+len-1]=j; + } + else{ + mPeakDbArr[i*peakLength+len]=_db; + mPeakFreArr[i*peakLength+len]=_fre; + mPeakHeightArr[i*peakLength+len]=_height; + mIndexArr[i*peakLength+len]=j; + + len++; + } + + j=_index; // update j + } + } + + lenArr[i]=len; + + // dB desc + __vcorrsort1(mPeakDbArr+i*peakLength, + mPeakFreArr+i*peakLength, + mPeakHeightArr+i*peakLength, + mIndexArr+i*peakLength, + len, 1); + + maxDBArr[i]=mPeakDbArr[i*peakLength]; + } +} + +static void __harmonicObj_filter(HarmonicObj harmonicObj){ + + __harmonicObj_filterHeight(harmonicObj); + __harmonicObj_filterNear(harmonicObj); + __harmonicObj_filterDB(harmonicObj); + +} + +static void __harmonicObj_filterHeight(HarmonicObj harmonicObj){ + int timeLength=0; + int peakLength=0; + + float *mPeakDbArr=NULL; + float *mPeakFreArr=NULL; + float *mPeakHeightArr=NULL; + int *mIndexArr=NULL; + int *lenArr=NULL; + + float *mFilterDbArr1=NULL; // height-filter + float *mFilterFreArr1=NULL; + float *mFilterHeightArr1=NULL; + int *mIndexArr1=NULL; + int *lenArr1=NULL; + + int len=0; + int len1=0; + + float minHeight=15; + + timeLength=harmonicObj->timeLength; + peakLength=harmonicObj->peakLength; + + mPeakDbArr=harmonicObj->mPeakDbArr; + mPeakFreArr=harmonicObj->mPeakFreArr; + mPeakHeightArr=harmonicObj->mPeakHeightArr; + mIndexArr=harmonicObj->mIndexArr; + lenArr=harmonicObj->lenArr; + + mFilterDbArr1=harmonicObj->mFilterDbArr1; + mFilterFreArr1=harmonicObj->mFilterFreArr1; + mFilterHeightArr1=harmonicObj->mFilterHeightArr1; + mIndexArr1=harmonicObj->mIndexArr1; + lenArr1=harmonicObj->lenArr1; + + for(int i=0;i=2){ + start=2; + len1=2; + } + else if(len>=1){ + start=1; + len1=1; + } + + for(int j=0;jstart~len1 + __vcorrsort1(mPeakFreArr+(i*peakLength+start), + mPeakDbArr+(i*peakLength+start), + mPeakHeightArr+(i*peakLength+start), + mIndexArr+(i*peakLength+start), + len-start, 0); + + for(int j=start;jminHeight){ + float curDb=0; + float preDb=0; + float nexDb=0; + + float preHeight=0; + float nexHeight=0; + + int curIndex=0; + int preIndex=0; + int nexIndex=0; + + curDb=mPeakDbArr[i*peakLength+j]; + preDb=mPeakDbArr[i*peakLength+j-1]; + nexDb=mPeakDbArr[i*peakLength+j+1]; + + preHeight=mPeakHeightArr[i*peakLength+j-1]; + nexHeight=mPeakHeightArr[i*peakLength+j+1]; + + curIndex=mIndexArr[i*peakLength+j]; + preIndex=mIndexArr[i*peakLength+j-1]; + nexIndex=mIndexArr[i*peakLength+j+1]; + + if(firstIndex){ + if(firstIndex>preIndex&&firstIndexpreIndex&&secondIndexcurIndex&&firstIndexcurIndex&&secondIndex12)||preHeight>minHeight)&& + ((curDb-nexDb>12)||nexHeight>minHeight)){ + + mFilterDbArr1[i*peakLength+len1]=mPeakDbArr[i*peakLength+j]; + mFilterFreArr1[i*peakLength+len1]=mPeakFreArr[i*peakLength+j]; + mFilterHeightArr1[i*peakLength+len1]=mPeakHeightArr[i*peakLength+j]; + mIndexArr1[i*peakLength+len1]=mIndexArr[i*peakLength+j]; + + len1++; + } + } + } + + lenArr1[i]=len1; + + // fre asc + __vcorrsort1(mPeakFreArr+i*peakLength, + mPeakDbArr+i*peakLength, + mPeakHeightArr+i*peakLength, + mIndexArr+i*peakLength, + len, 0); + + // fre asc + __vcorrsort1(mFilterFreArr1+i*peakLength, + mFilterDbArr1+i*peakLength, + mFilterHeightArr1+i*peakLength, + mIndexArr1+i*peakLength, + len1, 0); + } +} + +static void __harmonicObj_filterNear(HarmonicObj harmonicObj){ + int timeLength=0; + int peakLength=0; + + float *mFilterDbArr1=NULL; // height-filter + float *mFilterFreArr1=NULL; + float *mFilterHeightArr1=NULL; + int *mIndexArr1=NULL; + int *lenArr1=NULL; + + float *mFilterDbArr2=NULL; // near-filter + float *mFilterFreArr2=NULL; + float *mFilterHeightArr2=NULL; + int *mIndexArr2=NULL; + int *lenArr2=NULL; + + int len1=0; + int len2=0; + + float curDb=0; + float nexDb=0; + float nnDb=0; + + float curFre=0; + float nexFre=0; + float nnFre=0; + + int lastFlag=1; + + float minFre=30; + + timeLength=harmonicObj->timeLength; + peakLength=harmonicObj->peakLength; + + mFilterDbArr1=harmonicObj->mFilterDbArr1; + mFilterFreArr1=harmonicObj->mFilterFreArr1; + mFilterHeightArr1=harmonicObj->mFilterHeightArr1; + mIndexArr1=harmonicObj->mIndexArr1; + lenArr1=harmonicObj->lenArr1; + + mFilterDbArr2=harmonicObj->mFilterDbArr2; + mFilterFreArr2=harmonicObj->mFilterFreArr2; + mFilterHeightArr2=harmonicObj->mFilterHeightArr2; + mIndexArr2=harmonicObj->mIndexArr2; + lenArr2=harmonicObj->lenArr2; + + for(int i=0;innDb){ + j++; + } + } + } + + j++; + } + else if(nexFre-curFre<2*minFre){ // sub>15||<-70 + curDb=mFilterDbArr1[i*peakLength+j]; + nexDb=mFilterDbArr1[i*peakLength+j+1]; + } + + mFilterDbArr2[i*peakLength+len2]=mFilterDbArr1[i*peakLength+_index]; + mFilterFreArr2[i*peakLength+len2]=mFilterFreArr1[i*peakLength+_index]; + mFilterHeightArr2[i*peakLength+len2]=mFilterHeightArr1[i*peakLength+_index]; + mIndexArr2[i*peakLength+len2]=mIndexArr1[i*peakLength+_index]; + + len2++; + } + + if(lastFlag){ + mFilterDbArr2[i*peakLength+len2]=mFilterDbArr1[i*peakLength+len1-1]; + mFilterFreArr2[i*peakLength+len2]=mFilterFreArr1[i*peakLength+len1-1]; + mFilterHeightArr2[i*peakLength+len2]=mFilterHeightArr1[i*peakLength+len1-1]; + mIndexArr2[i*peakLength+len2]=mIndexArr1[i*peakLength+len1-1]; + + len2++; + } + + lenArr2[i]=len2; + } +} + +static void __harmonicObj_filterDB(HarmonicObj harmonicObj){ + int timeLength=0; + int peakLength=0; + + float *mFilterDbArr2=NULL; // near-filter + float *mFilterFreArr2=NULL; + float *mFilterHeightArr2=NULL; + int *mIndexArr2=NULL; + int *lenArr2=NULL; + + float *mFilterDbArr3=NULL; // dB-filter + float *mFilterFreArr3=NULL; + float *mFilterHeightArr3=NULL; + int *mIndexArr3=NULL; + int *lenArr3=NULL; + + int len2=0; + int len3=0; + + float *maxDBArr=NULL; + float maxDB=0; + + float minDB=15; // minDB + + timeLength=harmonicObj->timeLength; + peakLength=harmonicObj->peakLength; + + mFilterDbArr2=harmonicObj->mFilterDbArr2; + mFilterFreArr2=harmonicObj->mFilterFreArr2; + mFilterHeightArr2=harmonicObj->mFilterHeightArr2; + mIndexArr2=harmonicObj->mIndexArr2; + lenArr2=harmonicObj->lenArr2; + + mFilterDbArr3=harmonicObj->mFilterDbArr3; + mFilterFreArr3=harmonicObj->mFilterFreArr3; + mFilterHeightArr3=harmonicObj->mFilterHeightArr3; + mIndexArr3=harmonicObj->mIndexArr3; + lenArr3=harmonicObj->lenArr3; + + maxDBArr=harmonicObj->maxDBArr; + + for(int i=0;i len2->lne3 + for(int j=0;j-100){ + mFilterDbArr3[i*peakLength+len3]=mFilterDbArr2[i*peakLength+j]; + mFilterFreArr3[i*peakLength+len3]=mFilterFreArr2[i*peakLength+j]; + mFilterHeightArr3[i*peakLength+len3]=mFilterHeightArr2[i*peakLength+j]; + mIndexArr3[i*peakLength+len3]=mIndexArr2[i*peakLength+j]; + + len3++; + } + } + + // filter two continue >15 =>len3->len2 + { + float _db1=0; + float _db2=0; + float _db3=0; + float _db4=0; + + len2=0; + for(int j=0;jminDB&&_db1-_db3>minDB&& + _db4-_db2>minDB&&_db4-_db3>minDB){ // jump + + j=j+2; + } + } + // else if(j+2minDB&&_db1-_db3>minDB){ // last jump + + // j=j+1; + // } + // } + } + } + + // left -> first <15 => len2->len3 + len3=0; + _index=__arr_maxIndex(mFilterDbArr3+i*peakLength,len2); + for(int j=0;j<=_index;j++){ + + if(maxDB-mFilterDbArr3[i*peakLength+j]-42){ + + start=j; + + mFilterDbArr3[i*peakLength+len3]=mFilterDbArr3[i*peakLength+j]; + mFilterFreArr3[i*peakLength+len3]=mFilterFreArr3[i*peakLength+j]; + mFilterHeightArr3[i*peakLength+len3]=mFilterHeightArr3[i*peakLength+j]; + mIndexArr3[i*peakLength+len3]=mIndexArr3[i*peakLength+j]; + + len3++; + } + } + + // median -> relative near-filter, not cur dB-filter ??? + for(int j=start+1;j1&&startstftObj); + + free(harmonicObj->mPowerArr); + free(harmonicObj->mDbArr); + + free(harmonicObj->mPeakDbArr); + free(harmonicObj->mPeakFreArr); + free(harmonicObj->mPeakHeightArr); + free(harmonicObj->mIndexArr); + free(harmonicObj->lenArr); + + free(harmonicObj->mFilterDbArr1); + free(harmonicObj->mFilterFreArr1); + free(harmonicObj->mFilterHeightArr1); + free(harmonicObj->mIndexArr1); + free(harmonicObj->lenArr1); + + free(harmonicObj->mFilterDbArr2); + free(harmonicObj->mFilterFreArr2); + free(harmonicObj->mFilterHeightArr2); + free(harmonicObj->mIndexArr2); + free(harmonicObj->lenArr2); + + free(harmonicObj->mFilterDbArr3); + free(harmonicObj->mFilterFreArr3); + free(harmonicObj->mFilterHeightArr3); + free(harmonicObj->mIndexArr3); + free(harmonicObj->lenArr3); + + free(harmonicObj->maxDBArr); + + free(harmonicObj->mRealArr); + free(harmonicObj->mImageArr); + + free(harmonicObj); + } +} + +static int __arr_maxIndex(float *arr,int length){ + int index=0; + + float value=0; + + if(!length){ + return 0; + } + + value=arr[0]; + for(int i=1;i +#include +#include "flux_base.h" + +typedef struct OpaqueHarmonic *HarmonicObj; + +/*** + samplate 32000 + radix2Exp 12 + windowType hamm +****/ +int harmonicObj_new(HarmonicObj *harmonicObj, + int *samplate, + int *radix2Exp,WindowType *windowType,int *slideLength); + +int harmonicObj_calTimeLength(HarmonicObj harmonicObj,int dataLength); + +void harmonicObj_exec(HarmonicObj harmonicObj,float *dataArr,int dataLength); + +void harmonicObj_harmonicCount(HarmonicObj harmonicObj,float low,float high,int *countArr); + +void harmonicObj_free(HarmonicObj harmonicObj); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file