From e0c5d9b16d4dc20dd2fb189df4cc1deaa1931871 Mon Sep 17 00:00:00 2001 From: van Date: Wed, 17 Jan 2024 14:44:36 +0800 Subject: [PATCH 1/4] Update C header files. --- include/classic/nmf.h | 31 +++++++++++++++++++ include/classic/viterbi.h | 29 ++++++++++++++++++ include/dsp/conv_algorithm.h | 44 +++++++++++++++++++++++++++ include/dsp/hilbert_algorithm.h | 27 +++++++++++++++++ include/dsp/phase_vocoder.h | 26 ++++++++++++++++ include/dsp/resample_algorithm.h | 9 +++--- include/harmonic_algorithm.h | 37 +++++++++++++++++++++++ include/mir/_pitch_stft.h | 43 --------------------------- include/mir/_pitch_yin.h | 2 +- include/mir/pitchShift_algorithm.h | 33 +++++++++++++++++++++ include/mir/timeStretch_algorithm.h | 33 +++++++++++++++++++++ include/stft_algorithm.h | 46 +++++++++++++++++++++++++++++ include/util/flux_util.h | 26 ++++++++++++---- include/vector/flux_complex.h | 1 + include/vector/flux_vector.h | 12 +++++++- 15 files changed, 344 insertions(+), 55 deletions(-) create mode 100644 include/classic/nmf.h create mode 100644 include/classic/viterbi.h create mode 100644 include/dsp/conv_algorithm.h create mode 100644 include/dsp/hilbert_algorithm.h create mode 100644 include/dsp/phase_vocoder.h create mode 100644 include/harmonic_algorithm.h delete mode 100644 include/mir/_pitch_stft.h create mode 100644 include/mir/pitchShift_algorithm.h create mode 100644 include/mir/timeStretch_algorithm.h create mode 100644 include/stft_algorithm.h diff --git a/include/classic/nmf.h b/include/classic/nmf.h new file mode 100644 index 0000000..22961f0 --- /dev/null +++ b/include/classic/nmf.h @@ -0,0 +1,31 @@ + + +#ifndef NMF_H +#define NMF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/*** + V=W*H + k k +#include + +/*** + λ=(π,A,B) sLength*1,sLength*sLength,sLength*nLength + oArr B nLength index + mProbArr tLength*sLength + sArr A sLength index +****/ +float viterbi(float *piArr,float *mAArr,float *mBArr, + int sLength,int nLength, + int *oArr,int tLength,int *isLog, + int *sArr,float *mProbArr,int *mIndexArr); + + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/include/dsp/conv_algorithm.h b/include/dsp/conv_algorithm.h new file mode 100644 index 0000000..6047ed5 --- /dev/null +++ b/include/dsp/conv_algorithm.h @@ -0,0 +1,44 @@ + + +#ifndef CONV_ALGORITHM_H +#define CONV_ALGORITHM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "../flux_base.h" + +// convolution 相关 +typedef enum{ + ConvMode_Full=0, + ConvMode_Same, + ConvMode_Valid, + +} ConvModeType; + +typedef enum{ + ConvMethod_Auto=0, + ConvMethod_Direct, + ConvMethod_FFT, + +} ConvMethodType; + +typedef struct OpaqueConv *ConvObj; + +int convObj_new(ConvObj *convObj); + +int convObj_conv(ConvObj convObj,float *vArr1,int length1,float *vArr2,int length2, + ConvModeType *mode,ConvMethodType *method, + float *vArr3); + +void convObj_free(ConvObj convObj); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/dsp/hilbert_algorithm.h b/include/dsp/hilbert_algorithm.h new file mode 100644 index 0000000..e896cb4 --- /dev/null +++ b/include/dsp/hilbert_algorithm.h @@ -0,0 +1,27 @@ + + +#ifndef HILBERT_ALGORITHM_H +#define HILBERT_ALGORITHM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "../flux_base.h" + +typedef struct OpaqueHilbert *HilbertObj; + +int hilbertObj_new(HilbertObj *hilbertObj,int radix2Exp); + +void hilbertObj_hilbert(HilbertObj hilbertObj,float *dataArr, + float *realArr3,float *imageArr3); + +void hilbertObj_free(HilbertObj hilbertObj); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/include/dsp/phase_vocoder.h b/include/dsp/phase_vocoder.h new file mode 100644 index 0000000..759323c --- /dev/null +++ b/include/dsp/phase_vocoder.h @@ -0,0 +1,26 @@ + + +#ifndef PHASE_VOCODER_H +#define PHASE_VOCODER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/*** + mDataArr1 stft time*fftLength + rate 0.5~2 + slideLength fftLength/4 +****/ +void phase_vocoder(float *mRealArr1,float *mImageArr1,int timeLength,int fftLength,int slideLength,float rate, + float *mRealArr2,float *mImageArr2); + + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/include/dsp/resample_algorithm.h b/include/dsp/resample_algorithm.h index e5498f0..afcf368 100644 --- a/include/dsp/resample_algorithm.h +++ b/include/dsp/resample_algorithm.h @@ -31,11 +31,11 @@ typedef struct OpaqueResample *ResampleObj; int resampleObj_new(ResampleObj *resampleObj,ResampleQualityType *qualType,int *isScale,int *isContinue); /*** sinc right - zeroNum 64 一般16/32/64 - nbit 9 一般5~9 每个zero-cross 1< +#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 diff --git a/include/mir/_pitch_stft.h b/include/mir/_pitch_stft.h deleted file mode 100644 index 0a9ed29..0000000 --- a/include/mir/_pitch_stft.h +++ /dev/null @@ -1,43 +0,0 @@ - - -#ifndef _PITCH_STFT_H -#define _PITCH_STFT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include "../flux_base.h" - -typedef struct OpaquePitchSTFT *PitchSTFTObj; - -/*** - samplate 32000 - radix2Exp 12 - WindowType hamm - slideLength (1<0&&thresh<1 +// default 0.6 thresh>0&&thresh<1 void pitchYINObj_setThresh(PitchYINObj pitchYINObj,float thresh); int pitchYINObj_calTimeLength(PitchYINObj pitchYINObj,int dataLength); diff --git a/include/mir/pitchShift_algorithm.h b/include/mir/pitchShift_algorithm.h new file mode 100644 index 0000000..b75c953 --- /dev/null +++ b/include/mir/pitchShift_algorithm.h @@ -0,0 +1,33 @@ + + +#ifndef PITCHSHIFT_ALGORITHM_H +#define PITCHSHIFT_ALGORITHM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "../flux_base.h" + +typedef struct OpaquePitchShift *PitchShiftObj; + +/*** + radix2Exp 12 + WindowType hann + slideLength (1< +#include + +#include "../flux_base.h" + +typedef struct OpaqueTimeStretch *TimeStretchObj; + +/*** + radix2Exp 12 + WindowType hann + slideLength (1< +#include +#include "flux_base.h" + +typedef struct OpaqueSTFT *STFTObj; + +int stftObj_new(STFTObj *stftObj,int radix2Exp,WindowType *windowType,int *slideLength,int *isContinue); + +void stftObj_setSlideLength(STFTObj stftObj,int slideLength); +// value1 => constant/left +void stftObj_setPadding(STFTObj stftObj, + PaddingPositionType *positionType,PaddingModeType *modeType, + float *value1,float *value2); + +void stftObj_useWindowDataArr(STFTObj stftObj,float *winDataArr); +float *stftObj_getWindowDataArr(STFTObj stftObj); + +// center zero padding +void stftObj_enablePadding(STFTObj stftObj,int flag); +void stftObj_enableContinue(STFTObj stftObj,int flag); + +// set/enable后执行 +int stftObj_calTimeLength(STFTObj stftObj,int dataLength); +int stftObj_calDataLength(STFTObj stftObj,int timeLength); + +void stftObj_stft(STFTObj stftObj,float *dataArr,int dataLength,float *mRealArr,float *mImageArr); +// type 0(deault) 'weight overlap-add' 1 'overlap-add' +void stftObj_istft(STFTObj stftObj,float *mRealArr,float *mImageArr,int nLength,int type,float *dataArr); + +void stftObj_free(STFTObj stftObj); +void stftObj_debug(STFTObj stftObj); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/include/util/flux_util.h b/include/util/flux_util.h index d16e4f7..1fb1868 100644 --- a/include/util/flux_util.h +++ b/include/util/flux_util.h @@ -10,7 +10,7 @@ extern "C" { #include #include -// 2^n相关 +// 2^n int util_isPowerTwo(int value); int util_ceilPowerTwo(int value); int util_floorPowerTwo(int value); @@ -19,17 +19,25 @@ int util_roundPowerTwo(int value); // value=2^n =>n int util_powerTwoBit(int value); -// 最大公约数 a>b +// a>b greatest common divisor int util_gcd(int a,int b); -// fre相关 +// fre float util_midiToFre(int midi); int util_freToMidi(float fre); int util_midiTimes(int midi1,int midi2); int util_freTimes(float fre1,float fre2); int util_freToSimularMidi(float fre); -int util_freTimes1(float fre1,float fre2); +float util_freToMidiRange(float fre,int *midi1,int *midi2); + +// tone +void util_calTone(float value,float *value1,float *value2); +int util_calToneTimes(float value1,float value2,int *type); +int util_calFreTimes(float value1,float value2,int *type); + +int util_calRangeTimes(float value1,float value2,int *type); +int util_calApproTimes(float value1,float value2,int *type); // scale void util_minMaxScale(float *vArr1,int length,float *vArr2); @@ -41,7 +49,7 @@ void util_centerScale(float *vArr1,int length,float *vArr2); void util_meanScale(float *vArr1,int length,float *vArr2); void util_arctanScale(float *vArr1,int length,float *vArr2); -// 向量归一化 type 0 p 1/2/3... 1 Inf 2 -Inf +// vector norm type 0 p 1/2/3... 1 Inf 2 -Inf void util_normalize(float *vArr1,int length,int type,float p,float *vArr2); // mag/power/DB min=-80 @@ -54,6 +62,9 @@ void util_magToAbsDB(float *pArr,int length,int fftLength,int isNorm,float min,f void util_logCompress(float *vArr1,float *gamma,int length,float *vArr2); void util_log10Compress(float *vArr1,float *gamma,int length,float *vArr2); +// temproal, return maxDb, percent is < -base +float util_temproal(float *dataArr,int length,float base,float *avgDb,float *percent); + // gamma eps=1e-5 float util_gamma(float x,float *eps); long double util_gammal(long double x,long double *eps); @@ -61,13 +72,16 @@ long double util_gammal(long double x,long double *eps); // quadratically interpolated return p ∈[-1/2,1/2] float util_qaudInterp(float value1,float value2,float value3,float *outValue); +// peak pick +void util_peakPick(float *pArr,int length,int start,int end,int distance,int num,float *vArr,int *cArr); + // order must odd; delta/deltaDelta void util_delta(float *dataArr1,int length,int order,float *dataArr2); // pre_emphasis; coef 0.97 void util_preEmphasis(float *vArr1,int length,float coef,float *vArr2); -// wave相关 +// wave int util_readWave(char *name,float **dataArr); void util_writeWave(char *name,float *dataArr,int length); diff --git a/include/vector/flux_complex.h b/include/vector/flux_complex.h index e65ea32..526cfef 100644 --- a/include/vector/flux_complex.h +++ b/include/vector/flux_complex.h @@ -65,6 +65,7 @@ void __vcp2z(float *rArr,float *tArr,int length,float *realArr,float *imageArr); // arg/abs/conj void __vcarg(float *realArr1,float *imageArr1,int length,float *vArr1); +void __vcangle(float *realArr1,float *imageArr1,int length,float *vArr1); void __vcabs(float *realArr1,float *imageArr1,int length,float *vArr1); void __vcsquare(float *realArr1,float *imageArr1,int length,float *vArr1); void __vcconj(float *realArr1,float *imageArr1,int length,float *realArr3,float *imageArr3); diff --git a/include/vector/flux_vector.h b/include/vector/flux_vector.h index eef15d4..3482c4a 100644 --- a/include/vector/flux_vector.h +++ b/include/vector/flux_vector.h @@ -146,10 +146,19 @@ float __vzcr(float *vArr1,int length); void __vunwrap(float *vArr1,int length,float *vArr2); -// type 0 升 1降 +// type 0 asc 1 desc void __vsort(float *vArr1,int length,int type,float *vArr2); void __vsorti(int *vArr1,int length,int type,int *vArr2); +void __vcorrsort(float *vArr1,float *vArr2,float *vArr3,int length,int type); +void __vcorrsort1(float *vArr1,float *vArr2,float *vArr3,int *vArr4,int length,int type); + +int __vindex(float *vArr1,int length,float value); +int __vindexi(int *vArr1,int length,int value); + +int __vhas(float *vArr1,int length,float value); +int __vhasi(int *vArr1,int length,int value); + // univers function op void __vmap(float *vArr1,int length,void *callback,float *vArr2); void __vmap1(float *vArr1,int length,void *callback1,float value,float *vArr2); @@ -159,6 +168,7 @@ float *__vnew(int length,float *value); int *__vnewi(int length,int *value); float *__vlinspace(float start,float stop,int length,int type); +float *__vlogspace(float start,float stop,int length,int type); int __varange(float start,float stop,float step,float **outArr); int __varangei(int start,int stop,int step,int **outArr); From 44b4231a2e110f934da4444a8cafda6548452977 Mon Sep 17 00:00:00 2001 From: van Date: Wed, 17 Jan 2024 15:43:11 +0800 Subject: [PATCH 2/4] Fix resample algorithm bug, add support arbitrary sampling ratios. --- src/dsp/resample_algorithm.c | 87 +++++++++++++++++++++++++----------- src/dsp/resample_algorithm.h | 9 ++-- 2 files changed, 66 insertions(+), 30 deletions(-) diff --git a/src/dsp/resample_algorithm.c b/src/dsp/resample_algorithm.c index 117b98c..ab61789 100644 --- a/src/dsp/resample_algorithm.c +++ b/src/dsp/resample_algorithm.c @@ -37,8 +37,8 @@ struct OpaqueResample{ int sourceDataLength; int targetDataLength; - // continue==1 缓存相关 - float *tailDataArr; // 最小公倍数 + // continue==1 cache + float *tailDataArr; // gcd int tailDataLength; }; @@ -51,8 +51,8 @@ static float *_resampleObj_dealData(ResampleObj resampleObj,float *dataArr1,int static void _resampleObj_resample(ResampleObj resampleObj,float *dataArr1,float *dataArr2); /*** - qualType beat 使用kaiser - Beat zeroNum 64 nbit 9 beta 14.7697 roll-off 0.9476 + qualType beat, use kaiser + Best zeroNum 64 nbit 9 beta 14.7697 roll-off 0.9476 Mid zeroNum 32 nbit 9 beta 11.6626 roll-off 0.8988 Fast zeroNum 16 nbit 9 beta 8.5555 roll-off 0.85 ****/ @@ -61,13 +61,13 @@ int resampleObj_new(ResampleObj *resampleObj,ResampleQualityType *qualType,int * ResampleQualityType _qualType=ResampleQuality_Best; - int zeroNum=64; - int nbit=9; + int zeroNum=64; // 64 ->50 + int nbit=9; // 9 ->13 WindowType winType=Window_Kaiser; - float value=14.7696565; + float value=14.7696565; // 14.7696565 ->12.9846 - float rollOff=0.9475937; + float rollOff=0.9475937; // 0.9475937 ->0.917347 if(qualType){ _qualType=*qualType; @@ -77,11 +77,13 @@ int resampleObj_new(ResampleObj *resampleObj,ResampleQualityType *qualType,int * zeroNum=32; value=11.6625806; rollOff=0.8987969; + nbit=9; } else if(_qualType==ResampleQuality_Fast){ zeroNum=16; value=8.5555046; rollOff=0.85; + nbit=9; } status=resampleObj_newWithWindow(resampleObj, @@ -96,11 +98,11 @@ int resampleObj_new(ResampleObj *resampleObj,ResampleQualityType *qualType,int * /*** sinc right - zeroNum 64 一般16/32/64 - nbit 9 一般5~9 每个zero-cross 1<sourceRate=32000; resObj->targetRate=16000; - // 2. 计算interpArr + // 2. cal interpArr _resampleObj_calInterpArr(resObj); - // 3. 计算interpDeltaArr + // 3. cal interpDeltaArr resObj->interpDeltaArr=__vnew(interpLength, NULL); _resampleObj_calInterpDeltaArr(resObj); @@ -209,7 +211,7 @@ int resampleObj_newWithWindow(ResampleObj *resampleObj, } /*** - continue 0 默认 + continue 0 sourceDataLength=dataLength conttinue 1 sourceDataLength=dataLength-dataLength%q @@ -235,7 +237,7 @@ int resampleObj_calDataLength(ResampleObj resampleObj,int dataLength){ targetDataLength=floorf(dataLength*ratio); } else{ - if(q>1){ // 存在down + if(q>1){ // down sourceDataLength=dataLength-dataLength%q; targetDataLength=sourceDataLength*p/q; } @@ -277,15 +279,15 @@ void resampleObj_setSamplate(ResampleObj resampleObj,int sourceRate,int targetRa ratio=targetRate/(float )sourceRate; if(ratio!=resampleObj->ratio&& - (resampleObj->ratio<1||ratio<1)){ // 不相同 满足条件 更新interpArr/interpDeltaArr - // 1. 恢复 + (resampleObj->ratio<1||ratio<1)){ // update interpArr/interpDeltaArr + // 1. restore if(resampleObj->ratio<1){ for(int i=0;iratio; } } - // 2. 更新ratio interpDeltaArr + // 2. update ratio interpDeltaArr resampleObj->ratio=ratio; _resampleObj_calInterpDeltaArr(resampleObj); } @@ -298,9 +300,40 @@ void resampleObj_setSamplate(ResampleObj resampleObj,int sourceRate,int targetRa resampleObj->q=q; } +void resampleObj_setSamplateRatio(ResampleObj resampleObj,float ratio){ + float *interpArr=NULL; + int interpLength=0; + + if(ratio<0){ + return; + } + + interpArr=resampleObj->interpArr; + interpLength=resampleObj->interpLength; + + if(ratio!=resampleObj->ratio&& + (resampleObj->ratio<1||ratio<1)){ // update interpArr/interpDeltaArr + // 1. restore + if(resampleObj->ratio<1){ + for(int i=0;iratio; + } + } + + // 2. update ratio interpDeltaArr + resampleObj->ratio=ratio; + _resampleObj_calInterpDeltaArr(resampleObj); + } + + resampleObj->ratio=ratio; + + resampleObj->p=0; + resampleObj->q=0; +} + void resampleObj_enableContinue(ResampleObj resampleObj,int flag){ - if(!flag){ // 非实时切换 + if(!flag){ // not real-time change resampleObj->tailDataLength=0; } resampleObj->isContinue=flag; @@ -325,7 +358,7 @@ int resampleObj_resample(ResampleObj resampleObj,float *dataArr1,int dataLength1 // 1. dealData dealArr=_resampleObj_dealData(resampleObj,dataArr1,dataLength1); - if(dealArr){ // 存在 + if(dealArr){ curArr=dealArr; length1=dataLength1+resampleObj->tailDataLength; } @@ -341,7 +374,7 @@ int resampleObj_resample(ResampleObj resampleObj,float *dataArr1,int dataLength1 _resampleObj_resample(resampleObj,curArr,dataArr2); // 4. tailData - if(resampleObj->isContinue&&dealArr){ // 实时 + if(resampleObj->isContinue&&dealArr){ // real-time tailDataLength=length1-resampleObj->sourceDataLength; for(int i=0;itailDataArr[i]=dealArr[resampleObj->sourceDataLength+i]; @@ -447,6 +480,7 @@ static void _resampleObj_resample(ResampleObj resampleObj,float *dataArr1,float int _value1=0; int _value2=0; + t=i*1.0/ratio; n=floorf(t); // 1. left cal @@ -481,7 +515,8 @@ static void _resampleObj_resample(ResampleObj resampleObj,float *dataArr1,float } // 3. update t - t+=1.0/ratio; + // t+=1.0/ratio; + } } @@ -532,7 +567,7 @@ static void _resampleObj_calInterpArr(ResampleObj resampleObj){ type=Window_Hann; } - // 1. sinc计算 + // 1. sinc interpArr=__vlinspace(0, zeroNum, interpLength, 0); // == __vsinc_low for(int i=0;i Date: Wed, 17 Jan 2024 15:45:06 +0800 Subject: [PATCH 3/4] Fix wave bug. --- src/util/flux_wave.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/util/flux_wave.c b/src/util/flux_wave.c index 07dda06..5e5bcf2 100644 --- a/src/util/flux_wave.c +++ b/src/util/flux_wave.c @@ -66,6 +66,9 @@ char __wav_header[44]={ 0x00, 0x00, 0x00, 0x00 }; +static int __readChunkSize(FILE *file); +static void __readChunkName(FILE *file); + int waveReadObj_new(WaveReadObj *waveObj,char *fileName){ int status=0; WaveReadObj wave=NULL; @@ -76,8 +79,10 @@ int waveReadObj_new(WaveReadObj *waveObj,char *fileName){ unsigned int offset=0; unsigned int dataSize=0; + char *chunkName=NULL; + wave=*waveObj=(WaveReadObj )calloc(1, sizeof(struct OpaqueWaveRead )); - fp=fopen(fileName, "rb+"); + fp=fopen(fileName, "rb"); fread(&header, 1, sizeof(header), fp); if(header.fmtSize<16){ @@ -92,6 +97,24 @@ int waveReadObj_new(WaveReadObj *waveObj,char *fileName){ // printf("format is %d\n",header.format); offset=20+header.fmtSize+4; // ??? + fseek(fp, offset, SEEK_SET); + + // LIST + chunkName=(char *)calloc(5, sizeof(char )); + strncpy(chunkName,header.data,4); + while(strncmp(chunkName, "data", 4)){ + int skipSize=0; + + fread(&skipSize, 1, sizeof(int ), fp); + offset+=4; + + offset+=skipSize; + fseek(fp, offset, SEEK_SET); + fread(chunkName, 4, sizeof(char ), fp); + + offset+=4; + } + fseek(fp, offset, SEEK_SET); fread(&dataSize, 1, sizeof(unsigned int ), fp); @@ -105,6 +128,7 @@ int waveReadObj_new(WaveReadObj *waveObj,char *fileName){ wave->dataLength=dataSize/(header.bit/ 8); + free(chunkName); return status; } @@ -215,7 +239,7 @@ int waveWriteObj_new(WaveWriteObj *waveObj,char *fileName, int _channelNum=1; wave=*waveObj=(WaveWriteObj )calloc(1, sizeof(struct OpaqueWaveWrite )); - fp=fopen(fileName, "wb+"); + fp=fopen(fileName, "wb"); if(samplate){ if(*samplate>0&&*samplate<=196000){ From 4ad4df4d04c627dd7487f01039f5d36772ba5298 Mon Sep 17 00:00:00 2001 From: van Date: Wed, 17 Jan 2024 15:47:18 +0800 Subject: [PATCH 4/4] Add phase_vocoder, timeStretch and pitchShift algorithm. --- src/dsp/phase_vocoder.c | 129 ++++++++++++++++++++++++ src/dsp/phase_vocoder.h | 26 +++++ src/mir/pitchShift_algorithm.c | 99 ++++++++++++++++++ src/mir/pitchShift_algorithm.h | 33 ++++++ src/mir/timeStretch_algorithm.c | 173 ++++++++++++++++++++++++++++++++ src/mir/timeStretch_algorithm.h | 33 ++++++ src/vector/flux_complex.c | 15 +++ src/vector/flux_complex.h | 1 + 8 files changed, 509 insertions(+) create mode 100644 src/dsp/phase_vocoder.c create mode 100644 src/dsp/phase_vocoder.h create mode 100644 src/mir/pitchShift_algorithm.c create mode 100644 src/mir/pitchShift_algorithm.h create mode 100644 src/mir/timeStretch_algorithm.c create mode 100644 src/mir/timeStretch_algorithm.h diff --git a/src/dsp/phase_vocoder.c b/src/dsp/phase_vocoder.c new file mode 100644 index 0000000..cd4a569 --- /dev/null +++ b/src/dsp/phase_vocoder.c @@ -0,0 +1,129 @@ +// + +#include +#include +#include +#include + +#include "../vector/flux_vector.h" +#include "../vector/flux_vectorOp.h" +#include "../vector/flux_complex.h" + +#include "phase_vocoder.h" + +/*** + mDataArr1 stft time*fftLength + rate 0.5~2 + slideLength fftLength/4 +****/ +void phase_vocoder(float *mRealArr1,float *mImageArr1,int nLength,int mLength,int slideLength,float rate, + float *mRealArr2,float *mImageArr2){ + float *timeArr=NULL; + float *phiArr=NULL; + float *phaseArr=NULL; + + float *arr1=NULL; + float *arr2=NULL; + + float *arr3=NULL; + float *arr4=NULL; + + int tLen=0; + int fLen=0; + + fLen=mLength/2+1; + tLen=ceilf(nLength/rate); + __varange(0,nLength,rate,&timeArr); + + phiArr=__vlinspace(0, M_PI*slideLength, fLen, 0); + + phaseArr=__vnew(fLen, NULL); + __vcangle(mRealArr1,mImageArr1,fLen,phaseArr); + + arr1=__vnew(fLen, NULL); + arr2=__vnew(fLen, NULL); + + arr3=__vnew(fLen, NULL); + arr4=__vnew(fLen, NULL); + for(int i=0;i +#include + +/*** + mDataArr1 stft time*fftLength + rate 0.5~2 + slideLength fftLength/4 +****/ +void phase_vocoder(float *mRealArr1,float *mImageArr1,int timeLength,int fftLength,int slideLength,float rate, + float *mRealArr2,float *mImageArr2); + + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/mir/pitchShift_algorithm.c b/src/mir/pitchShift_algorithm.c new file mode 100644 index 0000000..f092e0d --- /dev/null +++ b/src/mir/pitchShift_algorithm.c @@ -0,0 +1,99 @@ +// + +#include +#include + +#include "../vector/flux_vector.h" +#include "../vector/flux_vectorOp.h" + +#include "../util/flux_util.h" +#include "../dsp/resample_algorithm.h" + +#include "timeStretch_algorithm.h" +#include "pitchShift_algorithm.h" + +struct OpaquePitchShift{ + TimeStretchObj timeStretchObj; + ResampleObj resampleObj; + + + +}; + +/*** + radix2Exp 12 + WindowType hann + slideLength (1<timeStretchObj=timeStretchObj; + ps->resampleObj=resampleObj; + + return status; +} + +// nSemitone -12~12 +void pitchShiftObj_pitchShift(PitchShiftObj pitchShiftObj,int samplate,int nSemitone,float *dataArr1,int dataLength1,float *dataArr2){ + float rate=0; + int samplate2=0; + + float *_dataArr=NULL; + int capacity=0; + int dataLength2=0; + + if(nSemitone>12||nSemitone<-12){ + return ; + } + + rate=powf(2, -nSemitone*1.0/12); + samplate2=roundf(samplate/rate); + + capacity=timeStretchObj_calDataCapacity(pitchShiftObj->timeStretchObj,rate,dataLength1); + _dataArr=__vnew(capacity, NULL); + + // 1. timeStretch + dataLength2=timeStretchObj_timeStretch(pitchShiftObj->timeStretchObj,rate,dataArr1,dataLength1,_dataArr); + + // 2. resample + // resampleObj_setSamplate(pitchShiftObj->resampleObj,samplate2,samplate); + resampleObj_setSamplateRatio(pitchShiftObj->resampleObj,rate); + resampleObj_resample(pitchShiftObj->resampleObj,_dataArr,dataLength2,dataArr2); + + + free(_dataArr); +} + +void pitchShiftObj__free(PitchShiftObj pitchShiftObj){ + + if(pitchShiftObj){ + timeStretchObj_free(pitchShiftObj->timeStretchObj); + resampleObj_free(pitchShiftObj->resampleObj); + + free(pitchShiftObj); + } +} + + + + + + + + + + diff --git a/src/mir/pitchShift_algorithm.h b/src/mir/pitchShift_algorithm.h new file mode 100644 index 0000000..b75c953 --- /dev/null +++ b/src/mir/pitchShift_algorithm.h @@ -0,0 +1,33 @@ + + +#ifndef PITCHSHIFT_ALGORITHM_H +#define PITCHSHIFT_ALGORITHM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "../flux_base.h" + +typedef struct OpaquePitchShift *PitchShiftObj; + +/*** + radix2Exp 12 + WindowType hann + slideLength (1< +#include + +#include "../vector/flux_vector.h" +#include "../vector/flux_vectorOp.h" + +#include "../util/flux_util.h" +#include "../dsp/phase_vocoder.h" +#include "../stft_algorithm.h" + +#include "timeStretch_algorithm.h" + +struct OpaqueTimeStretch{ + STFTObj stftObj; + + int radix2Exp; + int fftLength; + int slideLength; + WindowType windowType; + + int timeLength1; + int timeLength2; + + float *mRealArr1; // timeLength1 + float *mImageArr1; + + float *mRealArr2; // timeLength2 + float *mImageArr2; + +}; + +int timeStretchObj_new(TimeStretchObj *timeStretchObj,int *radix2Exp,int *slideLength,WindowType *windowType){ + int status=0; + + int fftLength=0; + int _radix2Exp=12; + int _slideLength=0; + WindowType _windowType=Window_Hann; + + STFTObj stftObj=NULL; + TimeStretchObj ts=NULL; + + ts=*timeStretchObj=(TimeStretchObj )calloc(1,sizeof(struct OpaqueTimeStretch )); + + 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; + } + } + + if(windowType){ + _windowType=*windowType; + } + + stftObj_new(&stftObj, _radix2Exp, &_windowType, &_slideLength, NULL); + + ts->stftObj=stftObj; + + ts->radix2Exp=_radix2Exp; + ts->fftLength=fftLength; + ts->slideLength=_slideLength; + ts->windowType=_windowType; + + return status; +} + +int timeStretchObj_calDataCapacity(TimeStretchObj timeStretchObj,float rate,int dataLength){ + + return ceilf(dataLength/rate)+timeStretchObj->fftLength; +} + +int timeStretchObj_timeStretch(TimeStretchObj timeStretchObj,float rate,float *dataArr1,int dataLength,float *dataArr2){ + int timeLength1=0; + int timeLength2=0; + + int fftLength=0; + int slideLength=0; + + float *mRealArr1=NULL; // timeLength1 + float *mImageArr1=NULL; + + float *mRealArr2=NULL; // timeLength2 + float *mImageArr2=NULL; + + if(rate<0){ + return 0; + } + + fftLength=timeStretchObj->fftLength; + slideLength=timeStretchObj->slideLength; + + timeLength1=stftObj_calTimeLength(timeStretchObj->stftObj, dataLength); + timeLength2=ceilf(timeLength1/rate); + + mRealArr1=timeStretchObj->mRealArr1; + mImageArr1=timeStretchObj->mImageArr1; + + mRealArr2=timeStretchObj->mRealArr2; + mImageArr2=timeStretchObj->mImageArr2; + + if(timeStretchObj->timeLength1timeLength1>timeLength1*2){ + free(mRealArr1); + free(mImageArr1); + + mRealArr1=__vnew(timeLength1*fftLength, NULL); + mImageArr1=__vnew(timeLength1*fftLength, NULL); + + timeStretchObj->timeLength1=timeLength1; + + timeStretchObj->mRealArr1=mRealArr1; + timeStretchObj->mImageArr1=mImageArr1; + } + + if(timeStretchObj->timeLength2timeLength2>timeLength2*2){ + free(mRealArr2); + free(mImageArr2); + + mRealArr2=__vnew(timeLength2*fftLength, NULL); + mImageArr2=__vnew(timeLength2*fftLength, NULL); + + timeStretchObj->timeLength2=timeLength2; + + timeStretchObj->mRealArr2=mRealArr2; + timeStretchObj->mImageArr2=mImageArr2; + } + + // 1. stft + stftObj_stft(timeStretchObj->stftObj, dataArr1, dataLength, mRealArr1, mImageArr1); + + // 2. phase vocoder + phase_vocoder(mRealArr1,mImageArr1,timeLength1,fftLength,slideLength,rate,mRealArr2,mImageArr2); + + // 3. istft + stftObj_istft(timeStretchObj->stftObj, mRealArr2, mImageArr2, timeLength2, 0, dataArr2); + + return roundf(dataLength/rate); +} + +void timeStretchObj_free(TimeStretchObj timeStretchObj){ + + if(timeStretchObj){ + stftObj_free(timeStretchObj->stftObj); + + free(timeStretchObj->mRealArr1); + free(timeStretchObj->mImageArr1); + + free(timeStretchObj->mRealArr2); + free(timeStretchObj->mImageArr2); + + free(timeStretchObj); + } +} + + + + + + + + + diff --git a/src/mir/timeStretch_algorithm.h b/src/mir/timeStretch_algorithm.h new file mode 100644 index 0000000..e6bdbaf --- /dev/null +++ b/src/mir/timeStretch_algorithm.h @@ -0,0 +1,33 @@ + + +#ifndef TIMESTRETCH_ALGORITHM_H +#define TIMESTRETCH_ALGORITHM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "../flux_base.h" + +typedef struct OpaqueTimeStretch *TimeStretchObj; + +/*** + radix2Exp 12 + WindowType hann + slideLength (1<