├── .DS_Store ├── BF0NLS_CPP ├── .DS_Store ├── lib │ ├── Makefile │ ├── README │ └── single_pitch.so ├── main │ ├── .DS_Store │ ├── Makefile │ ├── Readme │ ├── fastNLS │ ├── fastNLS.cpp │ ├── fastNLS.dSYM │ │ └── Contents │ │ │ ├── Info.plist │ │ │ └── Resources │ │ │ └── DWARF │ │ │ └── fastNLS │ ├── test_in.h5 │ ├── test_out.dat │ └── wb2ext.wav └── src │ ├── single_pitch.cpp │ ├── single_pitch.hpp │ ├── th.cpp │ ├── th.hpp │ ├── tools.cpp │ ├── tools.hpp │ ├── vector.cpp │ └── vector.hpp ├── BF0NLS_MATLAB ├── .DS_Store ├── BayesianfastF0NLS.m ├── CleanSpeech.wav ├── factoryNoise.mat ├── private │ ├── BF0NLS.m │ ├── addnoise.m │ ├── computeAllCostFunctions.m │ ├── computeComplexHarmonicDfts.m │ ├── computeComplexHarmonicDftsTest.m │ ├── computeGamma.m │ ├── computeGammaMultipleSinus.m │ ├── computeGammaSingleSinus.m │ ├── computeGammaTwoSinus.m │ ├── computeLogMarginalLikelihood.m │ ├── computePitchLogLikelihood.m │ ├── computePostModelPmf.m │ ├── computeRowsOfToeplitzHankelMatrix.m │ ├── dynamicRangeLimiting.m │ ├── estnoiseg_orig.m │ ├── generator.m │ ├── goldenSectionSearch.m │ ├── objFunction.m │ └── singlePitchNLSCostsNaive.m ├── run_colored_example.m ├── run_music_example.m ├── run_white_example.m └── vib_flute.wav ├── BF0NLS_realtimeDemo_MATLAB ├── .DS_Store ├── BayesianfastF0NLS.m ├── PitchTraking.m ├── SX36.wav ├── babble.mat ├── estnoiseg.m ├── f16.mat ├── factory2.mat ├── gustWind.mat ├── howlWind.mat ├── hypergeometric2F1ODE.m ├── leopard.mat ├── m109.mat ├── main.m ├── offlineprocessData_MMSE.m ├── pink.mat ├── private │ ├── computeAllCostFunctions.m │ ├── computeComplexHarmonicDfts.m │ ├── computeComplexHarmonicDftsTest.m │ ├── computeGamma.m │ ├── computeGammaMultipleSinus.m │ ├── computeGammaSingleSinus.m │ ├── computeGammaTwoSinus.m │ ├── computeLogMarginalLikelihood.m │ ├── computePitchLogLikelihood.m │ ├── computePostModelPmf.m │ ├── computeRowsOfToeplitzHankelMatrix.m │ ├── generator.m │ ├── goldenSectionSearch.m │ ├── listdlg2.m │ ├── objFunction.m │ ├── offlineprocessData.m │ ├── offlineprocessData_orig.m │ ├── processData.m │ ├── processData_orig.m │ └── singlePitchNLSCostsNaive.m ├── processData_MMSE.m ├── sAudioRealTimeRecord.m ├── wb2ext.wav └── white.mat ├── LICENSE ├── README.md └── figures ├── .DS_Store ├── 1111.png ├── 2222.png └── 3333.png /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/.DS_Store -------------------------------------------------------------------------------- /BF0NLS_CPP/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_CPP/.DS_Store -------------------------------------------------------------------------------- /BF0NLS_CPP/lib/Makefile: -------------------------------------------------------------------------------- 1 | # Optional - but remove link option -DMKL 2 | MKLROOT = /opt/intel 3 | 4 | #Dynamic linking 5 | MKL = -m64 -I$(MKLROOT)/mkl/include -I$(MKLROOT)/mkl/include/fftw -L$(MKLROOT)/mkl/lib/intel64 -L$(MKLROOT)/compilers_and_libraries/linux/lib/intel64_lin -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -lm -DALIGNMENT32 6 | 7 | #FTYPE = -DDOUBLE -DREGULARIZE 8 | FTYPE = -DDOUBLE 9 | #LINK = -DMKL $(MKL) -DALIGNMENT32 -DCHEBYSHEV 10 | LINK = -lfftw3 -DCHEBYSHEV 11 | 12 | 13 | all: 14 | g++ -O3 -march=native -fPIC --shared -Wl,-soname,single_pitch.so -Wno-write-strings -DLIB $(FTYPE) ../src/single_pitch.cpp ../src/tools.cpp ../src/th.cpp ../src/vector.cpp $(LINK) -pthread -o single_pitch.so 15 | -------------------------------------------------------------------------------- /BF0NLS_CPP/lib/README: -------------------------------------------------------------------------------- 1 | Compiles a library of the fast single pitch method 2 | 3 | Additional packages: 4 | Either MKL or FFTW 5 | 6 | FFW3 7 | apt-get install libfftw3-3 libfftw3-dev 8 | 9 | MKL: 10 | Download MKL: https://software.intel.com/en-us/mkl 11 | 12 | Makefile 13 | Set optional MKL 14 | 15 | Select one of the following LINK options 16 | 17 | - Use MKL for FFTs and vector operations and a recursive Chebyshev method 18 | for computing sinusoidal vectors 19 | 20 | LINK = -DMKL $(MKL) -DCHEBYSHEV 21 | 22 | - Use MKL for FFTs and vector operations 23 | 24 | LINK = -DMKL $(MKL) 25 | 26 | - Use FFTW3 for FFTs and direct for-loop implementation of vector-operations. 27 | 28 | LINK = -lfftw3 29 | 30 | with -DREGULARIZE the system is regularized with eps = 1e-8 -------------------------------------------------------------------------------- /BF0NLS_CPP/lib/single_pitch.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_CPP/lib/single_pitch.so -------------------------------------------------------------------------------- /BF0NLS_CPP/main/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_CPP/main/.DS_Store -------------------------------------------------------------------------------- /BF0NLS_CPP/main/Makefile: -------------------------------------------------------------------------------- 1 | # Mandatory 2 | #GTEST = /usr/lib/ 3 | #HDF5 = /usr/lib/x86_64-linux-gnu/hdf5/serial 4 | 5 | 6 | PATH_TO_GTEST=/usr/local 7 | PATH_TO_FFTW3=/usr/local/Cellar/fftw/3.3.8_1 8 | PATH_TO_HDF5=/usr/local/Cellar/hdf5/1.10.5_1 9 | # PATH_TO_eigen=/usr/local/Cellar/eigen/3.3.7 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | PATH_TO_GTEST_h= -I$(PATH_TO_GTEST)/include/eigen3 18 | PATH_TO_FFTW3_h=-I$(PATH_TO_FFTW3)/include 19 | PATH_TO_HDF5_h=-I$(PATH_TO_HDF5)/include 20 | # PATH_TO_eigen_h= -I$(PATH_TO_GTEST)/include 21 | 22 | PATH_TO_GTEST_lib= -L$(PATH_TO_GTEST)/lib 23 | PATH_TO_FFTW3_lib=-L$(PATH_TO_FFTW3)/lib 24 | PATH_TO_HDF5_lib=-L$(PATH_TO_HDF5)/lib 25 | 26 | 27 | 28 | 29 | 30 | # EXTLIB2=-L$(fftwlib) 31 | # EXTLIB = -L$(HDF5) 32 | # INCLUDE = -I$(HDF5)/include 33 | # INCLUDE2 = -I$(GTESTinclude)/include 34 | # LIBSHDF = $(EXTLIB) -lhdf5_hl -lhdf5 -lz 35 | 36 | # Optional - but remove link option -DMKL 37 | # MKLROOT = /opt/intel 38 | #Dynamic linking 39 | # MKL = -m64 -I$(MKLROOT)/mkl/include -I$(MKLROOT)/mkl/include/fftw -L$(MKLROOT)/mkl/lib/intel64 -L$(MKLROOT)/compilers_and_libraries/linux/lib/intel64_lin -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -lm -DALIGNMENT32 40 | 41 | FTYPE = -DDOUBLE 42 | 43 | #LINK = -DMKL $(MKL) -DCHEBYSHEV 44 | #LINK = -DMKL $(MKL) 45 | # LINK = $(EXTLIB2) -lfftw3 -DCHEBYSHEV 46 | 47 | all: 48 | # g++ -g -fno-inline -Wno-write-strings $(FTYPE) $(INCLUDE) $(INCLUDE2) ../src/single_pitch.cpp ../src/tools.cpp ../src/th.cpp ../src/vector.cpp fastNLS.cpp $(GTEST)/libgtest.a $(LIBSHDF) $(LINK) -pthread -o fastNLS 49 | g++ -g -fno-inline -Wno-write-strings $(FTYPE) $(PATH_TO_GTEST_h) $(PATH_TO_FFTW3_h) $(PATH_TO_HDF5_h) ../src/single_pitch.cpp ../src/tools.cpp ../src/th.cpp ../src/vector.cpp fastNLS.cpp $(PATH_TO_GTEST_lib) -lgtest $(PATH_TO_FFTW3_lib) -lfftw3 -DCHEBYSHEV $(PATH_TO_HDF5_lib) -lhdf5_hl -lhdf5 -lz -pthread -o fastNLS 50 | 51 | -------------------------------------------------------------------------------- /BF0NLS_CPP/main/Readme: -------------------------------------------------------------------------------- 1 | Mandatory: 2 | Googletest 3 | HDF5 dev 4 | and FFTW 5 | 6 | Googletest: 7 | Get and compile googletest from https://github.com/google/googletest 8 | 9 | HDF5: 10 | Get and install: Using Ubuntu 11 | apt-get install libhdf5-dev 12 | 13 | FFW3 14 | apt-get install libfftw3-3 libfftw3-dev -------------------------------------------------------------------------------- /BF0NLS_CPP/main/fastNLS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_CPP/main/fastNLS -------------------------------------------------------------------------------- /BF0NLS_CPP/main/fastNLS.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "hdf5.h" 6 | #include "hdf5_hl.h" 7 | #include "../src/tools.hpp" 8 | #include "gtest/gtest.h" 9 | //#include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "../src/single_pitch.hpp" 17 | 18 | #ifdef DOUBLE 19 | #define EPS 1e-10 // pure floating 20 | #define EPS2 1e-8 //iterative algs 21 | #else 22 | #define EPS 1e-1 23 | #define EPS2 1e-1 24 | #endif 25 | 26 | 27 | 28 | double* readInput(char *filename, int *numSample, int *fs) 29 | { 30 | hid_t file; 31 | herr_t status; 32 | file = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT); 33 | double *nData=vector(1); 34 | H5LTread_dataset(file, "/DL1", H5T_NATIVE_DOUBLE, nData); 35 | *numSample=nData[0]; 36 | 37 | double * x = vector(*numSample); 38 | H5LTread_dataset(file, "/DS1", H5T_NATIVE_DOUBLE, x); 39 | 40 | double *sr=vector(1); 41 | H5LTread_dataset(file, "/SR1", H5T_NATIVE_DOUBLE, sr); 42 | *fs=sr[0]; 43 | 44 | status = H5Fclose(file); 45 | 46 | double sumE=0; 47 | for( int ii = 1 ; ii <= nData[0] ; ++ii){ 48 | sumE += (x[ii-1])*(x[ii-1]); 49 | } 50 | sumE = sqrt(sumE/nData[0]); 51 | double scale = sqrt(3.1623e-5)/sumE; // scale to -45-dB loudness level 52 | // double scale=1; 53 | 54 | for (int ii = 1 ; ii <= nData[0] ; ++ii) 55 | x[ii-1] = scale*x[ii-1]; 56 | return x; 57 | 58 | } 59 | 60 | 61 | void process(char *filename, char *out_put_filename) 62 | { 63 | int sigLength; int F; 64 | 65 | double *x=readInput(filename, &sigLength, &F); 66 | 67 | 68 | 69 | 70 | 71 | 72 | int N = (int) round(25*F/1000/2)*2; 73 | 74 | int L = (int) 10; 75 | 76 | int shift_vaue= (int) round(10*F/1000); 77 | // zero padding 78 | x=x-N/2;sigLength=sigLength+N/2; 79 | int nData = sigLength; 80 | for (int ii =0; iiest_fast(xp); 128 | 129 | 130 | myfile1 << (ii-1)*10/1000.0; 131 | myfile1 << " "; 132 | 133 | myfile1 << omega_0h[0]*F/2.0/M_PI; 134 | myfile1 << " "; 135 | myfile1 << omega_0h[1]; 136 | myfile1 << " "; 137 | myfile1 << omega_0h[2]; 138 | 139 | myfile1 << " "; 140 | if (omega_0h[2]>0.5) 141 | { 142 | myfile1 << omega_0h[0]*F/2.0/M_PI; 143 | } 144 | else 145 | { 146 | myfile1 << 0.0/0.0; 147 | } 148 | myfile1 << " "; 149 | 150 | if (omega_0h[2]>0.5) 151 | { 152 | myfile1 << omega_0h[1]; 153 | } 154 | else 155 | { 156 | myfile1 << 0.0/0.0; 157 | } 158 | 159 | myfile1 << "\n"; 160 | 161 | x=x+shift_vaue; 162 | } 163 | myfile1.close(); 164 | delete sp; 165 | } 166 | 167 | int main(int argc, char **argv){ 168 | if (argc!=3) 169 | { 170 | printf("Usage: fastNLS input output\n"); 171 | return 1; 172 | } 173 | // int F=0; 174 | // 175 | // 176 | // char *s= argv[1]; 177 | // 178 | // sscanf(s, "%d", &F); 179 | 180 | // int F=argv[1];; 181 | char *filename=argv[1]; 182 | char *outfn=argv[2]; 183 | 184 | 185 | process(filename,outfn); 186 | 187 | return 0; 188 | 189 | } 190 | 191 | -------------------------------------------------------------------------------- /BF0NLS_CPP/main/fastNLS.dSYM/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleIdentifier 8 | com.apple.xcode.dsym.fastNLS 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundlePackageType 12 | dSYM 13 | CFBundleSignature 14 | ???? 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleVersion 18 | 1 19 | 20 | 21 | -------------------------------------------------------------------------------- /BF0NLS_CPP/main/fastNLS.dSYM/Contents/Resources/DWARF/fastNLS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_CPP/main/fastNLS.dSYM/Contents/Resources/DWARF/fastNLS -------------------------------------------------------------------------------- /BF0NLS_CPP/main/test_in.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_CPP/main/test_in.h5 -------------------------------------------------------------------------------- /BF0NLS_CPP/main/wb2ext.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_CPP/main/wb2ext.wav -------------------------------------------------------------------------------- /BF0NLS_CPP/src/single_pitch.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __SINGLE_PITCH_H__ 2 | #define __SINGLE_PITCH_H__ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #ifdef MKL 11 | #include "fftw3.h" 12 | #else 13 | #include 14 | #endif 15 | 16 | #include "tools.hpp" 17 | #include "th.hpp" 18 | #include "vector.hpp" 19 | //#include 20 | //#include 21 | 22 | #ifdef REGULARIZE 23 | #define T0_REG 1e-8 24 | #else 25 | #define T0_REG 0.0 26 | #endif 27 | 28 | #define DIM int 29 | 30 | //using namespace Eigen; 31 | 32 | class single_pitch{ 33 | public: 34 | single_pitch(int maxModelOrder, int nData, 35 | FTYPE * pitchBounds, double trans_std_var,FTYPE voicing_prob); 36 | 37 | ~single_pitch(); 38 | 39 | void compute(FTYPE * x); 40 | void update_gamma(int iOrder, int nPitches, int nPitchesOld, 41 | int nPitchesOldOld, FTYPE * phi, 42 | FTYPE * psi, FTYPE * alpha, FTYPE * lambda, 43 | FTYPE * mu, FTYPE * Gamma); 44 | 45 | void update_gamma_p(int iOrder, int nPitches, int nPitchesOld, 46 | int nPitchesOldOld, FTYPE * alpha, FTYPE * Gamma); 47 | 48 | void update_ls_sol(int iOrder, int nPitches, int nPitchesOld, 49 | bool add, FTYPE * dftData, 50 | FTYPE * Gamma, FTYPE * lsSol); 51 | 52 | void compute_cc(); 53 | 54 | // added by Liming Shi 55 | inline double squared(double x); 56 | double normpdf(double x, double u, double s); 57 | double log_sum_exp(double arr[], int count); 58 | double log_sumsum_exp(FTYPE **arr, int row_num,int col_num, double A_num); 59 | // double ramp(double x); 60 | double norm_prob(FTYPE **arr, int row_num,int col_num, double A_num,double scale_par); 61 | int norm_prob2(FTYPE **arr, int row_num, int col_num, double scale_par,FTYPE **arrtarget); 62 | double log_sum(double arr[], int count); 63 | double sum_vec(double arr[], int count); 64 | // 65 | 66 | FTYPE compute_obj(FTYPE omega, FTYPE * x, int iOrder); 67 | FTYPE compute_obj(FTYPE omega, FTYPE * x, int iOrder, FTYPE * ac, FTYPE * as); 68 | 69 | FTYPE * refine(FTYPE * x); 70 | FTYPE * refine(FTYPE * x, FTYPE eps); 71 | FTYPE refine_single(FTYPE *x, int iOrder, FTYPE eps); 72 | void compute_max_on_grid(void); 73 | 74 | FTYPE golden(FTYPE * x, int iOrder, FTYPE omega_L, FTYPE omega_U, FTYPE eps); 75 | 76 | // int model_order_selection(); 77 | int model_order_selection(); 78 | 79 | FTYPE est(FTYPE * x); 80 | FTYPE est(FTYPE * x, FTYPE lnBFZeroOrder, FTYPE eps); 81 | FTYPE * est_fast(FTYPE * x); 82 | 83 | FTYPE max_obj(int iOrder); 84 | FTYPE argmax_obj(int iOrder); 85 | 86 | FTYPE * Gamma1; 87 | FTYPE * Gamma2; 88 | FTYPE ** costFunctionMatrix; 89 | FTYPE * omega_0h; 90 | FTYPE * lnBF; 91 | 92 | int nPitches(int iOrder){ return nPitchesAll[iOrder-1];}; 93 | int modelOrder(){return estOrder;}; 94 | 95 | private: 96 | 97 | int maxFftIndexOld; 98 | //int M, N, L, F; 99 | int maxModelOrder, nData, nFftGrid; 100 | int estOrder; 101 | 102 | int t; 103 | int k; 104 | int M; 105 | int Mp; 106 | int minFftIndex; 107 | 108 | FTYPE pitchBounds[2]; 109 | 110 | int * nPitchesAll; 111 | 112 | FTYPE ** crossCorrelationVectors; 113 | FTYPE ** tf; 114 | FTYPE ** hf; 115 | 116 | FTYPE * dftData1; 117 | FTYPE * dftData2; 118 | FTYPE * x; 119 | FTYPE * y; 120 | FTYPE * yt; 121 | 122 | FTYPE * t1; 123 | FTYPE * t2; 124 | FTYPE * t3; 125 | FTYPE * t4; 126 | FTYPE * tp; 127 | 128 | FTYPE * fftShiftVector; 129 | FTYPE * lsSol1; 130 | FTYPE * lsSol2; 131 | 132 | FTYPE * range; 133 | 134 | FTYPE * xp; 135 | FTYPE * dftData; 136 | FFTW_PLAN p1; 137 | // added by Liming Shi 138 | FTYPE * logpi; 139 | FTYPE ** A; 140 | FTYPE ** B; 141 | FTYPE ** C; 142 | FTYPE * temp_normalization; 143 | FTYPE ** scaled_alpha_buffer; 144 | FTYPE ** scaled_alpha_buffer2; 145 | FTYPE unvoicing_scaled_alpha_buffer; 146 | FTYPE ** bar_alpha; 147 | FTYPE unvoicing_scaled_alpha; 148 | // FTYPE bar_alpha; 149 | FTYPE * state_prior; 150 | FTYPE * logModelPrior; 151 | FTYPE * returned_value; 152 | }; 153 | 154 | 155 | #ifdef LIB 156 | // The class is wrapped using these C-style functions 157 | extern "C"{ 158 | 159 | single_pitch * single_pitch_new(int maxModelOrder, int nFftGrid, 160 | int nData, FTYPE * pitchBounds){ 161 | return new single_pitch(maxModelOrder, nFftGrid, 162 | nData, pitchBounds); 163 | } 164 | 165 | FTYPE single_pitch_est(single_pitch * sp, FTYPE * x, FTYPE lnBFZeroOrder, FTYPE eps){ 166 | return sp->est(x, lnBFZeroOrder, eps); 167 | } 168 | 169 | FTYPE single_pitch_est_fast(single_pitch * sp, FTYPE * x, FTYPE lnBFZeroOrder, FTYPE eps){ 170 | return sp->est_fast(x, lnBFZeroOrder, eps); 171 | } 172 | 173 | void single_pitch_del(single_pitch * sp){delete sp;} 174 | 175 | int single_pitch_model_order(single_pitch * sp){return sp->modelOrder();} 176 | } 177 | #endif 178 | 179 | #endif 180 | -------------------------------------------------------------------------------- /BF0NLS_CPP/src/th.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Methods for computing the solution to a linear system with coefficient matrix 3 | 4 | R = T + H 5 | 6 | where T is symmetric Toeplitz and H is Hankel 7 | 8 | Based on: 9 | 10 | I. Gohberg and I. Koltracht 11 | Efficient Algorithms for Toeplitz Plus Hankel Matrices 12 | Integral Equations and Operator Theory 13 | Vol. 12 14 | 1989 15 | 16 | Tobias L. Jensen 17 | March 2015 18 | */ 19 | #include "th.hpp" 20 | 21 | 22 | void solve(int N, FTYPE *t, FTYPE *h, FTYPE *f, FTYPE *gam, FTYPE *x){ 23 | FTYPE *tp, *t1, lambda_k, zero = 0.0, *gamma; 24 | int K = ((N+2)*(N+1))/2; 25 | 26 | tp = vector(N+1); 27 | t1 = vector(N+1); 28 | 29 | if(gam==NULL){ 30 | gamma = vector(K); 31 | th(N, t, h, gamma); 32 | } 33 | else 34 | gamma = gam; 35 | 36 | 37 | CvmdReverse(N+1, t, tp); 38 | CvmdInit(N+1, zero, x); 39 | 40 | x[0] = f[0]/(t[0] + h[0]); 41 | 42 | for(int k = 1 ; k < N+1 ; ++k){ 43 | CvmdAdd(k, tp+N-k, h+k, t1); 44 | lambda_k = f[k] - CvmdDot(k, t1, x); 45 | 46 | /* x[:k+1] += lambda_k*gamma[k] */ 47 | CvmdAxpy(k+1, lambda_k, gamma+((k+1)*k)/2, x); 48 | } 49 | 50 | del_vector(tp); 51 | del_vector(t1); 52 | 53 | if(gam == NULL) 54 | del_vector(gamma); 55 | } 56 | 57 | 58 | void th(int N, FTYPE *t, FTYPE *h, FTYPE *gamma){ 59 | 60 | FTYPE *a, *tp, *alpha, *phi_k, *psi_k, *t1, *r_kp1, *b_k; 61 | FTYPE zero = 0.0, R00, R01, R11, s, lambda_k, mu_k, nu_kp1, gammap; 62 | int K, Kp1; 63 | 64 | // test two special cases 65 | if( N == 0 ){ 66 | R00 = t[0] + h[0]; 67 | gamma[0] = 1/R00; 68 | return; 69 | } 70 | if( N == 1 ){ 71 | R00 = t[0] + h[0]; 72 | R01 = t[1] + h[1]; 73 | R11 = t[0] + h[2]; 74 | 75 | gamma[0] = 1/R00; 76 | 77 | s = 1/(R00*R11 - R01*R01); 78 | gamma[1] = -s*R01; 79 | gamma[2] = s*R00; 80 | return; 81 | } 82 | 83 | /* allocate */ 84 | a= vector(N); 85 | tp = vector(N+1); 86 | alpha = vector(N+1); 87 | phi_k = vector(N+1); 88 | psi_k = vector(N+1); 89 | t1 = vector(N+1); 90 | r_kp1 = vector(N+1); 91 | b_k = vector(N+1); 92 | 93 | CvmdShift(N, t+1, h, a); 94 | CvmdReverse(N+1, t, tp); 95 | 96 | CvmdInit(N+1, zero, phi_k); 97 | CvmdInit(N+1, zero, psi_k); 98 | CvmdInit(N+1, zero, alpha); 99 | 100 | R00 = t[0] + h[0]; 101 | R01 = t[1] + h[1]; 102 | R11 = t[0] + h[2]; 103 | psi_k[0] = 1/R00; 104 | 105 | gamma[0] = 1/R00; 106 | phi_k[0] = a[0]/R00; 107 | alpha[1] = R01/R00; 108 | 109 | s = 1/(R00*R11 - R01*R01); 110 | gamma[1] = -s*R01; 111 | gamma[2] = s*R00; 112 | 113 | Kp1 = 1; 114 | 115 | for(int k = 1 ; k < N ; ++k){ 116 | 117 | K = Kp1; 118 | Kp1 = (k+2)*(k+1)/2; 119 | 120 | /* lambda_k = a[k] - np.dot(tp[N-k:N]+h[k:2*k], phi_k[:k]) */ 121 | CvmdAdd(k, tp+N-k, h+k, t1); 122 | lambda_k = a[k] - CvmdDot(k, t1, phi_k); 123 | 124 | /* mu_k = - np.dot(tp[N-k:N]+h[k:2*k], psi_k[:k]) */ 125 | mu_k = -CvmdDot(k, t1, psi_k); 126 | 127 | /* phi_k[:k+1] += lambda_k*gamma[k] */ 128 | CvmdAxpy(k+1, lambda_k, gamma+K, phi_k); 129 | 130 | /* psi_k[:k+1] += mu_k*gamma[k] */ 131 | CvmdAxpy(k+1, mu_k, gamma+K, psi_k); 132 | 133 | /*r_kp1 = tp[N-k-1:N] + h[k+1:2*k+2]*/ 134 | CvmdAdd(k+1, tp + N - k - 1, h + k + 1, r_kp1); 135 | 136 | /* alpha[k+1] = np.dot(tp[N-k-1:N]+h[k+1:2*(k+1)], gamma[k]) */ 137 | alpha[k+1] = CvmdDot(k+1, r_kp1, gamma + K); 138 | 139 | /* b_k = ((alpha[k] - alpha[k+1])*gamma[k] + np.hstack([0, gamma[k][:k]]) 140 | + np.hstack([gamma[k][1:k+1], 0]) 141 | -np.hstack([gamma[k-1], 0]) 142 | + psi_k[k]*phi_k[:k+1] - phi_k[k]*psi_k[:k+1]) */ 143 | CvmdInit(k+1, 0.0, b_k); 144 | CvmdAxpy(k+1, alpha[k]-alpha[k+1], gamma + K, b_k); 145 | CvmdAxpy(k, 1.0, gamma + K, b_k + 1); 146 | CvmdAxpy(k, 1.0, gamma + K + 1, b_k); 147 | CvmdAxpy(k, -1.0, gamma + ((k)*(k-1))/2, b_k); 148 | CvmdAxpy(k, psi_k[k], phi_k, b_k); 149 | CvmdAxpy(k, -phi_k[k], psi_k, b_k); 150 | 151 | /* nu_kp1 = (1/gamma[k][k]) * np.dot(tp[N-k-1:N]+h[k+1:2*(k+1)], b_k) */ 152 | nu_kp1 = (1/gamma[K + k]) 153 | * CvmdDot(k+1, r_kp1, b_k); 154 | 155 | gammap = 1.0/(nu_kp1 + tp[N] + h[2*k+2]); 156 | 157 | /* gamma.append(np.hstack([(gammap/gamma[k][k])*b_k, gammap])) */ 158 | CvmdScal(k+1, gammap/gamma[K + k], b_k); 159 | CvmdCopy(k+1, b_k, gamma + Kp1); 160 | gamma[Kp1 + k + 1] = gammap; 161 | } 162 | 163 | /* de-allocate */ 164 | del_vector(a); 165 | del_vector(tp); 166 | del_vector(alpha); 167 | del_vector(phi_k); 168 | del_vector(psi_k); 169 | del_vector(t1); 170 | del_vector(r_kp1); 171 | del_vector(b_k); 172 | } 173 | 174 | 175 | void thp(int N, FTYPE *t, FTYPE *h, FTYPE *gamma){ 176 | 177 | FTYPE *tp, *alpha, *r_kp1, *b_k; 178 | FTYPE zero = 0.0, R00, R01, R11, s, nu_kp1, gammap; 179 | int K, Kp1; 180 | 181 | // test two special cases 182 | if( N == 0 ){ 183 | R00 = t[0] + h[0]; 184 | gamma[0] = 1/R00; 185 | return; 186 | } 187 | if( N == 1 ){ 188 | R00 = t[0] + h[0]; 189 | R01 = t[1] + h[1]; 190 | R11 = t[0] + h[2]; 191 | 192 | gamma[0] = 1/R00; 193 | 194 | s = 1/(R00*R11 - R01*R01); 195 | gamma[1] = -s*R01; 196 | gamma[2] = s*R00; 197 | return; 198 | } 199 | 200 | 201 | /* allocate */ 202 | tp = vector(N+1); 203 | alpha = vector(N+1); 204 | r_kp1 = vector(N+1); 205 | b_k = vector(N+1); 206 | 207 | CvmdReverse(N+1, t, tp); 208 | 209 | CvmdInit(N+1, zero, alpha); 210 | 211 | R00 = t[0] + h[0]; 212 | R01 = t[1] + h[1]; 213 | R11 = t[0] + h[2]; 214 | 215 | gamma[0] = 1/R00; 216 | alpha[1] = R01/R00; 217 | 218 | s = 1/(R00*R11 - R01*R01); 219 | gamma[1] = -s*R01; 220 | gamma[2] = s*R00; 221 | 222 | Kp1 = 1; 223 | 224 | for(int k = 1 ; k < N ; ++k){ 225 | 226 | K = Kp1; 227 | Kp1 = (k+2)*(k+1)/2; 228 | 229 | /*r_kp1 = tp[N-k-1:N] + h[k+1:2*k+2]*/ 230 | CvmdAdd(k+1, tp + N - k - 1, h + k + 1, r_kp1); 231 | 232 | /* alpha[k+1] = np.dot(tp[N-k-1:N]+h[k+1:2*(k+1)], gamma[k]) */ 233 | alpha[k+1] = CvmdDot(k+1, r_kp1, gamma + ((k+1)*k)/2); 234 | 235 | /* b_k = ((alpha[k] - alpha[k+1])*gamma[k] + np.hstack([0, gamma[k][:k]]) 236 | + np.hstack([gamma[k][1:k+1], 0]) 237 | -np.hstack([gamma[k-1], 0]) 238 | */ 239 | CvmdInit(k+1, 0.0, b_k); 240 | CvmdAxpy(k+1, alpha[k]-alpha[k+1], gamma + ((k+1)*k)/2, b_k); 241 | CvmdAxpy(k, 1.0, gamma + K, b_k + 1); 242 | CvmdAxpy(k, 1.0, gamma + K + 1, b_k); 243 | CvmdAxpy(k, -1.0, gamma + ((k)*(k-1))/2, b_k); 244 | 245 | /* nu_kp1 = (1/gamma[k][k]) * np.dot(tp[N-k-1:N]+h[k+1:2*(k+1)], b_k) */ 246 | nu_kp1 = (1/gamma[K + k]) 247 | * CvmdDot(k+1, r_kp1, b_k); 248 | 249 | gammap = 1.0/(nu_kp1 + tp[N] + h[2*k+2]); 250 | 251 | /* gamma.append(np.hstack([(gammap/gamma[k][k])*b_k, gammap])) */ 252 | CvmdScal(k+1, gammap/gamma[K + k], b_k); 253 | CvmdCopy(k+1, b_k, gamma + Kp1); 254 | gamma[Kp1 + k + 1] = gammap; 255 | } 256 | 257 | /* de-allocate */ 258 | del_vector(tp); 259 | del_vector(alpha); 260 | del_vector(r_kp1); 261 | del_vector(b_k); 262 | } 263 | -------------------------------------------------------------------------------- /BF0NLS_CPP/src/th.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Methods for computing the solution to a linear system with coefficient matrix 3 | 4 | R = T + H 5 | 6 | where T is symmetric Toeplitz and H is Hankel 7 | 8 | Based on: 9 | 10 | I. Gohberg and I. Koltracht 11 | Efficient Algorithms for Toeplitz Plus Hankel Matrices 12 | Integral Equations and Operator Theory 13 | Vol. 12 14 | 1989 15 | 16 | Tobias L. Jensen 17 | March 2015 18 | */ 19 | #ifndef __TH__H_ 20 | #define __TH__H_ 21 | 22 | #include 23 | 24 | #include "tools.hpp" 25 | #include "vector.hpp" 26 | 27 | /* Solves the system with f as right hand side. 28 | t: length N+1 29 | h: lenght 2*N+1 30 | f: lenght N+1 31 | R is N+1 x N+1 32 | 33 | returns the solution in x. 34 | */ 35 | void solve(int N, FTYPE *t, FTYPE *h, FTYPE *f, FTYPE *gamma, FTYPE *x); 36 | 37 | /* Computes the gamma values for use in solve 38 | t: length N+1 39 | h: lenght 2*N+1 40 | gamma: length (N+2)*(N+1)/2 41 | gamma_0: lenght 1 42 | gamma_1: length 2 43 | gamma_2: length 3 44 | 45 | In general, 46 | gamma_k: starts at (k+1)*k/2 and has length k+1 47 | */ 48 | void th(int N, FTYPE *t, FTYPE *h, FTYPE *gamma); 49 | 50 | 51 | /* Computes the gamma values for use in solve with coefficient matrix 52 | 53 | R = T - H 54 | 55 | t: length N+1 56 | h: lenght 2*N+1 (should be called with -h) 57 | gamma: length (N+2)*(N+1)/2 58 | gamma_0: lenght 1 59 | gamma_1: length 2 60 | gamma_2: length 3 61 | 62 | In general, 63 | gamma_k: starts at (k+1)*k/2 and has length k+1 64 | 65 | Special case with t_2 = h_0, t_3 = h_1, etc 66 | */ 67 | void thp(int N, FTYPE *t, FTYPE *h, FTYPE *gamma); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /BF0NLS_CPP/src/tools.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Various elementwise tools. Developed specifically for the 4 | use in single pitch ML estimation 5 | 6 | Tobias L Jensen, 7 | March 2015 8 | */ 9 | 10 | 11 | #include "tools.hpp" 12 | 13 | // Copy y <= x 14 | void CvmdCopy(int n, FTYPE *x, FTYPE *y){ 15 | 16 | #ifdef MKL 17 | COPY(n, x, 1, y, 1); 18 | #else 19 | for(int i = 0 ; i < n ; ++i) 20 | y[i] = x[i]; 21 | #endif 22 | 23 | } 24 | 25 | // Scal x <= alpha*x 26 | void CvmdScal(int n, FTYPE alpha, FTYPE *x){ 27 | 28 | #ifdef MKL 29 | SCAL(n, alpha, x, 1); 30 | #else 31 | for(int i = 0 ; i < n ; ++i) 32 | x[i] = alpha*x[i]; 33 | #endif 34 | } 35 | 36 | // returns y <= alpha x + y 37 | void CvmdAxpy(int n, FTYPE alpha, FTYPE *x, FTYPE *y){ 38 | 39 | #ifdef MKL 40 | AXPY(n, alpha, x, 1, y, 1); 41 | #else 42 | for(int i = 0 ; i < n ; ++i) 43 | y[i] += alpha*x[i]; 44 | #endif 45 | } 46 | 47 | // returns inner dot product a^T b 48 | FTYPE CvmdDot(int n, FTYPE *a, FTYPE *b){ 49 | 50 | #ifdef MKL 51 | return DOT(n, a, 1, b, 1); 52 | #else 53 | FTYPE c = 0.0; 54 | for(int i = 0 ; i < n ; ++i) 55 | c += a[i]*b[i]; 56 | return c; 57 | #endif 58 | 59 | 60 | } 61 | 62 | // Adds c_i <- a + b_i 63 | void CvmdAddConstant(int n, FTYPE a, FTYPE *b, FTYPE *c){ 64 | 65 | for(int i = 0 ; i < n ; ++i) 66 | c[i] = a + b[i]; 67 | } 68 | 69 | // Adds c <- a + b 70 | void CvmdAdd(int n, FTYPE *a, FTYPE *b, FTYPE *c){ 71 | 72 | #ifdef MKL 73 | VADD(n, a, b, c); 74 | #else 75 | for(int i = 0 ; i < n ; ++i) 76 | c[i] = a[i] + b[i]; 77 | #endif 78 | } 79 | 80 | // Adds c <- a - b 81 | void CvmdSub(int n, FTYPE *a, FTYPE *b, FTYPE *c){ 82 | 83 | #ifdef MKL 84 | VSUB(n, a, b, c); 85 | #else 86 | for(int i = 0 ; i < n ; ++i) 87 | c[i] = a[i] - b[i]; 88 | #endif 89 | } 90 | 91 | // Adds a <- a + b 92 | void CvmdAddInplace(int n, FTYPE *a, FTYPE *b){ 93 | 94 | #ifdef MKL 95 | VADD(n, a, b, a); 96 | #else 97 | for(int i = 0 ; i < n ; ++i) 98 | a[i] += b[i]; 99 | #endif 100 | } 101 | 102 | // Adds a <- a - b 103 | void CvmdSubInplace(int n, FTYPE *a, FTYPE *b){ 104 | 105 | #ifdef MKL 106 | VSUB(n, a, b, a); 107 | #else 108 | for(int i = 0 ; i < n ; ++i) 109 | a[i] -= b[i]; 110 | #endif 111 | } 112 | 113 | //forms reverse vector b <- a_[n:1:-1] 114 | void CvmdReverse(int n, FTYPE *a, FTYPE *b){ 115 | 116 | for(int i=0 ; i < n ; ++i) 117 | b[i] = a[n-i-1]; 118 | 119 | } 120 | 121 | //forms symmetric vector b <- [a_[1:n]; a_[n-1:1:-1]] 122 | void CvmdSymmetric(int n, FTYPE *a, FTYPE *b){ 123 | 124 | for(int i=0 ; i < n ; ++i) 125 | b[i] = a[i]; 126 | 127 | for(int i=0 ; i < n-1 ; ++i) 128 | b[n+i] = a[n-i-2]; 129 | } 130 | 131 | //computer c <- a_[1:n] + [0; b_[1:n-1]] 132 | void CvmdShift(int n, FTYPE *a, FTYPE *b, FTYPE *c){ 133 | c[0] = a[0]; 134 | for(int i=1 ; i < n; ++i) 135 | c[i] = a[i] + b[i-1]; 136 | } 137 | 138 | //Computes elementwise y_i <- a - x_i^2 139 | void CvmdScalSquare(int n, FTYPE a, FTYPE * x, FTYPE * y){ 140 | 141 | for(int i = 0 ; i < n ; ++i){ 142 | y[i] = a - x[i]*x[i]; 143 | } 144 | } 145 | 146 | 147 | 148 | //Initialize a vector with value a 149 | void CvmdInit(int n, FTYPE a, FTYPE * x){ 150 | 151 | for(int i = 0 ; i < n ; ++i){ 152 | x[i] = a; 153 | } 154 | } 155 | 156 | 157 | //Computes elementwise sin y_i <- sin(a * x_i), where x_i is from min to max 158 | void CvmdSinRange(int min, int max, FTYPE a, FTYPE * y){ 159 | 160 | FTYPE * yp = y; 161 | for(int i = min ; i <= max ; ++i){ 162 | *yp++ = sin(a*i); 163 | } 164 | } 165 | 166 | //Computes elementwise sin y_i <- sin(a * x_i), 167 | void CvmdSinRange(int n, FTYPE * x, FTYPE a, FTYPE * t, FTYPE * y){ 168 | 169 | #ifdef MKL 170 | CvmdInit(n, 0.0, t); 171 | AXPY(n, a, x, 1, t, 1); 172 | VSIN(n, t, y); 173 | #else 174 | for(int i = 0 ; i < n ; ++i){ 175 | y[i] = sin(a*x[i]); 176 | } 177 | #endif 178 | } 179 | 180 | 181 | //Computes elementwise complex exponential y_i <- exp(1i*alpha * x_i) 182 | // where x_i is from min to max 183 | // and alpha and xi are real 184 | // y_i is in interleaved complex format 185 | void CvmdExpRange(int min, int max, FTYPE a, FTYPE * y){ 186 | FTYPE v; 187 | FTYPE *yp = y; 188 | 189 | for(int i = min ; i <= max ; ++i){ 190 | v = a*i; 191 | *yp++ = cos(v); 192 | *yp++ = sin(v); 193 | } 194 | } 195 | 196 | //Computes elementwise complex exponential y_i <- exp(1i*alpha * x_i) 197 | // where alpha and xi are real 198 | // y_i is in interleaved complex format 199 | // t1 and t2 are temp vectors of length n 200 | void CvmdExpRange(int n, FTYPE * x, FTYPE a, 201 | FTYPE * t1, FTYPE * t2, FTYPE * y){ 202 | 203 | #ifdef MKL 204 | CvmdInit(n, 0.0, y); 205 | AXPY(n, a, x, 1, y, 1); 206 | VSINCOS(n, y, t1, t2); 207 | VUNPACKI(n, t2, y, 2); 208 | VUNPACKI(n, t1, y+1, 2); 209 | #else 210 | FTYPE v; 211 | FTYPE *yp = y; 212 | 213 | for(int i = 0 ; i < n ; ++i){ 214 | v = a*x[i]; 215 | *yp++ = cos(v); 216 | *yp++ = sin(v); 217 | } 218 | #endif 219 | } 220 | 221 | //Computes elementwise 222 | // y_i = cos(alpha * x_i) 223 | // and 224 | // z_i = sin(alpha * x_i) 225 | // t is a temp vectors of length n 226 | void CvmdCosSinRange(int n, FTYPE * x, FTYPE a, FTYPE *t, 227 | FTYPE * y, FTYPE * z){ 228 | 229 | #ifdef MKL 230 | CvmdInit(n, 0.0, t); 231 | AXPY(n, a, x, 1, t, 1); 232 | VSINCOS(n, t, z, y); 233 | #else 234 | FTYPE v; 235 | 236 | for(int i = 0 ; i < n ; ++i){ 237 | v = a*x[i]; 238 | y[i] = cos(v); 239 | z[i] = sin(v); 240 | } 241 | #endif 242 | } 243 | 244 | 245 | //Computes elementwise multiplication y_i <- x_i * z_i 246 | void CvmdMul(int n, FTYPE * x, FTYPE * z, FTYPE * y){ 247 | 248 | #ifdef MKL 249 | VMUL(n, x, z, y); 250 | #else 251 | for(int i = 0 ; i < n ; ++i){ 252 | y[i] = x[i]*z[i]; 253 | } 254 | #endif 255 | } 256 | 257 | 258 | //Computes elementwise multiplication v + iw <- x_i * z_(si) 259 | // with x, z complex and step s 260 | // Real part goes into v, imaginary part into w 261 | // t is a temp vector with n complex number 262 | void CvmdMulz(int n, FTYPE * x, FTYPE * z, int s, FTYPE *t, 263 | FTYPE * v, FTYPE * w){ 264 | 265 | #ifdef MKL 266 | vzPackI(n, (MKL_COMPLEX*)z, s, (MKL_COMPLEX*)t); 267 | vzMul(n, (MKL_COMPLEX*)x, (MKL_COMPLEX*)t, (MKL_COMPLEX*)t); 268 | vdPackI(n, t, 2, v); 269 | vdPackI(n, t+1, 2, w); 270 | #else 271 | int ii = 0; 272 | for(int i = 0 ; i < n ; ++i){ 273 | v[i] = x[2*i]*z[ii] - x[2*i+1]*z[ii+1]; 274 | w[i] = x[2*i]*z[ii+1] + x[2*i+1]*z[ii]; 275 | ii += 2*s; 276 | } 277 | #endif 278 | } 279 | 280 | //Computes elementwise multiplication v + iw <- x_i * z_i 281 | // with x, z complex 282 | // Real part goes into v, imaginary part into w 283 | // t is a temp vector with n complex number 284 | void CvmdMulz(int n, FTYPE * x, FTYPE * z, FTYPE *t, 285 | FTYPE * v, FTYPE * w){ 286 | 287 | #ifdef MKL 288 | vzMul(n, (MKL_COMPLEX*)x, (MKL_COMPLEX*)z, (MKL_COMPLEX*)t); 289 | vdPackI(n, t, 2, v); 290 | vdPackI(n, t+1, 2, w); 291 | #else 292 | int ii = 0; 293 | for(int i = 0 ; i < n ; ++i){ 294 | v[i] = x[2*i]*z[ii] - x[2*i+1]*z[ii+1]; 295 | w[i] = x[2*i]*z[ii+1] + x[2*i+1]*z[ii]; 296 | ii += 2; 297 | } 298 | #endif 299 | } 300 | 301 | 302 | 303 | //Computes elementwise division y_i <- x_i / z_i 304 | void CvmdDiv(int n, FTYPE * x, FTYPE * z, FTYPE * y){ 305 | 306 | #ifdef MKL 307 | VDIV(n, x, z, y); 308 | #else 309 | for(int i = 0 ; i < n ; ++i){ 310 | y[i] = x[i]/z[i]; 311 | } 312 | #endif 313 | } 314 | 315 | //Computes elementwise inverse y_i <- 1.0 / x_i 316 | void CvmdInverse(int n, FTYPE * x, FTYPE * y){ 317 | 318 | #ifdef MKL 319 | VINV(n, x, y); 320 | #else 321 | for(int i = 0 ; i < n ; ++i){ 322 | y[i] = 1/x[i]; 323 | } 324 | #endif 325 | } 326 | 327 | // packs x from step s to unit stride in y 328 | void CvmdPack(int n, FTYPE * x, int s, FTYPE * y){ 329 | int ii = 0; 330 | for( int i = 0 ; i < n ; ++i){ 331 | y[i] = x[ii]; 332 | ii += s; 333 | } 334 | } 335 | 336 | 337 | int CvmdArgmax(int n, FTYPE * x){ 338 | 339 | FTYPE max; 340 | int arg; 341 | 342 | max = x[0]; 343 | arg = 0; 344 | 345 | for( int k = 1 ; k < n ; ++k){ 346 | if( x[k] > max){ 347 | max = x[k]; 348 | arg = k; 349 | } 350 | } 351 | 352 | return arg; 353 | 354 | } 355 | -------------------------------------------------------------------------------- /BF0NLS_CPP/src/tools.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __TOOLS_H__ 2 | #define __TOOLS_H__ 3 | 4 | #include 5 | 6 | #ifdef DOUBLE 7 | #define FTYPE double 8 | 9 | #define ABS fabs 10 | 11 | #define FFTW_MALLOC fftw_malloc 12 | #define FFTW_PLAN fftw_plan 13 | #define FFTW_PLAN_DFT_R2C_1D fftw_plan_dft_r2c_1d 14 | #define FFTW_PLAN_DFT_C2R_1D fftw_plan_dft_c2r_1d 15 | #define FFTW_EXECUTE fftw_execute 16 | #define FFTW_DESTROY_PLAN fftw_destroy_plan 17 | #define FFTW_FREE fftw_free 18 | #define FFTW_COMPLEX fftw_complex 19 | 20 | #define COPY cblas_dcopy 21 | #define SCAL cblas_dscal 22 | #define AXPY cblas_daxpy 23 | #define DOT cblas_ddot 24 | #define VADD vdAdd 25 | #define VSUB vdSub 26 | #define VSIN vdSin 27 | #define VSINCOS vdSinCos 28 | #define VUNPACKI vdUnpackI 29 | #define VMUL vdMul 30 | #define VDIV vdDiv 31 | #define VINV vdInv 32 | 33 | #define MKL_COMPLEX MKL_Complex16 34 | 35 | #else 36 | #define FTYPE float 37 | 38 | #define ABS fabsf 39 | 40 | #define FFTW_MALLOC fftwf_malloc 41 | #define FFTW_PLAN fftwf_plan 42 | #define FFTW_PLAN_DFT_R2C_1D fftwf_plan_dft_r2c_1d 43 | #define FFTW_PLAN_DFT_C2R_1D fftwf_plan_dft_c2r_1d 44 | #define FFTW_EXECUTE fftwf_execute 45 | #define FFTW_DESTROY_PLAN fftwf_destroy_plan 46 | #define FFTW_FREE fftwf_free 47 | #define FFTW_COMPLEX fftwf_complex 48 | 49 | #define COPY cblas_scopy 50 | #define SCAL cblas_sscal 51 | #define AXPY cblas_saxpy 52 | #define DOT cblas_sdot 53 | #define VADD vsAdd 54 | #define VSUB vsSub 55 | #define VSIN vsSin 56 | #define VSINCOS vsSinCos 57 | #define VUNPACKI vsUnpackI 58 | #define VMUL vsMul 59 | #define VDIV vsDiv 60 | #define VINV vsInv 61 | 62 | #define MKL_COMPLEX MKL_Complex8 63 | #endif 64 | 65 | #define MAX(A,B) (A > B ? A : B) 66 | #define MIN(A,B) (A < B ? A : B) 67 | 68 | #ifdef MKL 69 | #include 70 | #endif 71 | 72 | void CvmdSinRange(int min, int max, FTYPE a, FTYPE * y); 73 | 74 | void CvmdSinRange(int n, FTYPE * x, FTYPE a, FTYPE * t, FTYPE * y); 75 | 76 | void CvmdExpRange(int min, int max, FTYPE a, FTYPE * y); 77 | 78 | void CvmdExpRange(int n, FTYPE * x, FTYPE a, FTYPE *t1, FTYPE *t2, FTYPE * y); 79 | 80 | void CvmdCosSinRange(int n, FTYPE * x, FTYPE a, FTYPE *t, 81 | FTYPE * y, FTYPE * z); 82 | 83 | void CvmdScalSquare(int n, FTYPE a, FTYPE * x, FTYPE * y); 84 | 85 | void CvmdInit(int n, FTYPE a, FTYPE * x); 86 | 87 | void CvmdDiv(int n, FTYPE * x, FTYPE * z, FTYPE * y); 88 | 89 | void CvmdInverse(int n, FTYPE * x, FTYPE * y); 90 | 91 | void CvmdMul(int n, FTYPE * x, FTYPE * z, FTYPE * y); 92 | 93 | void CvmdMulz(int n, FTYPE * x, FTYPE * z, int s, FTYPE *t, FTYPE * v, FTYPE * w); 94 | 95 | void CvmdMulz(int n, FTYPE * x, FTYPE * z, FTYPE *t, FTYPE * v, FTYPE * w); 96 | 97 | void CvmdShift(int n, FTYPE *a, FTYPE *b, FTYPE *c); 98 | 99 | void CvmdSymmetric(int n, FTYPE *a, FTYPE *b); 100 | 101 | void CvmdReverse(int n, FTYPE *a, FTYPE *b); 102 | 103 | FTYPE CvmdDot(int n, FTYPE *a, FTYPE *b); 104 | 105 | void CvmdAddConstant(int n, FTYPE a, FTYPE *b, FTYPE *c); 106 | 107 | void CvmdAdd(int n, FTYPE *a, FTYPE *b, FTYPE *c); 108 | 109 | void CvmdSub(int n, FTYPE *a, FTYPE *b, FTYPE *c); 110 | 111 | void CvmdAddInplace(int n, FTYPE *a, FTYPE *b); 112 | 113 | void CvmdSubInplace(int n, FTYPE *a, FTYPE *b); 114 | 115 | void CvmdAxpy(int n, FTYPE alpha, FTYPE *x, FTYPE *y); 116 | 117 | void CvmdScal(int n, FTYPE alpha, FTYPE *x); 118 | 119 | void CvmdCopy(int n, FTYPE *x, FTYPE *y); 120 | 121 | void CvmdPack(int n, FTYPE * x, int s, FTYPE * y); 122 | 123 | int CvmdArgmax(int n, FTYPE * x); 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /BF0NLS_CPP/src/vector.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Defines usefull constructs (memory constructs) and 3 | free that supports several memory organization approaches 4 | using proper usage of defines 5 | 6 | MKL: uses MKL malloc and free. 7 | Define ALIGNMENT32, ALIGNMENT64, ALIGNMENT128, as well 8 | to define the alignment. 9 | 10 | else: uses standard C++ allocation via new and delete of arrays. 11 | 12 | */ 13 | 14 | #include "vector.hpp" 15 | 16 | FTYPE * vector(int N){ 17 | FTYPE * x; 18 | 19 | #ifdef MKL 20 | x = (FTYPE*)mkl_malloc(sizeof(FTYPE)*N, ALIGNMENT); 21 | #else 22 | x = new FTYPE [N]; 23 | #endif 24 | 25 | if( x == NULL ){ 26 | printf("Vector.cpp: Could not allocate %d bytes of memory", 27 | (int)sizeof(FTYPE)*N); 28 | exit(EXIT_FAILURE); 29 | } 30 | 31 | return x; 32 | } 33 | 34 | 35 | void del_vector(FTYPE * x){ 36 | 37 | #ifdef MKL 38 | mkl_free(x); 39 | #else 40 | delete [] x; 41 | #endif 42 | 43 | } 44 | -------------------------------------------------------------------------------- /BF0NLS_CPP/src/vector.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __VECTOR_H__ 2 | #define __VECTOR_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include "tools.hpp" 8 | 9 | #ifdef ALIGNMENT32 10 | #define ALIGNMENT 32 11 | #endif 12 | 13 | #ifdef ALIGNMENT64 14 | #define ALIGNMENT 64 15 | #endif 16 | 17 | #ifdef ALIGNMENT128 18 | #define ALIGNMENT 128 19 | #endif 20 | 21 | FTYPE * vector(int N); 22 | 23 | void del_vector(FTYPE * x); 24 | 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_MATLAB/.DS_Store -------------------------------------------------------------------------------- /BF0NLS_MATLAB/BayesianfastF0NLS.m: -------------------------------------------------------------------------------- 1 | classdef BayesianfastF0NLS< handle 2 | 3 | % usuage 4 | 5 | % obj= BayesianfastF0NLS(N, L, pitchBounds, A_var,voicingProb,varargin) 6 | % N is the frame length 7 | % L is the maximum allowed harmonic order 8 | % pitchBounds denotes the pitch range e.g.,[f_min/fs, f_max/fs], where fs is 9 | % the sampling frequency 10 | % A_var denotes the frequncy transition variance. 11 | % voicingProb denotes the initial voicing probability 12 | 13 | 14 | 15 | % Can only be set in the constructor 16 | properties (SetAccess=immutable) 17 | N 18 | L 19 | F 20 | pitchBoundsOuter = [0.0 0.5] % The outer bounds that are acceptable 21 | 22 | % default values 23 | epsilon = 0.0 24 | dcIsIncluded = false 25 | epsilon_ref = 0.0 26 | 27 | % Precomputed quantities 28 | crossCorrelationVectors 29 | Gamma1 30 | Gamma2 31 | fftShiftVector 32 | end 33 | 34 | properties (SetAccess=private) 35 | pitchBounds % The current active bounds 36 | fullPitchGrid 37 | validFftIndices 38 | defaultRefinementTol 39 | refinementTol 40 | gPriorParam = 3 41 | logPitchPdfs % the pitch pdf (column) for every candidate model order 42 | logModelPmf % an (L+1)x1 vector 43 | logpi 44 | A 45 | scaled_alpha_buffer 46 | scaled_alpha_buffer2 47 | unvoicing_scaled_alpha_buffer 48 | logModelPrior; 49 | %% varSpeech is a regularization parameter and it should be chosen according to the input SNR 50 | % In high SNR, a larger value leads to better performance from our 51 | % experience. 52 | varSpeech=5e-6; 53 | %% 54 | B 55 | C 56 | norml_factor=0; 57 | cnt=1; 58 | prew_state 59 | end 60 | 61 | methods 62 | 63 | 64 | function obj = BayesianfastF0NLS(N, L, pitchBounds, A_var,voicingProb,varargin) 65 | switch nargin 66 | case 0 67 | N=0.03*16000; 68 | L=10; 69 | pitchBounds=[50/16000,400/16000]; 70 | A_var=[2/16000]; 71 | voicingProb=0.7; 72 | case 1 73 | L=10; 74 | pitchBounds=[50/16000,400/16000]; 75 | A_var=[2/16000]; 76 | voicingProb=0.7; 77 | case 2 78 | pitchBounds=[50/16000,400/16000]; 79 | A_var=[2/16000]; 80 | voicingProb=0.7; 81 | case 3 82 | A_var=[2/16000]; 83 | voicingProb=0.7; 84 | case 4 85 | voicingProb=0.7; 86 | end 87 | 88 | % validate input 89 | if length(varargin) >= 1 90 | if islogical(varargin{1}) 91 | obj.dcIsIncluded = varargin{1}; 92 | else 93 | error('Argument 4 is not of type logical (true/false)') 94 | end 95 | end 96 | if length(varargin) >= 2 97 | if isscalar(varargin{2}) 98 | obj.F = varargin{2}; 99 | else 100 | error('Argument 5 is not a scalar') 101 | end 102 | else 103 | obj.F = 2^14; 104 | end 105 | obj.defaultRefinementTol = 1/obj.F; 106 | 107 | if length(varargin) >= 3 108 | if isscalar(varargin{3}) 109 | obj.epsilon = varargin{3}; 110 | else 111 | error('Argument 6 is not a scalar') 112 | end 113 | end 114 | 115 | if length(varargin) > 4 116 | error('Too many input arguments') 117 | end 118 | 119 | if ~isscalar(N) 120 | error('Input argument N is not a scalar') 121 | else 122 | obj.N = N; 123 | end 124 | if ~isscalar(L) 125 | error('Input argument L is not a scalar') 126 | else 127 | obj.L = L; 128 | end 129 | 130 | if ~ (isvector(pitchBounds) && length(pitchBounds) == 2) 131 | error(['Input argument pitchBound must be a 2-' ... 132 | 'vector']) 133 | elseif pitchBounds(1) < obj.pitchBoundsOuter(1) || ... 134 | pitchBounds(2) > obj.pitchBoundsOuter(2) 135 | 136 | error(['Input argument pitchBounds must be within the ' ... 137 | 'bounds specified in the constructor (at ' ... 138 | 'least [0.0 0.5])']) 139 | else 140 | obj.pitchBounds = pitchBounds; 141 | end 142 | 143 | if pitchBounds(1) < 1/N 144 | warning(['The lower pitch bound is set lower than one '... 145 | ' period/segment. Inaccurate results might be '... 146 | 'produced - especially if you do not set the'... 147 | ' regularisation parameter.']); 148 | end 149 | 150 | % Init 151 | F = obj.F; 152 | minFftIndex = ceil(F*pitchBounds(1)); 153 | maxFftIndex = floor(F*pitchBounds(2)); 154 | obj.validFftIndices = (minFftIndex:maxFftIndex)'; 155 | obj.fullPitchGrid = obj.validFftIndices/F; 156 | nPitches = length(obj.fullPitchGrid); 157 | obj.logModelPrior=[voicingProb,1-voicingProb]; 158 | 159 | % cross-correlation vectors 160 | obj.crossCorrelationVectors = ... 161 | [N*ones(1, nPitches)/2 + N*obj.epsilon;... 162 | sin(pi*(1:2*L)'*obj.fullPitchGrid'*N)./... 163 | (2*sin(pi*(1:2*L)'*obj.fullPitchGrid'))]; 164 | 165 | obj.fftShiftVector = ... 166 | exp(1i*2*pi*(0:ceil(F/2)-1)'*(N-1)/(2*F)); 167 | 168 | % Compute Gamma for the T+H and T-H systems 169 | [obj.Gamma1, obj.Gamma2] = computeGamma(L, F, pitchBounds, ... 170 | obj.crossCorrelationVectors, nPitches, ... 171 | obj.validFftIndices, ... 172 | obj.dcIsIncluded); 173 | %% added by Liming Shi 174 | obj.scaled_alpha_buffer=nan; 175 | grid_width=diff(obj.fullPitchGrid(1:2)); 176 | % obj.logpi=(log(1/(nPitches-1))-log(grid_width))*ones(nPitches,1); 177 | obj.logpi=log((voicingProb)/(nPitches*L))*ones(nPitches,1); 178 | obj.A=zeros(nPitches,nPitches); 179 | 180 | 181 | for jj=1:nPitches 182 | % f0=obj.fullPitchGrid(jj); 183 | % obj.A(jj,:)= abs(sin(pi*(obj.fullPitchGrid-f0)/f0)./pi./(obj.fullPitchGrid-f0)*f0)+.1; 184 | obj.A(jj,:)=(normpdf(obj.fullPitchGrid,obj.fullPitchGrid(jj),A_var)); 185 | % var_value=1e-1; 186 | % obj.logA(jj,:)=log(lognpdf(obj.fullPitchGrid,log(obj.fullPitchGrid(jj)*exp(var_value)),var_value)); 187 | % obj.logA(jj,:)=log(normpdf(log(obj.fullPitchGrid),log(obj.fullPitchGrid(jj)),.1)); 188 | end 189 | 190 | 191 | obj.A=obj.A./repmat(sum(obj.A,2),1,nPitches); 192 | 193 | obj.B=zeros(obj.L,obj.L); 194 | 195 | 196 | for jj=1:obj.L 197 | obj.B(jj,:)=normpdf(jj,[1:obj.L],1); 198 | end 199 | 200 | 201 | obj.B=obj.B./repmat(sum(obj.B,2),1,obj.L); 202 | 203 | obj.C=[.7 .3;.4,.6]; 204 | 205 | obj.scaled_alpha_buffer2=1/obj.L/nPitches*ones(nPitches,obj.L); 206 | 207 | end 208 | 209 | function varargout = computeCostFunctions(obj, x) 210 | % Compute and returns the cost functions for l=1,...,L 211 | 212 | % validate input 213 | if ~isvector(x) && length(x) == obj.N 214 | error(['First argument x must be vector of ' ... 215 | 'length N=', num2str(obj.N)]); 216 | end 217 | x = reshape(x, obj.N, 1); % make sure its a column 218 | % vector 219 | 220 | 221 | varargout{1} = computeAllCostFunctions(x, obj.L, ... 222 | obj.fullPitchGrid, obj.fftShiftVector, ... 223 | obj.crossCorrelationVectors, obj.Gamma1, obj.Gamma2, ... 224 | obj.dcIsIncluded); 225 | 226 | if nargout == 2 227 | varargout{2} = obj.fullPitchGrid; 228 | end 229 | 230 | end 231 | 232 | function varargout = estimate(obj, x, flag,tinc,varargin) 233 | % Estimate fundamental frequency and order of the signal x 234 | 235 | % validate input 236 | if ~isvector(x) && length(x) == obj.N 237 | error(['First argument x must be vector of ' ... 238 | 'length N=', num2str(obj.N)]); 239 | end 240 | x = reshape(x, obj.N, 1); % make sure its a column 241 | % vector 242 | 243 | if length(varargin) == 1 244 | if isscalar(varargin{1}) 245 | obj.refinementTol = varargin{1}; 246 | else 247 | error('Argument 2 is not a scalar') 248 | end 249 | else 250 | obj.refinementTol = obj.defaultRefinementTol; 251 | end 252 | if flag==1 253 | spec_pow_all=(abs(fft(x,2048)).^2)'; 254 | if isempty(obj.prew_state) 255 | [psdouput,obj.prew_state]=estnoiseg_orig(spec_pow_all,tinc); 256 | else 257 | [psdouput,obj.prew_state]=estnoiseg_orig(spec_pow_all,obj.prew_state); 258 | end 259 | mmse_covariance_all = (real(ifft(psdouput'))); 260 | mmse_lpc_all= levinson(mmse_covariance_all,30); 261 | [xp] = filter(mmse_lpc_all,1,... 262 | x); 263 | x=xp/norm(xp)*norm(x); 264 | end 265 | 266 | 267 | 268 | 269 | % if the data consists of all zeros then return null model 270 | if x'*x/obj.N<1e-10 271 | estimatedPitch = nan; 272 | estimatedOrder = 0; 273 | unvoicing_scaled_alpha=log(1); 274 | else 275 | % Step 2: compute the profile log-likelihood function 276 | % over only the fundamental frequency (the linear 277 | % parameters, noise variance and g have been integrated 278 | % out) 279 | % x=x/norm(x); 280 | costs = obj.computeCostFunctions(x); 281 | 282 | % for ii=1:size(costs,1) 283 | % regvalue=1e-5; 284 | % tempt=costs(ii,:)/(2*regvalue); 285 | % pitchLogLikelihood(ii,:)=tempt+log(tempt)*(-3/2-ii+1)+... 286 | % log(gammainc(costs(ii,:),3/2+ii-1)); 287 | % end 288 | 289 | 290 | cod = costs*(1/(x'*x+obj.varSpeech*obj.N)); 291 | % % cod = (costs)*(1/(x'*x)); 292 | % % cod = costs*(1/(x'*x)); 293 | [~, pitchLogLikelihood] = ... 294 | computePitchLogLikelihood(cod, obj.N, obj.gPriorParam); 295 | % % pitchLogLikelihood=pitchLogLikelihood; 296 | null_modellike=1; 297 | 298 | %% added/modified by Liming Shi (implements the hidden markov chain) 299 | if isnan(obj.scaled_alpha_buffer) 300 | inx=isnan(pitchLogLikelihood); 301 | pitchLogLikelihood(inx)=-inf; 302 | bar_alpha=obj.logpi+pitchLogLikelihood'; 303 | 304 | unvoicing_bar_alpha=log(obj.logModelPrior(2)*null_modellike); 305 | log_scale=log_sumsum_exp_ls([[unvoicing_bar_alpha,-inf*ones(1,obj.L-1)];bar_alpha]); 306 | scaled_alpha=bar_alpha-log_scale; 307 | unvoicing_scaled_alpha=unvoicing_bar_alpha-log_scale; 308 | 309 | else 310 | inx=isnan(pitchLogLikelihood); 311 | pitchLogLikelihood(inx)=-inf; 312 | state_prior=obj.C(1,1)*obj.A'*obj.scaled_alpha_buffer*obj.B; 313 | 314 | state_prior=state_prior+obj.scaled_alpha_buffer2*obj.C(2,1)*obj.unvoicing_scaled_alpha_buffer; 315 | 316 | bar_alpha=log(state_prior)+pitchLogLikelihood'; 317 | 318 | temp=[1-obj.unvoicing_scaled_alpha_buffer;obj.unvoicing_scaled_alpha_buffer]; 319 | 320 | unvoicing_bar_alpha=log(obj.C(:,2)'*temp*null_modellike); 321 | log_scale=log_sumsum_exp_ls([[unvoicing_bar_alpha,-inf*ones(1,obj.L-1)];bar_alpha]); 322 | scaled_alpha=bar_alpha-log_scale; 323 | unvoicing_scaled_alpha=unvoicing_bar_alpha-log_scale; 324 | 325 | end 326 | 327 | [value, inx] = ... 328 | max(scaled_alpha); 329 | [~,inx_2]=max(value); 330 | pitchIndex=inx(inx_2); 331 | estimatedOrder=inx_2; 332 | estimatedPitch = obj.fullPitchGrid(pitchIndex(1)); 333 | %% added by Liming Shi (buffering the previous meaningful estimates of the posterior states) 334 | 335 | 336 | if unvoicing_scaled_alpha < log(0.5) 337 | obj.scaled_alpha_buffer2=exp(scaled_alpha-log(1-exp(unvoicing_scaled_alpha))); 338 | else 339 | % estimatedOrder=nan; 340 | end 341 | obj.scaled_alpha_buffer=exp(scaled_alpha); 342 | obj.unvoicing_scaled_alpha_buffer=exp(unvoicing_scaled_alpha); 343 | end 344 | 345 | %% 346 | 347 | if nargout >= 1 348 | varargout{1} = estimatedPitch; 349 | end 350 | if nargout >= 2 351 | varargout{2} = estimatedOrder; 352 | end 353 | if nargout >= 3 354 | % [~, alpha] = objFunction(estimatedPitch, x, ... 355 | % estimatedOrder, obj.dcIsIncluded); 356 | varargout{3} = 1-exp(unvoicing_scaled_alpha); 357 | end 358 | 359 | end 360 | function obj=destroy(obj) 361 | end 362 | end 363 | end 364 | function y=log_sumsum_exp_ls(x) 365 | max_temp=max(max(x)); 366 | inf_ind=isinf(max_temp); 367 | y=log(sum(sum(exp(x-max_temp))))+max_temp; 368 | y(inf_ind)=-inf; 369 | end 370 | 371 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/CleanSpeech.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_MATLAB/CleanSpeech.wav -------------------------------------------------------------------------------- /BF0NLS_MATLAB/factoryNoise.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_MATLAB/factoryNoise.mat -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/BF0NLS.m: -------------------------------------------------------------------------------- 1 | function result=BF0NLS(speechSignal,samplingFreq,plot_flag,prew_flag,Par_set) 2 | % ----------------------------------------------------------------------- 3 | % format of the input and output arguments 4 | % 5 | % input: 6 | % input arguments --> as the names suggested 7 | % plot_flag: 0 when you do not want a plot (0 in default) 8 | % prew_flag: 0 when you do not want to prewhiten the signal (0 in default) 9 | % Par_set: the parameter set you can set, including the segment time, 10 | % segment shift and F0 boundaries. 11 | % 12 | % Par_set.segmentTime is the segmentTime in seconds (25 ms in default) 13 | % Par_set.segmentShift is the segmentShift in seconds (10 ms in default) 14 | % Par_set.f0Bounds is the F0 boundaries in Hz ([70 400] Hz in default) 15 | % 16 | % output: 17 | % result.tt --> time vector 18 | % result.ff --> Fundamental frequency estimates 19 | % (when all the frames are considered as voiced) 20 | % result.oo --> order estimates 21 | % (when all the frames are considered as voiced) 22 | % result.vv --> voicing probability 23 | % result.best_ff --> Best fundamental frequency estimates (setting the F0=nan 24 | % when voicing probability is less than .5) 25 | % result.best_order --> Best harmonic order estimates (setting the order=nan 26 | % when voicing probability is less than .5) 27 | % 28 | % Example for for customize Par_set 29 | % 30 | % Par_set.segmentTime = 0.025; 25 ms for each segment (default value) 31 | % Par_set.segmentShift = 0.01; 10 ms for segment shift (default value) 32 | % Par_set.f0Bounds =[70, 400]; pitch is bounded between 70 to 400 Hz (default value) 33 | % 34 | % 35 | % Written by Liming Shi, Aalborg 9000, Denmark 36 | % Email: ls@create.aau.dk 37 | % ----------------------------------------------------------------------- 38 | 39 | 40 | if nargin<3 41 | % do not use prewhitening in default, and do not plot 42 | plot_flag=0; 43 | prew_flag=0; 44 | Par_set=[]; 45 | end 46 | if nargin<4 47 | % do not use prewhitening in default 48 | prew_flag=0; 49 | Par_set=[]; 50 | end 51 | if nargin<5 52 | % use default parameter set 53 | Par_set=[]; 54 | end 55 | 56 | %% resample to 16 KHz for tuned parameters. However, the sampling frequency can be changed. 57 | fs_fine_tuned=16000; 58 | speechSignal=resample(speechSignal,fs_fine_tuned,samplingFreq); 59 | samplingFreq=fs_fine_tuned; 60 | if isempty(Par_set) 61 | segmentTime = 0.025; % seconds 62 | segmentShift = 0.010; % seconds 63 | f0Bounds = [70, 400]; % cycles/sample 64 | std_pitch=2; 65 | else 66 | if isfield(Par_set,'segmentTime') 67 | segmentTime = Par_set.segmentTime; % seconds 68 | else 69 | segmentTime = 0.025; % seconds 70 | end 71 | if isfield(Par_set,'segmentShift') 72 | segmentShift = Par_set.segmentShift; 73 | % std_pitch --> standard deviation for the pitch for 10 ms frame shift. 74 | % This value shouold be modified if frame shift is shorter or longer, with a lower bound of .5 Hz. 75 | std_pitch=max(2/10*segmentShift*1000,0.5); 76 | else 77 | segmentShift = 0.010; % seconds 78 | % std_pitch --> standard deviation for the pitch for 10 ms frame shift. 79 | std_pitch=2; 80 | end 81 | if isfield(Par_set,'f0Bounds') 82 | f0Bounds = Par_set.f0Bounds; % cycles/sample 83 | else 84 | f0Bounds = [70, 400]; % cycles/sample 85 | end 86 | end 87 | 88 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 89 | % normalization step 90 | sumE = sqrt(speechSignal'*speechSignal/length(speechSignal)); 91 | scale = sqrt(3.1623e-5)/sumE; % scale to -45-dB loudness level 92 | speechSignal=speechSignal*scale; 93 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 94 | nData = length(speechSignal); 95 | % set up 96 | f0Bounds=f0Bounds/samplingFreq; 97 | segmentLength = round(segmentTime*samplingFreq/2)*2; % samples 98 | nShift = round(segmentShift*samplingFreq); % samples 99 | nSegments = floor((nData+segmentLength/2-segmentLength)/nShift)+1; 100 | 101 | if prew_flag==0 102 | maxNoHarmonics = 10; 103 | else 104 | if prew_flag==1 105 | maxNoHarmonics = 30; 106 | end 107 | end 108 | f0Estimator = BayesianfastF0NLS(segmentLength, maxNoHarmonics, f0Bounds, std_pitch/samplingFreq,.7); 109 | speechSignal_padded=[zeros(segmentLength/2,1);speechSignal]; 110 | % do the analysis 111 | idx = 1:segmentLength; 112 | f0Estimates = nan(nSegments,1); % cycles/sample 113 | order=nan(nSegments,1); 114 | voicing_prob=nan(nSegments,1); 115 | if prew_flag==0 116 | for ii = 1:nSegments 117 | speechSegment = speechSignal_padded(idx); 118 | [f0Estimates(ii),order(ii),voicing_prob(ii)]=f0Estimator.estimate(speechSegment,0); 119 | idx = idx + nShift; 120 | end 121 | else 122 | if prew_flag==1 123 | for ii = 1:nSegments 124 | speechSegment = speechSignal_padded(idx); 125 | [f0Estimates(ii),order(ii),voicing_prob(ii)]=f0Estimator.estimate(speechSegment,1,segmentShift); 126 | idx = idx + nShift; 127 | end 128 | end 129 | end 130 | 131 | 132 | f0Estimates_remove_unvoiced=f0Estimates; 133 | unvoiced_indicator=voicing_prob<.5;; 134 | f0Estimates_remove_unvoiced(unvoiced_indicator)=nan; 135 | order_remove_unvoiced=order; 136 | order_remove_unvoiced(unvoiced_indicator)=nan; 137 | timeVector = [(0:nSegments-1)*segmentShift]'; 138 | 139 | result.tt=timeVector; 140 | result.ff=f0Estimates*samplingFreq; 141 | result.oo=order; 142 | result.vv=voicing_prob; 143 | result.best_ff=f0Estimates_remove_unvoiced*samplingFreq; 144 | result.best_order=order_remove_unvoiced; 145 | if plot_flag==1 146 | figure; 147 | subplot(4,1,4) 148 | plot([0:length(speechSignal_padded)-1]/samplingFreq,speechSignal_padded/max(abs(speechSignal_padded))); 149 | xlim([0,(length(speechSignal_padded)-1)/samplingFreq]) 150 | xlabel('Time [s]'); 151 | ylabel('Amplitude'); 152 | subplot(4,1,3) 153 | % plot the spectrogram 154 | window = gausswin(segmentLength); 155 | nOverlap = segmentLength-nShift; 156 | nDft = 2048; 157 | [stft, stftFreqVector] = ... 158 | spectrogram(speechSignal_padded, window, nOverlap, nDft, samplingFreq); 159 | powerSpectrum = abs(stft).^2; 160 | imagesc(timeVector, stftFreqVector, ... 161 | 10*log10(dynamicRangeLimiting(powerSpectrum, 60))); 162 | axis xy; 163 | ylim([0,f0Bounds(2)*samplingFreq+100]) 164 | hold on; 165 | plot(timeVector, result.best_ff, 'r-', 'linewidth',2); 166 | ylabel('Frequency [Hz]'); 167 | subplot(4,1,2) 168 | plot(timeVector,result.best_order,'r.', 'linewidth',2) 169 | xlim([timeVector(1),timeVector(end)]) 170 | ylabel('Order estimate') 171 | subplot(4,1,1) 172 | plot(timeVector,result.vv,'r-', 'linewidth',2) 173 | xlim([timeVector(1),timeVector(end)]) 174 | ylabel('Voicing probability') 175 | end 176 | 177 | end -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/addnoise.m: -------------------------------------------------------------------------------- 1 | function output_noise=addnoise(sig,input_noise,snr) 2 | noise=input_noise; 3 | noise_std_var=sqrt(10^(-snr/10)*(sig(:)'*sig(:))/(noise(:)'*noise(:))); 4 | output_noise=noise_std_var*noise; 5 | end 6 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/computeAllCostFunctions.m: -------------------------------------------------------------------------------- 1 | function costFunctions = computeAllCostFunctions(x, L, fullPitchGrid, ... 2 | fftShiftVector, crossCorrelationVectors, Gamma1, Gamma2, ... 3 | dcIsIncluded) 4 | % compute Zc'*y for all model orders and frequencies where Zc is the 5 | % complex-valued sinusoidal matrix 6 | [harmonicDfts, pitchGrids] = ... 7 | computeComplexHarmonicDfts(x, fullPitchGrid, L, fftShiftVector); 8 | nPitches = length(fullPitchGrid); 9 | costFunctions = nan(L, nPitches); 10 | 11 | for l = 1:L 12 | % Update the valid pitches and the DFT matrices 13 | nPitches = sum(~isnan(pitchGrids(l,:))); 14 | 15 | if dcIsIncluded 16 | gamma1 = Gamma1{l+1}; 17 | else 18 | gamma1 = Gamma1{l}; 19 | end 20 | gamma2 = Gamma2{l}; 21 | 22 | if l == 1 23 | if dcIsIncluded 24 | lsSol1 = sum(x)*Gamma1{1}; 25 | R1 = computeRowsOfToeplitzHankelMatrix(2, 2, ... 26 | crossCorrelationVectors(1:2*l+1, 1:nPitches), ... 27 | true, true); 28 | 29 | lambda1 = (ones(2, 1)*(real(harmonicDfts(l,1:nPitches))-... 30 | sum(R1(1:end-1, :).*lsSol1(:, 1:nPitches),1))); 31 | 32 | lsSol1 = [lsSol1; zeros(1, nPitches)]+lambda1.*gamma1; 33 | else 34 | lsSol1 = real(harmonicDfts(l,1:nPitches)).*gamma1; 35 | end 36 | 37 | lsSol2 = imag(harmonicDfts(l,1:nPitches)).*gamma2; 38 | else 39 | 40 | if dcIsIncluded 41 | ll = l+1; 42 | else 43 | ll = l; 44 | end 45 | 46 | R1 = computeRowsOfToeplitzHankelMatrix(ll, ll, ... 47 | crossCorrelationVectors(1:2*l+1, 1:nPitches), ... 48 | true, dcIsIncluded); 49 | 50 | lambda1 = (ones(ll, 1)*(real(harmonicDfts(l,1:nPitches))-... 51 | sum(R1(1:end-1, :).*lsSol1(:, 1:nPitches),1))); 52 | 53 | lsSol1 = [lsSol1(:, 1:nPitches); zeros(1, nPitches)] ... 54 | + lambda1.*gamma1; 55 | 56 | R2 = computeRowsOfToeplitzHankelMatrix(l, l, ... 57 | crossCorrelationVectors(1:2*l+1, 1:nPitches), ... 58 | false, dcIsIncluded); 59 | 60 | lambda2 = (ones(l, 1)*(imag(harmonicDfts(l,1:nPitches))-... 61 | sum(R2(1:end-1, :).*lsSol2(:, 1:nPitches),1))); 62 | 63 | lsSol2 = [lsSol2(:, 1:nPitches); zeros(1, nPitches)] ... 64 | + lambda2.*gamma2; 65 | 66 | end 67 | 68 | % compute the cost function 69 | if dcIsIncluded 70 | costFunctions(l, 1:nPitches) = sum(x)*lsSol1(1, :)+... 71 | sum(real(harmonicDfts(1:l,1:nPitches)).*lsSol1(2:l+1,:),1)+... 72 | sum(imag(harmonicDfts(1:l,1:nPitches)).*lsSol2,1); 73 | else 74 | costFunctions(l, 1:nPitches) = ... 75 | sum(real(harmonicDfts(1:l,1:nPitches)).*lsSol1,1)+... 76 | sum(imag(harmonicDfts(1:l,1:nPitches)).*lsSol2,1); 77 | end 78 | end -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/computeComplexHarmonicDfts.m: -------------------------------------------------------------------------------- 1 | function [harmonicDfts, pitchGrids] = ... 2 | computeComplexHarmonicDfts(dataVector, fullPitchGrid, ... 3 | pitchOrder, fftShiftVector) 4 | nData = length(dataVector); 5 | dataAreRealValued = isreal(dataVector); 6 | nDft = round(1/diff(fullPitchGrid(1:2))); 7 | dftData = fft(dataVector, nDft); 8 | % compensate for a symmetric time index (i.e., a start index of 9 | % -(nData-1)/2) 10 | fftShiftVectorLength = length(fftShiftVector); 11 | shiftedDftData = (dftData(1:fftShiftVectorLength).*fftShiftVector).'; 12 | for ii = 1:pitchOrder 13 | dftIndices = computeDftIndicesNHarmonic(nDft, ... 14 | fullPitchGrid([1,end]), ii, dataAreRealValued); 15 | nPitches = length(dftIndices); 16 | if ii == 1 17 | % allocate memory 18 | pitchGrids = nan(pitchOrder, nPitches); 19 | harmonicDfts = nan(pitchOrder, nPitches); 20 | end 21 | pitchGrids(ii,1:nPitches) = dftIndices/(ii*nDft); 22 | harmonicDfts(ii, 1:nPitches) = shiftedDftData(dftIndices+1); 23 | end 24 | end 25 | 26 | function dftIndices = computeDftIndicesNHarmonic(nDft, pitchBounds, ... 27 | pitchOrder, dataAreRealValued) 28 | minPitchIdx = max(0, ceil(pitchBounds(1)*nDft)); 29 | % the max pitch must be smaller than 1/modelOrder for complex-valued 30 | % data and 1/(2*modelOrder) for real-valued data to avoid problems 31 | % with aliasing 32 | if dataAreRealValued 33 | maxPitchIdx = min(nDft/(2*pitchOrder)-1, ... 34 | floor(pitchBounds(2)*nDft)); 35 | else 36 | maxPitchIdx = min(nDft/pitchOrder-1, ... 37 | floor(pitchBounds(2)*nDft)); 38 | end 39 | dftIndices = (minPitchIdx:maxPitchIdx)*pitchOrder; 40 | end 41 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/computeComplexHarmonicDftsTest.m: -------------------------------------------------------------------------------- 1 | function tests = computeComplexHarmonicDftsTest() 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testComputedDftsComplex(testCase) 6 | % setup 7 | rng(2); 8 | nData = 200; 9 | startIndex = -(nData-1)/2; 10 | dataVector = randn(nData,2)*[1;1i]; 11 | maxPitchOrder = 5; 12 | pitchResolution = 1/(5*maxPitchOrder*nData); 13 | pitchBounds = [0,nData-1]/nData; 14 | fullPitchGrid = computePitchGrid(pitchResolution, pitchBounds, 1); 15 | nDft = round(1/diff(fullPitchGrid(1:2))); 16 | fftShiftVector = exp(-1i*2*pi*((0:nDft-1)/nDft)*startIndex); 17 | for ii = 1:maxPitchOrder 18 | pitchGrid = computePitchGrid(pitchResolution, pitchBounds, ii); 19 | nPitches = length(pitchGrid); 20 | if ii == 1 21 | expHarmonicDfts = nan(maxPitchOrder, nPitches); 22 | expPitchGrids = nan(maxPitchOrder, nPitches); 23 | end 24 | expPitchGrids(ii,1:nPitches) = pitchGrid; 25 | for jj = 1:nPitches 26 | sinusoid = ... 27 | exp(1i*2*pi*pitchGrid(jj)*ii*((0:nData-1)+startIndex)'); 28 | expHarmonicDfts(ii,jj) = sinusoid'*dataVector; 29 | end 30 | end 31 | [actHarmonicDfts, actPitchGrids] = ... 32 | computeComplexHarmonicDfts(dataVector, fullPitchGrid, ... 33 | maxPitchOrder, fftShiftVector); 34 | testCase.assertEqual(actHarmonicDfts, expHarmonicDfts, ... 35 | 'absTol', 1e-11); 36 | testCase.assertEqual(actPitchGrids, expPitchGrids, ... 37 | 'absTol', 1e-11); 38 | end 39 | 40 | function testComputedDftsReal(testCase) 41 | % setup 42 | rng(2); 43 | nData = 200; 44 | startIndex = -(nData-1)/2; 45 | dataVector = randn(nData,1); 46 | maxPitchOrder = 5; 47 | pitchResolution = 1/(5*maxPitchOrder*nData); 48 | pitchBounds = [0,nData/2-1]/nData; 49 | fullPitchGrid = ... 50 | computePitchGrid(pitchResolution, pitchBounds, 1, true); 51 | nDft = round(1/diff(fullPitchGrid(1:2))); 52 | fftShiftVector = exp(-1i*2*pi*((0:nDft-1)/nDft)*startIndex); 53 | for ii = 1:maxPitchOrder 54 | pitchGrid = ... 55 | computePitchGrid(pitchResolution, pitchBounds, ii, true); 56 | nPitches = length(pitchGrid); 57 | if ii == 1 58 | expHarmonicDfts = nan(maxPitchOrder, nPitches); 59 | expPitchGrids = nan(maxPitchOrder, nPitches); 60 | end 61 | expPitchGrids(ii,1:nPitches) = pitchGrid; 62 | for jj = 1:nPitches 63 | sinusoid = ... 64 | exp(1i*2*pi*pitchGrid(jj)*ii*((0:nData-1)+startIndex)'); 65 | expHarmonicDfts(ii,jj) = sinusoid'*dataVector; 66 | end 67 | end 68 | [actHarmonicDfts, actPitchGrids] = ... 69 | computeComplexHarmonicDfts(dataVector, fullPitchGrid, ... 70 | maxPitchOrder, fftShiftVector); 71 | testCase.assertEqual(actHarmonicDfts, expHarmonicDfts, ... 72 | 'absTol', 1e-11); 73 | testCase.assertEqual(actPitchGrids, expPitchGrids, ... 74 | 'absTol', 1e-11); 75 | end 76 | 77 | function pitchGrid = computePitchGrid(pitchResolution, pitchBounds, ... 78 | modelOrder, dataAreRealValued) 79 | if nargin < 4 80 | dataAreRealValued = false; 81 | end 82 | nPitches = ceil(1/pitchResolution); 83 | minPitchIdx = max(0, ceil(pitchBounds(1)*nPitches)); 84 | % the max pitch must be smaller than 1/modelOrder to avoid problems 85 | % with aliasing 86 | if dataAreRealValued 87 | maxPitchIdx = min(nPitches/(2*modelOrder)-1, ... 88 | floor(pitchBounds(2)*nPitches)); 89 | else 90 | maxPitchIdx = min(nPitches/modelOrder-1, ... 91 | floor(pitchBounds(2)*nPitches)); 92 | end 93 | % the pitch grid must a subset of the full dft grid 94 | dftPitchGrid = (0:nPitches-1)'/nPitches; 95 | pitchGrid = dftPitchGrid((minPitchIdx(1):maxPitchIdx(1))+1); 96 | end -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/computeGamma.m: -------------------------------------------------------------------------------- 1 | function [Gamma1, Gamma2] = computeGamma(L, F, pitchBounds, crossCorrelationVectors, nPitches,... 2 | validFftIndices, dcIsIncluded) 3 | 4 | if L == 1 5 | a1 = crossCorrelationVectors(2, :); 6 | a2 = a1; 7 | else 8 | if dcIsIncluded 9 | a1 = crossCorrelationVectors(2:L+1, :)+... 10 | [zeros(1, nPitches);... 11 | crossCorrelationVectors((1:L-1), :)]; 12 | else 13 | a1 = crossCorrelationVectors(2:L, :)+... 14 | [zeros(1,nPitches);... 15 | crossCorrelationVectors((1:L-2)+2, :)]; 16 | end 17 | 18 | a2 = crossCorrelationVectors(2:L, :)-... 19 | [zeros(1,nPitches);... 20 | crossCorrelationVectors((1:L-2)+2, :)]; 21 | end 22 | 23 | for l = 1:L 24 | maxFftIndex = floor(min(F*pitchBounds(2),F/(2*l)-1)); 25 | nPitches = nPitches-(validFftIndices(end)-maxFftIndex); 26 | validPitchIndices = 1:nPitches; 27 | validFftIndices = validFftIndices(validPitchIndices); 28 | 29 | if l == 1 30 | % compute the cost function for a model of one 31 | if dcIsIncluded 32 | [psi1, phi1, gammaOld1] = computeGammaSingleSinus(... 33 | crossCorrelationVectors(1, validPitchIndices), ... 34 | a1(1, validPitchIndices), true, true); 35 | Gamma1{1} = gammaOld1; 36 | 37 | [R1, alpha1, gammaNew1] = computeGammaTwoSinus(... 38 | crossCorrelationVectors(1:3,validPitchIndices), ... 39 | psi1, gammaOld1, true, true); 40 | Gamma1{2} = gammaNew1; 41 | 42 | else 43 | [psi1, phi1, gammaOld1] = computeGammaSingleSinus(... 44 | crossCorrelationVectors(1:3,validPitchIndices), ... 45 | a1(1,validPitchIndices), true, false); 46 | Gamma1{1} = gammaOld1; 47 | end 48 | 49 | [psi2, phi2, gammaOld2] = computeGammaSingleSinus(... 50 | crossCorrelationVectors(1:3,validPitchIndices), ... 51 | a2(1,validPitchIndices), false, dcIsIncluded); 52 | 53 | Gamma2{1} = gammaOld2; 54 | 55 | elseif l == 2 56 | % compute the cost function for a model of two 57 | if dcIsIncluded 58 | [R1, phi1, psi1, alpha1, gammaOld1, gammaNew1] = ... 59 | computeGammaMultipleSinus(... 60 | R1(1:end-1,validPitchIndices), 3, ... 61 | crossCorrelationVectors(1:5,validPitchIndices), ... 62 | a1(l,validPitchIndices), ... 63 | phi1(:,validPitchIndices), ... 64 | psi1(:,validPitchIndices), ... 65 | gammaOld1(:,validPitchIndices), ... 66 | gammaNew1(:,validPitchIndices), ... 67 | alpha1(validPitchIndices), ... 68 | true, true); 69 | Gamma1{3} = gammaNew1; 70 | else 71 | [R1, alpha1, gammaNew1] = computeGammaTwoSinus(... 72 | crossCorrelationVectors(1:5,validPitchIndices), ... 73 | psi1(validPitchIndices), ... 74 | gammaOld1(validPitchIndices), true, false); 75 | 76 | Gamma1{2} = gammaNew1; 77 | end 78 | 79 | [R2, alpha2, gammaNew2] = computeGammaTwoSinus(... 80 | crossCorrelationVectors(1:5,validPitchIndices), ... 81 | psi2(validPitchIndices), ... 82 | gammaOld2(validPitchIndices), false, false); 83 | 84 | 85 | Gamma2{2} = gammaNew2; 86 | 87 | 88 | else 89 | 90 | if dcIsIncluded 91 | ll = l; 92 | else 93 | ll = l-1; 94 | end 95 | 96 | % compute the cost function for a model of more than two 97 | [R1, phi1, psi1, alpha1, gammaOld1, gammaNew1] = ... 98 | computeGammaMultipleSinus(... 99 | R1(1:end-1, validPitchIndices), ll+1, ... 100 | crossCorrelationVectors(1:2*l+1, validPitchIndices), ... 101 | a1(ll, validPitchIndices), ... 102 | phi1(:, validPitchIndices), ... 103 | psi1(:, validPitchIndices), ... 104 | gammaOld1(:, validPitchIndices), ... 105 | gammaNew1(:, validPitchIndices), ... 106 | alpha1(validPitchIndices), ... 107 | true, dcIsIncluded); 108 | [R2, phi2, psi2, alpha2, gammaOld2, gammaNew2] = ... 109 | computeGammaMultipleSinus(... 110 | R2(1:end-1,validPitchIndices), l, ... 111 | crossCorrelationVectors(1:2*l+1, validPitchIndices), ... 112 | a2(l-1, validPitchIndices), ... 113 | phi2(:, validPitchIndices), ... 114 | psi2(:, validPitchIndices), ... 115 | gammaOld2(:, validPitchIndices), ... 116 | gammaNew2(:, validPitchIndices), ... 117 | alpha2(validPitchIndices), ... 118 | false, dcIsIncluded); 119 | 120 | if dcIsIncluded 121 | Gamma1{l+1} = gammaNew1; 122 | else 123 | Gamma1{l} = gammaNew1; 124 | end 125 | Gamma2{l} = gammaNew2; 126 | end 127 | end 128 | 129 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/computeGammaMultipleSinus.m: -------------------------------------------------------------------------------- 1 | function [RNew, phi, psi, alphaNew, gammaOld, gammaNew] = ... 2 | computeGammaMultipleSinus(... 3 | ROld, iOrder, crossCorrelationVectors, a, phi, psi, gammaOld, ... 4 | gammaNew, alphaOld, hankelMatrixIsAdded, dcIsIncluded) 5 | 6 | nPitches = length(a); 7 | RNew = computeRowsOfToeplitzHankelMatrix(iOrder, iOrder, ... 8 | crossCorrelationVectors, hankelMatrixIsAdded, dcIsIncluded); 9 | lambda = a-sum(ROld.*phi,1); 10 | mu = -sum(ROld.*psi,1); 11 | phi = [phi;zeros(1,nPitches)]+(ones(iOrder-1,1)*lambda).*gammaNew; 12 | psi = [psi;zeros(1,nPitches)]+(ones(iOrder-1,1)*mu).*gammaNew; 13 | alphaNew = sum(RNew(1:end-1,:).*gammaNew,1); 14 | b = (ones(iOrder-1,1)*(alphaOld-alphaNew)).*gammaNew+... 15 | [zeros(1,nPitches);gammaNew(1:iOrder-2,:)]+... 16 | [gammaNew(2:end,:);zeros(1,nPitches)]-... 17 | [gammaOld(1:iOrder-2,:);zeros(1,nPitches)]+... 18 | (ones(iOrder-1,1)*psi(end,:)).*phi-... 19 | (ones(iOrder-1,1)*phi(end,:)).*psi; 20 | nu = sum(RNew(1:end-1,:).*b)./gammaNew(end,:); 21 | gammaOld = gammaNew; 22 | gammaNew = nan(iOrder,nPitches); 23 | gammaNew(iOrder,:) = 1./(nu+RNew(iOrder,:)); 24 | gammaNew(1:iOrder-1,:) = (ones(iOrder-1,1)*... 25 | (gammaNew(iOrder,:)./gammaOld(end,:))).*b; 26 | 27 | end 28 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/computeGammaSingleSinus.m: -------------------------------------------------------------------------------- 1 | function [psi, phi, gamma] = computeGammaSingleSinus(... 2 | crossCorrelationVectors, a, hankelMatrixIsAdded, dcIsIncluded) 3 | 4 | R = computeRowsOfToeplitzHankelMatrix(1, 1, ... 5 | crossCorrelationVectors, ... 6 | hankelMatrixIsAdded, ... 7 | dcIsIncluded); 8 | psi = 1./R(1, :); 9 | gamma = psi; 10 | phi = a.*gamma; 11 | end 12 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/computeGammaTwoSinus.m: -------------------------------------------------------------------------------- 1 | function [R, alpha, gamma] = computeGammaTwoSinus(... 2 | crossCorrelationVectors, psi, gamma, ... 3 | hankelMatrixIsAdded, dcIsIncluded) 4 | 5 | nPitches = length(psi); 6 | R = computeRowsOfToeplitzHankelMatrix(2,... 7 | 2, crossCorrelationVectors, hankelMatrixIsAdded, dcIsIncluded); 8 | alpha = R(1,:).*gamma; 9 | 10 | gamma = ... 11 | [-R(1,:).*psi;ones(1,nPitches)]./(ones(2,1)*(R(2,:)-R(1,: ... 12 | ).^2.*psi)); 13 | 14 | end 15 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/computeLogMarginalLikelihood.m: -------------------------------------------------------------------------------- 1 | function logMarginalLikelihood = ... 2 | computeLogMarginalLikelihood(logPitchLikelihood, fullPitchGrid) 3 | % compute the unnormalised log marginal likelihood 4 | deltaFreq = 1; 5 | maxModelOrder = size(logPitchLikelihood,1); 6 | logMarginalLikelihood = ones(1,maxModelOrder); 7 | for iOrder = 1:maxModelOrder 8 | % find the non-NaN indices 9 | indices = find(~isnan(logPitchLikelihood(iOrder,:))); 10 | % find the maximum value 11 | maxLogMarginalLikelihood = max(logPitchLikelihood(iOrder,indices)); 12 | logMarginalLikelihood(iOrder) = maxLogMarginalLikelihood+... 13 | log(deltaFreq*sum(exp(... 14 | logPitchLikelihood(iOrder,indices)-maxLogMarginalLikelihood))); 15 | 16 | % log(trapz(exp(... 17 | % logPitchLikelihood(iOrder,indices)-maxLogMarginalLikelihood)))+log(deltaFreq)+maxLogMarginalLikelihood 18 | % log(sum( (exp(... 19 | % logPitchLikelihood(iOrder,indices)-maxLogMarginalLikelihood))))+log(deltaFreq)+maxLogMarginalLikelihood 20 | end 21 | end -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/computePitchLogLikelihood.m: -------------------------------------------------------------------------------- 1 | function [pitchLikelihood, pitchLogLikelihood] = ... 2 | computePitchLogLikelihood(cod, nData, delta) 3 | [maxModelOrder, nFreqs] = size(cod); 4 | pitchLogLikelihood = nan(maxModelOrder, nFreqs); 5 | for iOrder = 1:maxModelOrder 6 | [gHat, tauVar] = computeLaplaceParameters(cod(iOrder,:), 1, ... 7 | (nData-2*iOrder-delta)/2, nData/2); 8 | pitchLogLikelihood(iOrder,:) = ... 9 | log(gHat*(delta-2)/2)+(nData-2*iOrder-delta)/2*log(1+gHat)-... 10 | nData/2*log(1+gHat.*(1-cod(iOrder,:)))+... 11 | 1/2*log(2*pi*tauVar); 12 | end 13 | pitchLikelihood = exp(pitchLogLikelihood); 14 | end 15 | 16 | function [gHat, tauVar] = computeLaplaceParameters(cod, v, w, u) 17 | a = (1-cod)*(v+w-u); 18 | b = (u-v)*cod+2*v+w-u; 19 | gHat = (b+sqrt(b.^2-4*a*v))./(-2*a); 20 | tauVar = 1./(gHat.*(1-cod)*u./(1+gHat.*(1-cod)).^2-... 21 | gHat.*w./(1+gHat).^2); 22 | end 23 | 24 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/computePostModelPmf.m: -------------------------------------------------------------------------------- 1 | function postModelPmf = computePostModelPmf(logMarginalLikelihood, ... 2 | logModelPrior) 3 | scaledLogPostModelPmf = logMarginalLikelihood + logModelPrior; 4 | scaledPostModelPmf = ... 5 | exp(scaledLogPostModelPmf-max(scaledLogPostModelPmf)); 6 | postModelPmf = scaledPostModelPmf/sum(scaledPostModelPmf); 7 | end 8 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/computeRowsOfToeplitzHankelMatrix.m: -------------------------------------------------------------------------------- 1 | function rowMatrix = computeRowsOfToeplitzHankelMatrix(rowNumber,... 2 | nColumns, crossCorrelationVectors, hankelMatrixIsAdded, dcIsIncluded) 3 | % if rowNumber == 1 4 | % toeplitzRows = crossCorrelationVectors(1:nColumns,:); 5 | % else 6 | % toeplitzRows = ... 7 | % [flip(crossCorrelationVectors(2:rowNumber,:),1);... 8 | % crossCorrelationVectors(1:nColumns-rowNumber+1,:)]; 9 | % end 10 | % modified by Liming Shi for fast computation in MATLAB 11 | toeplitzRows=crossCorrelationVectors(rowNumber:-1:1,:); 12 | 13 | 14 | 15 | if dcIsIncluded && hankelMatrixIsAdded 16 | hankelOffset = 1; 17 | else 18 | hankelOffset = 3; 19 | end 20 | 21 | hankelRows = crossCorrelationVectors((0:nColumns-1)+... 22 | hankelOffset+rowNumber-1,:); 23 | 24 | if hankelMatrixIsAdded 25 | rowMatrix = toeplitzRows + hankelRows; 26 | else 27 | rowMatrix = toeplitzRows - hankelRows; 28 | end 29 | 30 | end 31 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/dynamicRangeLimiting.m: -------------------------------------------------------------------------------- 1 | %% dynamicRangeLimiting 2 | % Limit the dynamic range of nonnegative data 3 | % 4 | %% Syntax: 5 | % limitedNonnegativeData = ... 6 | % dynamicRangeLimiting(nonnegativeData, maxRangeDb) 7 | % 8 | %% Description: 9 | % Limit the dynamic range of nonnegative data. This is usefull for plotting 10 | % purposes, e.g., the the spectrogram. The data in the returned vector 11 | % satifies that 12 | % $$maxRangeDb >= 10*log10(max(limitedNonnegativeData)/... 13 | % min(limitedNonnegativeData))$$ 14 | % 15 | % * nonnegativeData: A vector of nonnegative data 16 | % * maxRangeDb: The maximum dynamic range in dB 17 | % * limitedNonnegativeData: The input vector with a limited dynamic range 18 | % 19 | %% Examples: 20 | % maxRangeDb = 60 dB; 21 | % limitedMagnitudeSpectrum = ... 22 | % dft2SymmetricDft(abs(fft(data)).^2, maxRangeDb); 23 | % 24 | function limitedNonnegativeData = ... 25 | dynamicRangeLimiting(nonnegativeData, maxRangeDb) 26 | if min(nonnegativeData) < 0 27 | error('dynamicRangeLimiting:argChk', ... 28 | 'All data must be nonnegative'); 29 | end 30 | logPowerSpectrum = 10*log10(nonnegativeData); 31 | limitedLogPowerSpectrum = max(logPowerSpectrum, ... 32 | max(max(logPowerSpectrum)-abs(maxRangeDb))); 33 | limitedNonnegativeData = 10.^(limitedLogPowerSpectrum/10); 34 | end -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/estnoiseg_orig.m: -------------------------------------------------------------------------------- 1 | function [x,zo]=estnoiseg_orig(yf,tz,pp) 2 | %ESTNOISEG - estimate MMSE noise spectrum [x,zo]=(yf,tz,pp) 3 | % 4 | % Usage: ninc=round(0.016*fs); % frame increment [fs=sample frequency] 5 | % ovf=2; % overlap factor 6 | % f=rfft(enframe(s,hanning(ovf*ninc,'periodic'),ninc),ovf*ninc,2); 7 | % f=f.*conj(f); % convert to power spectrum 8 | % x=estnoiseg(f,ninc/fs); % estimate the noise power spectrum 9 | % 10 | % Inputs: 11 | % yf input power spectra (one row per frame) 12 | % tz frame increment in seconds 13 | % Alternatively, the input state from a previous call (see below) 14 | % pp algorithm parameters [optional] 15 | % 16 | % Outputs: 17 | % x estimated noise power spectra (one row per frame) 18 | % zo output state 19 | % 20 | % The algorithm parameters are defined in reference [1] from which equation 21 | % numbers are given in parentheses. They are as follows: 22 | % 23 | % pp.tax % smoothing time constant for noise power estimate [0.0717 seconds](8) 24 | % pp.tap % smoothing time constant for smoothed speech prob [0.152 seconds](23) 25 | % pp.psthr % threshold for smoothed speech probability [0.99] (24) 26 | % pp.pnsaf % noise probability safety value [0.01] (24) 27 | % pp.pspri % prior speech probability [0.5] (18) 28 | % pp.asnr % active SNR in dB [15] (18) 29 | % pp.psini % initial speech probability [0.5] (23) 30 | % pp.tavini % assumed speech absent time at start [0.064 seconds] 31 | % 32 | % If convenient, you can call estnoiseg in chunks of arbitrary size. Thus the following are equivalent: 33 | % 34 | % (a) dp=estnoiseg(yp(1:300),tinc); 35 | % 36 | % (b) [dp(1:100,:),z]=estnoiseg(yp(1:100,:),tinc); 37 | % [dp(101:200,:),z]=estnoiseg(yp(101:200,:),z); 38 | % [dp(201:300,:),z]=estnoiseg(yp(201:300,:),z); 39 | 40 | 41 | % This is intended to be a precise implementation of [1] for a frame rate of 62.5 Hz. 42 | % Time constants are adjusted for other frame rates. 43 | % 44 | % Refs: 45 | % [1] Gerkmann, T. & Hendriks, R. C. 46 | % Unbiased MMSE-Based Noise Power Estimation With Low Complexity and Low Tracking Delay 47 | % IEEE Trans Audio, Speech, Language Processing, 2012, 20, 1383-1393 48 | 49 | % Copyright (C) Mike Brookes 2012 50 | % Version: $Id: estnoiseg.m 3387 2013-08-23 12:32:47Z dmb $ 51 | % 52 | % VOICEBOX is a MATLAB toolbox for speech processing. 53 | % Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html 54 | % 55 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 56 | % This program is free software; you can redistribute it and/or modify 57 | % it under the terms of the GNU General Public License as published by 58 | % the Free Software Foundation; either version 2 of the License, or 59 | % (at your option) any later version. 60 | % 61 | % This program is distributed in the hope that it will be useful, 62 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 63 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 64 | % GNU General Public License for more details. 65 | % 66 | % You can obtain a copy of the GNU General Public License from 67 | % http://www.gnu.org/copyleft/gpl.html or by writing to 68 | % Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA. 69 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 70 | 71 | [nr,nrf]=size(yf); % number of frames and freq bins 72 | x=zeros(nr,nrf); % initialize output arrays 73 | if isempty(yf) && isstruct(tz) % no real data 74 | zo=tz; % just keep the same state 75 | else 76 | if isstruct(tz) % take parameters from a previous call 77 | nrcum=tz.nrcum; % cumulative number of frames 78 | xt=tz.xt; % smoothed power spectrum 79 | pslp=tz.pslp; % correction factor (9) 80 | tinc=tz.tinc; % frame increment 81 | qq=tz.qq; % parameter structure 82 | else 83 | tinc = tz; % second argument is frame increment 84 | nrcum=0; % no frames so far 85 | % default algorithm constants 86 | qq.tax=0.0717; % noise output smoothing time constant = -tinc/log(0.8) (8) 87 | qq.tap=0.152; % speech prob smoothing time constant = -tinc/log(0.9) (23) 88 | qq.psthr=0.99; % threshold for smoothed speech probability [0.99] (24) 89 | qq.pnsaf=0.01; % noise probability safety value [0.01] (24) 90 | qq.pspri=0.5; % prior speech probability [0.5] (18) 91 | qq.asnr=15; % active SNR in dB [15] (18) 92 | qq.psini=0.5; % initial speech probability [0.5] (23) 93 | qq.tavini=0.064; % assumed speech absent time at start [64 ms] 94 | 95 | if nargin>=3 && ~isempty(pp) % update fields from pp input 96 | qqn=fieldnames(qq); 97 | for i=1:length(qqn) 98 | if isfield(pp,qqn{i}) 99 | qq.(qqn{i})=pp.(qqn{i}); 100 | end 101 | end 102 | end 103 | pslp=repmat(qq.psini,1,nrf); % initialize smoothed speech presence prob 104 | xt=[]; % initialize just in case the first call has no data 105 | end 106 | 107 | % unpack parameters needed within the loop 108 | 109 | psthr=qq.psthr; % threshold for smoothed speech probability [0.99] (24) 110 | pnsaf=qq.pnsaf; % noise probability safety value [0.01] (24) 111 | 112 | % derived algorithm constants 113 | 114 | ax=exp(-tinc/qq.tax); % noise output smoothing factor = 0.8 (8) 115 | axc=1-ax; 116 | ap=exp(-tinc/qq.tap); % noise output smoothing factor = 0.9 (23) 117 | apc=1-ap; 118 | xih1=10^(qq.asnr/10); % speech-present SNR 119 | xih1r=1/(1+xih1)-1; 120 | pfac=(1/qq.pspri-1)*(1+xih1); % p(noise)/p(speech) (18) 121 | 122 | if nrcum==0 && nr>0 % initialize values for first frame 123 | xt=qq.psini*mean(yf(1:max(1,min(nr,round(1+qq.tavini/tinc))),:),1); % initial noise estimate 124 | end 125 | 126 | % loop for each frame 127 | for t=1:nr 128 | yft=yf(t,:); % noisy speech power spectrum 129 | ph1y=(1+pfac*exp(xih1r*yft./xt)).^(-1); % a-posteriori speech presence prob (18) 130 | pslp=ap*pslp+apc*ph1y; % smoothed speech presence prob (23) 131 | ph1y=min(ph1y,1-pnsaf*(pslp>psthr)); % limit ph1y (24) 132 | xtr=(1-ph1y).*yft+ph1y.*xt; % estimated raw noise spectrum (22) 133 | xt=ax*xt+axc*xtr; % smooth the noise estimate (8) 134 | x(t,:)=xt; % save the noise estimate 135 | end 136 | if nargout>1 % we need to store the state for next time 137 | zo.nrcum=nrcum+nr; % number of frames so far 138 | zo.xt=xt; % smoothed power spectrum 139 | zo.pslp=pslp; % correction factor (9) 140 | zo.tinc=tinc; % must be the last one 141 | zo.qq=qq; 142 | end 143 | if ~nargout 144 | clf; 145 | subplot(212); 146 | plot((1:nr)*tinc,10*log10([sum(yf,2) sum(x,2)])) 147 | ylabel('Frame Energy (dB)'); 148 | xlabel(sprintf('Time (s) [%d ms frame incr]',round(tinc*1000))); 149 | axisenlarge([-1 -1.05]); 150 | legend('input','noise','Location','Best'); 151 | subplot(211); 152 | plot(1:nrf,10*log10([sum(yf,1)'/nr sum(x,1)'/nr])) 153 | ylabel('Power (dB)'); 154 | xlabel('Frequency bin'); 155 | axisenlarge([-1 -1.05]); 156 | legend('input','noise','Location','Best'); 157 | end 158 | end -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/generator.m: -------------------------------------------------------------------------------- 1 | function x = generator(N, ell, f0, alpha) 2 | % 3 | % Generates a harmonic signal 4 | % 5 | 6 | modelOrders = (1:ell)'; 7 | n = (-(N-1)/2:-(N-1)/2+N-1)'; 8 | Z = exp(1i*2*pi*f0*n*modelOrders'); 9 | sinusoidalMatrix = [ones(N, 1), real(Z), -imag(Z)]; 10 | x = sinusoidalMatrix*alpha; 11 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/goldenSectionSearch.m: -------------------------------------------------------------------------------- 1 | %% goldenSectionSearch 2 | % Single variable bounded minisation using a golden section search 3 | % 4 | %% Syntax: 5 | % [lowerFinalBound, upperFinalBound] = goldenSectionSearch(objectiveFunction,... 6 | % lowerInitialBound, upperInitialBound, requiredInterval); 7 | % 8 | %% Description: 9 | % Narrows down the minimum of a function from an initial interval to smaller 10 | % interval using af golden section search. 11 | % The implementation is based on Sec. 4.4 in 12 | % A. Antoniou and W.-S. Lu, Practical Optimization: Algorithms and Engineering 13 | % Applications. Springer, Mar. 2007. 14 | % * objectiveFunction: A function handle of the function to be minimised 15 | % * lowerInitialBound: The lower initial bound of the minimiser 16 | % * upperInitialBound: The upper initial bound of the minimiser 17 | % * requiredInterval: The required final interval of uncertainty 18 | % * lowerFinalBound: The final lower bound 19 | % * upperFinalBound: The final upper bound 20 | %% Examples: 21 | % f = @(x) x.^2-2*x-3; 22 | % lowerBound = -2; 23 | % upperBound = 5; 24 | % requiredUncertainty = 1e-3; 25 | % [lowerBound, upperBound] = goldenSectionSearch(f,lowerBound,upperBound,... 26 | % requiredUncertainty); 27 | % estimatedMinimiser = (upperBound+lowerBound)/2; 28 | % 29 | function [lowerFinalBound, upperFinalBound] = goldenSectionSearch(objectiveFunction,... 30 | lowerInitialBound, upperInitialBound, requiredInterval) 31 | % Check the input arguments 32 | if nargin<4 33 | error('goldenSectionSearch:argChk','Four input arguments are required.'); 34 | end 35 | validateObjectiveFunction(objectiveFunction); 36 | validateBound(lowerInitialBound); 37 | validateBound(upperInitialBound); 38 | initialInterval = upperInitialBound-lowerInitialBound; 39 | if initialInterval<=0 40 | error('goldenSectionSearch:argChk',... 41 | 'The lower bound must be smaller than the upper bound.'); 42 | end 43 | validateInterval(requiredInterval); 44 | % Perform the golden section search 45 | [lowerFinalBound, upperFinalBound] = narrowBounds(objectiveFunction,... 46 | lowerInitialBound, upperInitialBound, requiredInterval); 47 | end 48 | 49 | % Return an error if the objective function is invalid 50 | function validateObjectiveFunction(objectiveFunction) 51 | if ~isa(objectiveFunction, 'function_handle') 52 | error('goldenSectionSearch:argChk',... 53 | 'The input argument must be a function handle'); 54 | end 55 | end 56 | 57 | % Return an error if the bound is invalid 58 | function validateBound(bound) 59 | if ~isscalar(bound) || ~isfinite(bound) 60 | error('goldenSectionSearch:argChk',... 61 | 'The bounds must be real-valued scalars.'); 62 | end 63 | end 64 | 65 | % Return an error if the interval is invalid 66 | function validateInterval(interval) 67 | if ~isscalar(interval) || ~isfinite(interval) ||... 68 | interval<=0 69 | error('goldenSectionSearch:argChk',... 70 | 'The required interval must be a positive real-valued scalar.'); 71 | end 72 | end 73 | 74 | % Run the golden section search algorithm to narrow down the lower and upper 75 | % bound for the minimiser to within a tolerance of at most +/-requiredInterval/2. 76 | % The algorithm is based on algorithm 4.2 in A. Antoniou and W.-S. Lu, 77 | % Practical Optimization: Algorithms and Engineering Applications. 78 | % Springer, Mar. 2007. 79 | function [lowerBound, upperBound] = narrowBounds(objectiveFunction,... 80 | lowerBound, upperBound, requiredInterval) 81 | goldenRatio = 0.5+sqrt(1.25); 82 | startInterval = upperBound-lowerBound; 83 | iInterval = startInterval/goldenRatio; 84 | variableLowerVal = upperBound-iInterval; 85 | funcLowerVal = objectiveFunction(variableLowerVal); 86 | variableUpperVal = lowerBound+iInterval; 87 | funcUpperVal = objectiveFunction(variableUpperVal); 88 | while iInterval > requiredInterval 89 | iInterval = iInterval/goldenRatio; 90 | if funcLowerVal > funcUpperVal 91 | % The minimum is in the interval [variableLowerVal;upperBound] 92 | lowerBound = variableLowerVal; 93 | variableLowerVal = variableUpperVal; 94 | variableUpperVal = lowerBound+iInterval; 95 | funcLowerVal = funcUpperVal; 96 | funcUpperVal = objectiveFunction(variableUpperVal); 97 | else 98 | % The minimum is in the interval [lowerBound;variableUpperVal] 99 | upperBound = variableUpperVal; 100 | variableUpperVal = variableLowerVal; 101 | variableLowerVal = upperBound-iInterval; 102 | funcUpperVal = funcLowerVal; 103 | funcLowerVal = objectiveFunction(variableLowerVal); 104 | end 105 | % If the final search tolerance is within the precision of 106 | % the computer, then stop 107 | if variableLowerVal>variableUpperVal 108 | break; 109 | end 110 | end 111 | % When iInterval is smaller than the required interval, we make one final 112 | % comparison so that (upperBound-lowerBound) funcUpperVal 114 | % The minimum is in the interval [variableLowerVal;upperBound] 115 | lowerBound = variableLowerVal; 116 | elseif funcLowerVal == funcUpperVal 117 | % The minimum is in the interval [variableLowerVal;variableUpperVal] 118 | lowerBound = variableLowerVal; 119 | upperBound = variableUpperVal; 120 | else 121 | % The minimum is in the interval [lowerBound;variableUpperVal] 122 | upperBound = variableUpperVal; 123 | end 124 | end 125 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/objFunction.m: -------------------------------------------------------------------------------- 1 | function varargout = objFunction(f0, x, l, dcIsIncluded, varargin) 2 | % 3 | % Computes the objective of the function 4 | % 5 | % f(f0, l) = x^T Z_l(f0)(Z_l(f0)^T Z_l(f0))^-1 Z_l^T(f0) x 6 | % 7 | % Input: 8 | % omega: fundamental frequency in radians 9 | % x: x length N 10 | % l: model order 11 | % epsilon: Regularization (default epsilon=0) 12 | % 13 | % Output: 14 | % objective: f(\omega, l) 15 | % alpha : (optional) least-squares solution 16 | % 17 | 18 | N = length(x); 19 | 20 | epsilon = 0; 21 | if length(varargin) == 2 22 | epsilon = N*varargin{2}; 23 | end 24 | 25 | n = (0:N-1)'-(N-1)/2; 26 | 27 | E = exp(1i*2*pi*f0*n*(1:l)); 28 | if dcIsIncluded 29 | C = [ones(N, 1), real(E)]; %cos(omega*n'*(1:l)); 30 | else 31 | C = real(E); 32 | end 33 | 34 | S = imag(E); %sin(omega*n'*(1:l)); 35 | bc = C'*x; 36 | bs = -S'*x; 37 | 38 | ac = (C'*C+epsilon*eye(size(C, 2)))\bc; % just solve it using an O(n^3) algorithm for now 39 | as = (S'*S+epsilon*eye(l))\bs; 40 | 41 | obj = bc'*ac + bs'*as; 42 | varargout{1} = obj; 43 | 44 | if nargout >= 2 45 | alpha = [ac; as]; 46 | varargout{2} = alpha; 47 | end 48 | 49 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/private/singlePitchNLSCostsNaive.m: -------------------------------------------------------------------------------- 1 | %% singlePitchMlCostFunctionNaiveImplementationMod 2 | % A naive implementation of the single pitch ML cost-function. 3 | % 4 | %% Syntax: 5 | %# [costFunctionMatrix,fullPitchGrid] = ... 6 | %# singlePitchMlCostFunctionNaiveImplementation(data, maxModelOrder, ... 7 | %# resolution, pitchBounds) 8 | % 9 | %% Description: 10 | % A naive implementation of the single pitch ML cost-function. 11 | % The cost function is computed on a uniform (Fourier) grid for all model 12 | % orders up to the model orders specified by maxModelOrder. DC is also 13 | % included in the model. 14 | % 15 | % * data: A data vector of real- or complex-valued data. 16 | % * maxModelOrder: The maximum number of harmonic components that the cost 17 | % function is evaluated for. 18 | % * resolution: The resolution of the uniform pitch grid that the cost functions 19 | % are evaluated for. 20 | % * pitchBounds: A 2D vector specifiyng the lower and upper bound for the pitch 21 | % in cycles/sample. 22 | % * costFunctionMatrix: A matrix of cost functions. Each row corresponds to the 23 | % the cost function for a candidate model order. 24 | % * fullPitchGrid: The pitches corresponding to the values in the rows of the 25 | % cost function matrix. 26 | % 27 | %% Examples: 28 | %# data = recordedData; 29 | %# nData = length(data); 30 | %# maxModelOrder = 10; 31 | %# resolution = 1/(5*nData); 32 | %# pitchBounds = [1/nData;0.5-1/nData]; 33 | %# [costFunctionMatrix,fullPitchGrid] = ... 34 | %# singlePitchMlCostFunctionNaiveImplementationMod(data, maxModelOrder, ... 35 | %# resolution, pitchBounds); 36 | % 37 | function [costFunctionMatrix,fullPitchGrid, varargout] = ... 38 | singlePitchNLSCostsNaive(data,maxModelOrder,... 39 | resolution,pitchBounds,dcIsIncluded) 40 | 41 | nData = length(data); 42 | dataAreRealValued = isreal(data); 43 | time = (0:nData-1)'-(nData-1)/2; 44 | nFftGrid = ceil(1/resolution); 45 | minFftIndex = ceil(nFftGrid*pitchBounds(1)); 46 | maxFftIndex = floor(nFftGrid*pitchBounds(2)); 47 | validFftIndices = (minFftIndex:maxFftIndex)'; 48 | fullPitchGrid = validFftIndices/nFftGrid; 49 | nPitches = length(fullPitchGrid); 50 | % initialisation 51 | costFunctionMatrix = nan(maxModelOrder,maxFftIndex-minFftIndex+1); 52 | if dcIsIncluded 53 | phiMatrix = costFunctionMatrix; 54 | dcMatrix = costFunctionMatrix; 55 | end 56 | 57 | for iOrder = 1:maxModelOrder 58 | if dataAreRealValued 59 | maxFftIndex = ... 60 | floor(min(nFftGrid*pitchBounds(2),nFftGrid/(2*iOrder)-1)); 61 | else 62 | maxFftIndex = ... 63 | floor(min(nFftGrid*pitchBounds(2),nFftGrid/iOrder-1)); 64 | end 65 | pitchGrid = (minFftIndex:maxFftIndex)'/nFftGrid; 66 | nPitches = length(pitchGrid); 67 | modelOrders = 1:iOrder; 68 | for jPitch = 1:nPitches 69 | pitch = pitchGrid(jPitch); 70 | expMatrix = exp(1i*2*pi*pitch*time*modelOrders); 71 | if dataAreRealValued 72 | if dcIsIncluded 73 | sinusoidalMatrix = [ones(nData,1), real(expMatrix),... 74 | imag(expMatrix)]; 75 | else 76 | sinusoidalMatrix = [real(expMatrix),... 77 | imag(expMatrix)]; 78 | end 79 | else 80 | if dcIsIncluded 81 | sinusoidalMatrix = [ones(nData,1), expMatrix]; 82 | else 83 | sinusoidalMatrix = expMatrix; 84 | end 85 | 86 | end 87 | linearParameters = sinusoidalMatrix\data; 88 | if dcIsIncluded 89 | inverseFirstColumn = ... 90 | (sinusoidalMatrix'*sinusoidalMatrix)\[1;zeros(2*iOrder,1)]; 91 | dcMatrix(iOrder,jPitch) = linearParameters(1); 92 | phiMatrix(iOrder,jPitch) = inverseFirstColumn(1); 93 | end 94 | costFunctionMatrix(iOrder,jPitch) = ... 95 | real((data'*sinusoidalMatrix)*linearParameters); 96 | end 97 | end 98 | if dcIsIncluded 99 | varargout{1} = phiMatrix; 100 | varargout{2} = dcMatrix; 101 | else 102 | varargout = {}; 103 | end 104 | end 105 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/run_colored_example.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | close all; 4 | %% read speech signals 5 | [cleanspeech, samplingFreq] = audioread(['CleanSpeech.wav']); 6 | %% generate noisy data 7 | SNR=0; 8 | load factoryNoise.mat 9 | noise=resample(factoryNoise,samplingFreq,16000); 10 | randstart=randi(length(noise)-length(cleanspeech)-100); 11 | noise_seg=noise(randstart:randstart+length(cleanspeech)-1); 12 | scaled_noise=addnoise(cleanspeech,noise_seg,SNR); 13 | NoisySignal=cleanspeech+scaled_noise; 14 | %% process the data 15 | % the third input argument is the plot flag, 16 | % when plot_flag=0, results will not be given in figure; 17 | % when plot_flag=1, results will be given in figure; 18 | 19 | % the fourth input argument is the pre-whitening flag, 20 | % when prew_flag=0, pre-whitening will be disabled, and 21 | % when prew_flag=1, pre-whitening will be enabled 22 | 23 | % the fifth input argument is the parameter set you can customize yourself, 24 | plot_flag=1; 25 | prew_flag=1; 26 | tic 27 | F0_result=BF0NLS(NoisySignal,samplingFreq,plot_flag,prew_flag); 28 | toc -------------------------------------------------------------------------------- /BF0NLS_MATLAB/run_music_example.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | close all; 4 | %% read music signals 5 | [vib_flute, samplingFreq] = audioread(['vib_flute.wav']);vib_flute=vib_flute(:,1); 6 | %% generate noisy data 7 | SNR=0; 8 | noise=randn(size(vib_flute)); % White Gaussian noise 9 | scaled_noise=addnoise(vib_flute,noise,SNR); 10 | NoisySignal=vib_flute+scaled_noise; 11 | %% process the data 12 | % the third input argument is the plot flag, 13 | % when plot_flag=0, results will not be given in figure; 14 | % when plot_flag=1, results will be given in figure; 15 | 16 | % the fourth input argument is the pre-whitening flag, 17 | % when prew_flag=0, pre-whitening will be disabled, and 18 | % when prew_flag=1, pre-whitening will be enabled 19 | 20 | % the fifth input argument is the parameter set you can customize yourself, 21 | plot_flag=1; 22 | prew_flag=0; 23 | Par_set.f0Bounds = [100, 1000]; % Pitch boundaries for music signal (prior information) 24 | tic 25 | F0_result=BF0NLS(NoisySignal,samplingFreq,plot_flag,prew_flag,Par_set); 26 | toc 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/run_white_example.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | close all; 4 | %% read speech signals 5 | [cleanspeech, samplingFreq] = audioread(['CleanSpeech.wav']);cleanspeech=cleanspeech(:,1); 6 | %% generate noisy data 7 | SNR=0; 8 | noise=randn(size(cleanspeech)); % White Gaussian noise 9 | scaled_noise=addnoise(cleanspeech,noise,SNR); 10 | NoisySignal=cleanspeech+scaled_noise; 11 | %% process the data 12 | % the third input argument is the plot flag, 13 | % when plot_flag=0, results will not be given in figure; 14 | % when plot_flag=1, results will be given in figure; 15 | 16 | % the fourth input argument is the pre-whitening flag, 17 | % when prew_flag=0, pre-whitening will be disabled, and 18 | % when prew_flag=1, pre-whitening will be enabled 19 | 20 | % the fifth input argument is the parameter set you can customize yourself, 21 | plot_flag=1; 22 | prew_flag=0; 23 | tic 24 | F0_result=BF0NLS(NoisySignal,samplingFreq,plot_flag,prew_flag); 25 | toc 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /BF0NLS_MATLAB/vib_flute.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_MATLAB/vib_flute.wav -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_realtimeDemo_MATLAB/.DS_Store -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/BayesianfastF0NLS.m: -------------------------------------------------------------------------------- 1 | classdef BayesianfastF0NLS< handle 2 | 3 | % Can only be set in the constructor 4 | properties (SetAccess=immutable) 5 | N 6 | L 7 | F 8 | pitchBoundsOuter = [0.0 0.5] % The outer bounds that are acceptable 9 | 10 | % default values 11 | epsilon = 0.0 12 | dcIsIncluded = false 13 | epsilon_ref = 0.0 14 | 15 | % Precomputed quantities 16 | crossCorrelationVectors 17 | Gamma1 18 | Gamma2 19 | fftShiftVector 20 | end 21 | 22 | properties (SetAccess=private) 23 | pitchBounds % The current active bounds 24 | fullPitchGrid 25 | validFftIndices 26 | defaultRefinementTol 27 | refinementTol 28 | gPriorParam = 3 29 | logPitchPdfs % the pitch pdf (column) for every candidate model order 30 | logModelPmf % an (L+1)x1 vector 31 | logpi 32 | A 33 | scaled_alpha_buffer 34 | scaled_alpha_buffer2 35 | unvoicing_scaled_alpha_buffer 36 | logModelPrior; 37 | varSpeech=5e-6; 38 | B 39 | C 40 | norml_factor=0; 41 | cnt=1; 42 | end 43 | 44 | methods 45 | 46 | function obj = BayesianfastF0NLS(N, L, pitchBounds, A_var,voicingProb,varargin) 47 | 48 | % validate input 49 | if length(varargin) >= 1 50 | if islogical(varargin{1}) 51 | obj.dcIsIncluded = varargin{1}; 52 | else 53 | error('Argument 4 is not of type logical (true/false)') 54 | end 55 | end 56 | if length(varargin) >= 2 57 | if isscalar(varargin{2}) 58 | obj.F = varargin{2}; 59 | else 60 | error('Argument 5 is not a scalar') 61 | end 62 | else 63 | obj.F = 2^13; 64 | end 65 | obj.defaultRefinementTol = 1/obj.F; 66 | 67 | if length(varargin) >= 3 68 | if isscalar(varargin{3}) 69 | obj.epsilon = varargin{3}; 70 | else 71 | error('Argument 6 is not a scalar') 72 | end 73 | end 74 | 75 | if length(varargin) > 4 76 | error('Too many input arguments') 77 | end 78 | 79 | if ~isscalar(N) 80 | error('Input argument N is not a scalar') 81 | else 82 | obj.N = N; 83 | end 84 | if ~isscalar(L) 85 | error('Input argument L is not a scalar') 86 | else 87 | obj.L = L; 88 | end 89 | 90 | if ~ (isvector(pitchBounds) && length(pitchBounds) == 2) 91 | error(['Input argument pitchBound must be a 2-' ... 92 | 'vector']) 93 | elseif pitchBounds(1) < obj.pitchBoundsOuter(1) || ... 94 | pitchBounds(2) > obj.pitchBoundsOuter(2) 95 | 96 | error(['Input argument pitchBounds must be within the ' ... 97 | 'bounds specified in the constructor (at ' ... 98 | 'least [0.0 0.5])']) 99 | else 100 | obj.pitchBounds = pitchBounds; 101 | end 102 | 103 | if pitchBounds(1) < 1/N 104 | warning(['The lower pitch bound is set lower than one '... 105 | ' period/segment. Inaccurate results might be '... 106 | 'produced - especially if you do not set the'... 107 | ' regularisation parameter.']); 108 | end 109 | 110 | % Init 111 | F = obj.F; 112 | minFftIndex = ceil(F*pitchBounds(1)); 113 | maxFftIndex = floor(F*pitchBounds(2)); 114 | obj.validFftIndices = (minFftIndex:maxFftIndex)'; 115 | obj.fullPitchGrid = obj.validFftIndices/F; 116 | nPitches = length(obj.fullPitchGrid); 117 | obj.logModelPrior=[voicingProb,1-voicingProb]; 118 | 119 | % cross-correlation vectors 120 | obj.crossCorrelationVectors = ... 121 | [N*ones(1, nPitches)/2 + N*obj.epsilon;... 122 | sin(pi*(1:2*L)'*obj.fullPitchGrid'*N)./... 123 | (2*sin(pi*(1:2*L)'*obj.fullPitchGrid'))]; 124 | 125 | obj.fftShiftVector = ... 126 | exp(1i*2*pi*(0:ceil(F/2)-1)'*(N-1)/(2*F)); 127 | 128 | % Compute Gamma for the T+H and T-H systems 129 | [obj.Gamma1, obj.Gamma2] = computeGamma(L, F, pitchBounds, ... 130 | obj.crossCorrelationVectors, nPitches, ... 131 | obj.validFftIndices, ... 132 | obj.dcIsIncluded); 133 | %% added by Liming Shi 134 | obj.scaled_alpha_buffer=nan; 135 | grid_width=diff(obj.fullPitchGrid(1:2)); 136 | % obj.logpi=(log(1/(nPitches-1))-log(grid_width))*ones(nPitches,1); 137 | obj.logpi=log((voicingProb)/(nPitches*L))*ones(nPitches,1); 138 | obj.A=zeros(nPitches,nPitches); 139 | 140 | 141 | for jj=1:nPitches 142 | % f0=obj.fullPitchGrid(jj); 143 | % obj.A(jj,:)= abs(sin(pi*(obj.fullPitchGrid-f0)/f0)./pi./(obj.fullPitchGrid-f0)*f0)+.1; 144 | obj.A(jj,:)=(normpdf(obj.fullPitchGrid,obj.fullPitchGrid(jj),A_var)); 145 | % var_value=1e-1; 146 | % obj.logA(jj,:)=log(lognpdf(obj.fullPitchGrid,log(obj.fullPitchGrid(jj)*exp(var_value)),var_value)); 147 | % obj.logA(jj,:)=log(normpdf(log(obj.fullPitchGrid),log(obj.fullPitchGrid(jj)),.1)); 148 | end 149 | 150 | 151 | obj.A=obj.A./repmat(sum(obj.A,2),1,nPitches); 152 | 153 | obj.B=zeros(obj.L,obj.L); 154 | 155 | 156 | for jj=1:obj.L 157 | obj.B(jj,:)=(normpdf(jj,[1:obj.L],1)); 158 | end 159 | 160 | 161 | obj.B=obj.B./repmat(sum(obj.B,2),1,obj.L); 162 | 163 | obj.C=[.7 .3;.4,.6]; 164 | 165 | obj.scaled_alpha_buffer2=1/obj.L/nPitches*ones(nPitches,obj.L); 166 | 167 | end 168 | 169 | function varargout = computeCostFunctions(obj, x) 170 | % Compute and returns the cost functions for l=1,...,L 171 | 172 | % validate input 173 | if ~isvector(x) && length(x) == obj.N 174 | error(['First argument x must be vector of ' ... 175 | 'length N=', num2str(obj.N)]); 176 | end 177 | x = reshape(x, obj.N, 1); % make sure its a column 178 | % vector 179 | 180 | 181 | varargout{1} = computeAllCostFunctions(x, obj.L, ... 182 | obj.fullPitchGrid, obj.fftShiftVector, ... 183 | obj.crossCorrelationVectors, obj.Gamma1, obj.Gamma2, ... 184 | obj.dcIsIncluded); 185 | 186 | if nargout == 2 187 | varargout{2} = obj.fullPitchGrid; 188 | end 189 | 190 | end 191 | 192 | function varargout = estimate(obj, x, flag,varargin) 193 | % Estimate fundamental frequency and order of the signal x 194 | 195 | % validate input 196 | if ~isvector(x) && length(x) == obj.N 197 | error(['First argument x must be vector of ' ... 198 | 'length N=', num2str(obj.N)]); 199 | end 200 | x = reshape(x, obj.N, 1); % make sure its a column 201 | % vector 202 | 203 | if length(varargin) == 1 204 | if isscalar(varargin{1}) 205 | obj.refinementTol = varargin{1}; 206 | else 207 | error('Argument 2 is not a scalar') 208 | end 209 | else 210 | obj.refinementTol = obj.defaultRefinementTol; 211 | end 212 | % if the data consists of all zeros then return zero model 213 | % obj.norml_factor=obj.norml_factor+x'*x; 214 | % sumE=sqrt(obj.norml_factor/obj.cnt/length(x)); 215 | % obj.cnt=obj.cnt+1; 216 | % scale=sqrt(3.1623e-5)/sumE; 217 | % if obj.cnt>=100 218 | % x=x*scale; 219 | % end 220 | if x'*x/obj.N<1e-16 221 | estimatedPitch = nan; 222 | estimatedOrder = 0; 223 | unvoicing_scaled_alpha=log(1); 224 | else 225 | % Step 2: compute the profile log-likelihood function 226 | % over only the fundamental frequency (the linear 227 | % parameters, noise variance and g have been integrated 228 | % out) 229 | % tic 230 | costs = obj.computeCostFunctions(x); 231 | % toc 232 | cod = costs*(1/(x'*x+obj.varSpeech*obj.N)); 233 | % cod = costs*(1/(x'*x)); 234 | [~, pitchLogLikelihood] = ... 235 | computePitchLogLikelihood(cod, obj.N, obj.gPriorParam); 236 | % for ii=1:10 237 | % lok(ii,:)=log(hypergeom([length(x)/2,1],(2*ii+3)/2,cod(ii,:))/(2*ii+1)); 238 | % end 239 | % normparameter=log_sumsum_exp_ls(pitchLogLikelihood); 240 | % pitchLogLikelihood=pitchLogLikelihood-log_sumsum_exp_ls(pitchLogLikelihood); 241 | null_modellike=1; 242 | 243 | %% added/modified by Liming Shi (implements the hidden markov chain) 244 | if isnan(obj.scaled_alpha_buffer) 245 | inx=isnan(pitchLogLikelihood); 246 | pitchLogLikelihood(inx)=-inf; 247 | bar_alpha=obj.logpi+pitchLogLikelihood'; 248 | 249 | unvoicing_bar_alpha=log(obj.logModelPrior(2)*null_modellike); 250 | log_scale=log_sumsum_exp_ls([[unvoicing_bar_alpha,-inf*ones(1,obj.L-1)];bar_alpha]); 251 | scaled_alpha=bar_alpha-log_scale; 252 | unvoicing_scaled_alpha=unvoicing_bar_alpha-log_scale; 253 | % log_scale=log_trapz_exp_ls(bar_alpha,1); 254 | % scaled_alpha=bar_alpha-log_scale-log(grid_width); 255 | else 256 | inx=isnan(pitchLogLikelihood); 257 | pitchLogLikelihood(inx)=-inf; 258 | state_prior=obj.C(1,1)*obj.A'*obj.scaled_alpha_buffer*obj.B; 259 | % state_prior=state_prior+1/obj.L/length(obj.fullPitchGrid)*obj.C(2,1)*obj.unvoicing_scaled_alpha_buffer; 260 | state_prior=state_prior+obj.scaled_alpha_buffer2*obj.C(2,1)*obj.unvoicing_scaled_alpha_buffer; 261 | % plot(state_prior);drawno2w; 262 | bar_alpha=log(state_prior)+pitchLogLikelihood'; 263 | 264 | temp=[1-obj.unvoicing_scaled_alpha_buffer;obj.unvoicing_scaled_alpha_buffer]; 265 | % sum(sum(state_prior))+obj.C(:,2)'*temp 266 | unvoicing_bar_alpha=log(obj.C(:,2)'*temp*null_modellike); 267 | log_scale=log_sumsum_exp_ls([[unvoicing_bar_alpha,-inf*ones(1,obj.L-1)];bar_alpha]); 268 | scaled_alpha=bar_alpha-log_scale; 269 | unvoicing_scaled_alpha=unvoicing_bar_alpha-log_scale; 270 | 271 | end 272 | 273 | [value, inx] = ... 274 | max(scaled_alpha); 275 | [~,inx_2]=max(value); 276 | pitchIndex=inx(inx_2); 277 | estimatedOrder=inx_2; 278 | estimatedPitch = obj.fullPitchGrid(pitchIndex(1)); 279 | %% added by Liming Shi (buffering the previous meaningful estimates of the posterior states) 280 | 281 | 282 | if unvoicing_scaled_alpha < log(0.5) 283 | obj.scaled_alpha_buffer2=exp(scaled_alpha-log_sumsum_exp_ls(scaled_alpha)); 284 | else 285 | estimatedOrder=nan; 286 | end 287 | obj.scaled_alpha_buffer=exp(scaled_alpha); 288 | obj.unvoicing_scaled_alpha_buffer=exp(unvoicing_scaled_alpha); 289 | end 290 | 291 | %% 292 | 293 | if nargout >= 1 294 | varargout{1} = estimatedPitch; 295 | end 296 | if nargout >= 2 297 | varargout{2} = estimatedOrder; 298 | end 299 | if nargout >= 3 300 | % [~, alpha] = objFunction(estimatedPitch, x, ... 301 | % estimatedOrder, obj.dcIsIncluded); 302 | varargout{3} = 1-exp(unvoicing_scaled_alpha); 303 | end 304 | 305 | end 306 | end 307 | end 308 | function y=log_sumsum_exp_ls(x) 309 | max_temp=max(max(x)); 310 | inf_ind=isinf(max_temp); 311 | y=log(sum(sum(exp(x-max_temp))))+max_temp; 312 | y(inf_ind)=-inf; 313 | end 314 | 315 | 316 | function y=log_sum_exp_ls(x,dim) 317 | if nargin ==1 318 | dim=1; 319 | end 320 | max_temp=max(x,[],dim); 321 | inf_ind=isinf(max_temp); 322 | y=log(sum(exp(x-max_temp),dim))+max_temp; 323 | y(inf_ind)=-inf; 324 | end 325 | 326 | 327 | function y=log_trapz_exp_ls(x,dim) 328 | if nargin ==1 329 | dim=1; 330 | end 331 | max_temp=max(x,[],dim); 332 | inf_ind=isinf(max_temp); 333 | y=log(trapz(exp(x-max_temp),dim))+max_temp; 334 | y(inf_ind)=-inf; 335 | end -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/SX36.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_realtimeDemo_MATLAB/SX36.wav -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/babble.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_realtimeDemo_MATLAB/babble.mat -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/estnoiseg.m: -------------------------------------------------------------------------------- 1 | function [x,zo]=estnoiseg(yf,tz,pp) 2 | %ESTNOISEG - estimate MMSE noise spectrum [x,zo]=(yf,tz,pp) 3 | % 4 | % Usage: ninc=round(0.016*fs); % frame increment [fs=sample frequency] 5 | % ovf=2; % overlap factor 6 | % f=rfft(enframe(s,hanning(ovf*ninc,'periodic'),ninc),ovf*ninc,2); 7 | % f=f.*conj(f); % convert to power spectrum 8 | % x=estnoiseg(f,ninc/fs); % estimate the noise power spectrum 9 | % 10 | % Inputs: 11 | % yf input power spectra (one row per frame) 12 | % tz frame increment in seconds 13 | % Alternatively, the input state from a previous call (see below) 14 | % pp algorithm parameters [optional] 15 | % 16 | % Outputs: 17 | % x estimated noise power spectra (one row per frame) 18 | % zo output state 19 | % 20 | % The algorithm parameters are defined in reference [1] from which equation 21 | % numbers are given in parentheses. They are as follows: 22 | % 23 | % pp.tax % smoothing time constant for noise power estimate [0.0717 seconds](8) 24 | % pp.tap % smoothing time constant for smoothed speech prob [0.152 seconds](23) 25 | % pp.psthr % threshold for smoothed speech probability [0.99] (24) 26 | % pp.pnsaf % noise probability safety value [0.01] (24) 27 | % pp.pspri % prior speech probability [0.5] (18) 28 | % pp.asnr % active SNR in dB [15] (18) 29 | % pp.psini % initial speech probability [0.5] (23) 30 | % pp.tavini % assumed speech absent time at start [0.064 seconds] 31 | % 32 | % If convenient, you can call estnoiseg in chunks of arbitrary size. Thus the following are equivalent: 33 | % 34 | % (a) dp=estnoiseg(yp(1:300),tinc); 35 | % 36 | % (b) [dp(1:100,:),z]=estnoiseg(yp(1:100,:),tinc); 37 | % [dp(101:200,:),z]=estnoiseg(yp(101:200,:),z); 38 | % [dp(201:300,:),z]=estnoiseg(yp(201:300,:),z); 39 | 40 | 41 | % This is intended to be a precise implementation of [1] for a frame rate of 62.5 Hz. 42 | % Time constants are adjusted for other frame rates. 43 | % 44 | % Refs: 45 | % [1] Gerkmann, T. & Hendriks, R. C. 46 | % Unbiased MMSE-Based Noise Power Estimation With Low Complexity and Low Tracking Delay 47 | % IEEE Trans Audio, Speech, Language Processing, 2012, 20, 1383-1393 48 | 49 | % Copyright (C) Mike Brookes 2012 50 | % Version: $Id: estnoiseg.m 3387 2013-08-23 12:32:47Z dmb $ 51 | % 52 | % VOICEBOX is a MATLAB toolbox for speech processing. 53 | % Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html 54 | % 55 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 56 | % This program is free software; you can redistribute it and/or modify 57 | % it under the terms of the GNU General Public License as published by 58 | % the Free Software Foundation; either version 2 of the License, or 59 | % (at your option) any later version. 60 | % 61 | % This program is distributed in the hope that it will be useful, 62 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 63 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 64 | % GNU General Public License for more details. 65 | % 66 | % You can obtain a copy of the GNU General Public License from 67 | % http://www.gnu.org/copyleft/gpl.html or by writing to 68 | % Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA. 69 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 70 | 71 | [nr,nrf]=size(yf); % number of frames and freq bins 72 | x=zeros(nr,nrf); % initialize output arrays 73 | if isempty(yf) && isstruct(tz) % no real data 74 | zo=tz; % just keep the same state 75 | else 76 | if isstruct(tz) % take parameters from a previous call 77 | nrcum=tz.nrcum; % cumulative number of frames 78 | xt=tz.xt; % smoothed power spectrum 79 | pslp=tz.pslp; % correction factor (9) 80 | tinc=tz.tinc; % frame increment 81 | qq=tz.qq; % parameter structure 82 | else 83 | tinc = tz; % second argument is frame increment 84 | nrcum=0; % no frames so far 85 | % default algorithm constants 86 | qq.tax=0.0717; % noise output smoothing time constant = -tinc/log(0.8) (8) 87 | qq.tap=0.152; % speech prob smoothing time constant = -tinc/log(0.9) (23) 88 | qq.psthr=0.99; % threshold for smoothed speech probability [0.99] (24) 89 | qq.pnsaf=0.01; % noise probability safety value [0.01] (24) 90 | qq.pspri=0.5; % prior speech probability [0.5] (18) 91 | qq.asnr=15; % active SNR in dB [15] (18) 92 | qq.psini=0.5; % initial speech probability [0.5] (23) 93 | qq.tavini=0.064; % assumed speech absent time at start [64 ms] 94 | 95 | if nargin>=3 && ~isempty(pp) % update fields from pp input 96 | qqn=fieldnames(qq); 97 | for i=1:length(qqn) 98 | if isfield(pp,qqn{i}) 99 | qq.(qqn{i})=pp.(qqn{i}); 100 | end 101 | end 102 | end 103 | pslp=repmat(qq.psini,1,nrf); % initialize smoothed speech presence prob 104 | xt=[]; % initialize just in case the first call has no data 105 | end 106 | 107 | % unpack parameters needed within the loop 108 | 109 | psthr=qq.psthr; % threshold for smoothed speech probability [0.99] (24) 110 | pnsaf=qq.pnsaf; % noise probability safety value [0.01] (24) 111 | 112 | % derived algorithm constants 113 | 114 | ax=exp(-tinc/qq.tax); % noise output smoothing factor = 0.8 (8) 115 | axc=1-ax; 116 | ap=exp(-tinc/qq.tap); % noise output smoothing factor = 0.9 (23) 117 | apc=1-ap; 118 | xih1=10^(qq.asnr/10); % speech-present SNR 119 | xih1r=1/(1+xih1)-1; 120 | pfac=(1/qq.pspri-1)*(1+xih1); % p(noise)/p(speech) (18) 121 | 122 | if nrcum==0 && nr>0 % initialize values for first frame 123 | xt=qq.psini*mean(yf(1:max(1,min(nr,round(1+qq.tavini/tinc))),:),1); % initial noise estimate 124 | end 125 | 126 | % loop for each frame 127 | for t=1:nr 128 | yft=yf(t,:); % noisy speech power spectrum 129 | ph1y=(1+pfac*exp(xih1r*yft./xt)).^(-1); % a-posteriori speech presence prob (18) 130 | pslp=ap*pslp+apc*ph1y; % smoothed speech presence prob (23) 131 | ph1y=min(ph1y,1-pnsaf*(pslp>psthr)); % limit ph1y (24) 132 | xtr=(1-ph1y).*yft+ph1y.*xt; % estimated raw noise spectrum (22) 133 | xt=ax*xt+axc*xtr; % smooth the noise estimate (8) 134 | x(t,:)=xt; % save the noise estimate 135 | end 136 | if nargout>1 % we need to store the state for next time 137 | zo.nrcum=nrcum+nr; % number of frames so far 138 | zo.xt=xt; % smoothed power spectrum 139 | zo.pslp=pslp; % correction factor (9) 140 | zo.tinc=tinc; % must be the last one 141 | zo.qq=qq; 142 | end 143 | if ~nargout 144 | clf; 145 | subplot(212); 146 | plot((1:nr)*tinc,10*log10([sum(yf,2) sum(x,2)])) 147 | ylabel('Frame Energy (dB)'); 148 | xlabel(sprintf('Time (s) [%d ms frame incr]',round(tinc*1000))); 149 | axisenlarge([-1 -1.05]); 150 | legend('input','noise','Location','Best'); 151 | subplot(211); 152 | plot(1:nrf,10*log10([sum(yf,1)'/nr sum(x,1)'/nr])) 153 | ylabel('Power (dB)'); 154 | xlabel('Frequency bin'); 155 | axisenlarge([-1 -1.05]); 156 | legend('input','noise','Location','Best'); 157 | end 158 | end 159 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/f16.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_realtimeDemo_MATLAB/f16.mat -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/factory2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_realtimeDemo_MATLAB/factory2.mat -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/gustWind.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_realtimeDemo_MATLAB/gustWind.mat -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/howlWind.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_realtimeDemo_MATLAB/howlWind.mat -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/hypergeometric2F1ODE.m: -------------------------------------------------------------------------------- 1 | % [z,y]=hypergeometric2F1ODE(a,b,c,zSpan,relTol,absTolF,absTolFp) 2 | % 3 | % Computes the Gauss hypergeometric function 2F1(a,b;c;z) for real z, z<1 4 | % by integrating the defining differential equation using the Matlab differential equation 5 | % solver ode15i. The initial values are set at z=0. 6 | % 7 | % 8 | % a,b,c: scalar - parameters of the Gauss hypergeometric function 9 | % zSpan: vector - The function values are computed within the span given by zSpan. 10 | % The first element must be zero as the initial values of ode15i are given 11 | % at zero. The second element must be <1. 2F1 is then evaluated for 12 | % coordinates chosen the by the differential equation solver within this 13 | % span. 14 | % If zSpan contains more than two elements, then the function is evaluated 15 | % exactly at these points. The elements must either all be increasing or 16 | % decreasing. 17 | % relTol, absTolF, absTolFp: scalar - optional parameters determining the tolerance 18 | % for ode15i (see Matlab help). The accuracy of the resulting 19 | % hypergeometric function values can be inferior particulary for values 20 | % that are far away from z=0. At z=1, 2F1 diverges. For points close to zero a tolerance 21 | % less strict than the default can already yield good results. 22 | % 23 | % 24 | % z: function output coordinates 25 | % y: values of 2F1 and its derivative at z, the first column contains the 26 | % function values, the second column the derivative 27 | % 28 | % Example: 29 | % [z y]=hypergeometric2F1ODE(10,11.13,11,[0 -1000]); 30 | % z(end) 31 | % ans = 32 | % -1000 33 | % y(end,1) 34 | % ans = 35 | % 6.8820e-031 36 | % 37 | % This program follows the idea presented in "Numerical recipes in C, Second Edition", 38 | % 1992, reprinted in 2002, Section 5.14, but is implemented for real 39 | % variables only. 40 | % 41 | % 42 | % Sample values at precision: relTol=1e-12, absTolF=1e-40, absTolFp=1e-40; 43 | % Parameters a,b,c z hypergeometric2F1ODE Mathematica precision 12 44 | % 10, 11.13, 11 -1000 6.882032e-031 6.88203163442e-31 45 | % ------- 0.99999999 1.082407e+081 1.08240679687e+81 46 | % 10, 30.98, 11 0.99999999 2.307641e+239 2.30764098825e+239 47 | % ------- -1000 3.357558e-038 3.35489870441e-38 !!! 48 | % ------- -100 3.354899e-028 3.35489870441e-28 49 | % 1, 21.54, 2 -1000 4.868549e-005 0.000486854917235 50 | % ------- 0.99999999 1.017184e+163 1.01718389611e+163 51 | % 5.9561, 0.7, 6.2561 0.9995 55.9807 55.9807392028 52 | % 53 | % ....................................................................... 54 | % 2nd order differential equation for the 55 | % Gauss hypergeometric function 2F1(a,b;c;z), [Gradshteyn, 1965, 9.151] 56 | % 57 | % z*(1-z)*d^2F/dz^2=a*b*F-[c-(a+b+1)*z]*dF/dz 58 | % 59 | % Transformation to a first order system of differential equations 60 | % with F1=F, F2=dF/dz: 61 | % dF1/dz = F2 62 | % dF2/dz = 1/(z*(1-z))*[a*b-F1-[c-(a+b+1)*z]F2] 63 | % => 64 | % 0 = dF1/dz - F2 65 | % 0 = z*(1-z)*dF2/dz - [a*b-F1-[c-(a+b+1)*z]F2] 66 | % 67 | % Initial values at z=0 68 | % with F(a,b;c;0)=1, dF(a,b;c;z)/dz|(z=0)=a*b/c, 69 | % d^2F(a,b;c;z)/dz^2|(z=0)=a*b/c*(a+1)*(b+1)/(c+1): 70 | % 71 | % F(0)=[F1(0); F2(0)]=[1; a*b/c]; 72 | % dF/dz(0)=[dF1/dz(0); dF2/dz(0)]= [a*b/c; a*b/c*(a+1)*(b+1)/(c+1)]; 73 | % 74 | % 75 | % FileName hypergeometric2F1ODE.m 76 | % Author Robert Kohlleppel 77 | % 78 | % DATE VERSION CHANGES 79 | % 20/07/2007 0.0 initial version 80 | 81 | function [z, y]=hypergeometric2F1ODE(a,b,c,zSpan,relTol,absTolF,absTolFp) 82 | 83 | if nargin==4 84 | relTol=1e-12; 85 | absTolF=1e-40; 86 | absTolFp=1e-40; 87 | elseif nargin~=7 88 | error('Wrong number of arguments.'); 89 | end; 90 | 91 | %% set initial values 92 | F0=[1; a*b/c]; 93 | Fp0=[a*b/c; a*b/c*(a+1)*(b+1)/(c+1)]; 94 | 95 | 96 | %% set tolerance values and pass jacobian 97 | options = odeset('RelTol',relTol,'AbsTol',[absTolF absTolFp], ... 98 | 'Jacobian',@(zPass,FPass,FpPass)FJAC(zPass,FPass,FpPass,a,b,c)); 99 | 100 | %% solve the differential equation 101 | [z y]=hypergeometric2F1ODE(10,11.13,11,[0 -1000]);[z, y] = ode15i(@(zPass,FPass,FpPass)f(zPass,FPass,FpPass,a,b,c),zSpan,F0,Fp0,options); 102 | 103 | 104 | end 105 | 106 | %% nested functions 107 | % Jacobian 108 | function [dfdF,dfdFp] = FJAC(z,F,Fp,a,b,c) 109 | dfdF= [0 -1; 110 | -a*b c-(a+b+1)*z]; 111 | dfdFp=[1 0; 112 | 0 z*(1-z)]; 113 | end 114 | 115 | % Differential equation 116 | function res = f(z,F,Fp,a,b,c) 117 | 118 | res = [Fp(1) - F(2); 119 | z*(1-z)*Fp(2) - (a*b*F(1)-(c-(a+b+1)*z)*F(2)) ]; 120 | end 121 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/leopard.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_realtimeDemo_MATLAB/leopard.mat -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/m109.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_realtimeDemo_MATLAB/m109.mat -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/main.m: -------------------------------------------------------------------------------- 1 | PitchTraking() -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/offlineprocessData_MMSE.m: -------------------------------------------------------------------------------- 1 | function Obj=offlineprocessData_MMSE(Obj) 2 | % tic 3 | % this is a so-called callback function. See more here 4 | % https://se.mathworks.com/help/matlab/matlab_prog/timer-callback-functions.html 5 | x= Obj.UserData{25}; 6 | x_clean= Obj.UserData{26}; 7 | time_indx=Obj.UserData{2}; 8 | frame=x(time_indx); 9 | frame_clean=x_clean(time_indx); 10 | 11 | win_input=frame_clean.*gausswin(length(frame)); 12 | pow_spec=periodgram_shi(win_input,256); 13 | 14 | % % % % % % rng(1); 15 | 16 | spec_pow=abs(fft(frame,2048)).^2; 17 | if time_indx(1) == 1 18 | [mmsePSD,mmseState]=estnoiseg(spec_pow',length(frame)/Obj.UserData{5}); 19 | Obj.mmseState=mmseState; 20 | else %(i.e., for all the frames except the first one) 21 | 22 | [mmsePSD, Obj.mmseState]=estnoiseg(spec_pow',Obj.mmseState); 23 | end 24 | mmse_covariance = real(ifft(mmsePSD')); 25 | %%Compute MMSE LPC coefficients which will be also added to the dictionary 26 | %%spectral envelopes 27 | mmse_lpc = levinson(mmse_covariance,30); 28 | if time_indx(1) == 1 29 | [frame_p,filter_state] = filter([mmse_lpc],1,... 30 | frame); 31 | Obj.filterstate=filter_state; 32 | else 33 | [frame_p,Obj.filterstate] = filter([mmse_lpc],1,... 34 | frame,Obj.filterstate); 35 | end 36 | frame=frame_p/norm(frame_p)*norm(frame); 37 | 38 | 39 | 40 | 41 | 42 | 43 | [f0Estimates,order,vad_prob]=Obj.UserData{4}(frame,1); 44 | if vad_prob<=.5 45 | f0Estimates=nan; 46 | end 47 | Obj.UserData{6}(Obj.UserData{1})=f0Estimates*Obj.UserData{5}; 48 | 49 | % Obj.UserData{7}(Obj.UserData{1},Obj.UserData{6}(Obj.UserData{1}),order,pow_spec); 50 | % plot(Obj.UserData{1},f0Estimates*Obj.UserData{5},'.');hold on; 51 | 52 | % Obj.UserData{8}{1}.XData(time_indx)=time_indx/Obj.UserData{5}; 53 | % Obj.UserData{8}{1}.YData(time_indx)=x(time_indx); 54 | if Obj.UserData{1}==1 55 | sample_vec=[1:Obj.UserData{11}*Obj.UserData{5}]/Obj.UserData{5}; 56 | Obj.UserData{12}{1}=plot(Obj.UserData{9},sample_vec,nan(length(sample_vec),1)); 57 | xlabel(Obj.UserData{9},'Time [s]') 58 | ylabel(Obj.UserData{9},'Time series'); 59 | 60 | Obj.UserData{12}{2}(1)=imagesc(Obj.UserData{8},Obj.UserData{20}, Obj.UserData{21},nan(Obj.UserData{22},length(Obj.UserData{20}))); 61 | ylim(Obj.UserData{8},[0,Obj.UserData{23}]) 62 | xlim(Obj.UserData{8},[0 Obj.UserData{11}]) 63 | axis(Obj.UserData{8},'xy'); 64 | hold on; 65 | Obj.UserData{12}{2}(2)=plot(Obj.UserData{15},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r-', 'linewidth',2); 66 | ylim(Obj.UserData{15},[0,Obj.UserData{23}]) 67 | xlim(Obj.UserData{15},[0 Obj.UserData{11}]) 68 | axis(Obj.UserData{15},'off'); 69 | ylabel(Obj.UserData{8},'Frequency') 70 | 71 | 72 | Obj.UserData{12}{3}=plot(Obj.UserData{10},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r-', 'linewidth',2); 73 | ylim(Obj.UserData{10},[0,1]) 74 | xlim(Obj.UserData{10},[0 Obj.UserData{11}]) 75 | ylabel(Obj.UserData{10},'Voicing Probability'); 76 | 77 | 78 | Obj.UserData{12}{4}=plot(Obj.UserData{17},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r.', 'linewidth',2); 79 | ylim(Obj.UserData{17},[0,Obj.UserData{24}]) 80 | xlim(Obj.UserData{17},[0 Obj.UserData{11}]) 81 | ylabel(Obj.UserData{17},'Order'); 82 | 83 | end 84 | % soundsc(x(time_indx)) 85 | Obj.UserData{12}{1}.YData(time_indx)=x(time_indx); 86 | xlim(Obj.UserData{9},[0,Obj.UserData{11}]); 87 | Obj.UserData{12}{2}(1).CData(:,Obj.UserData{1})=10*log10(abs(pow_spec(1:Obj.UserData{22}))); 88 | Obj.UserData{12}{2}(2).YData(Obj.UserData{1})=[ Obj.UserData{6}(Obj.UserData{1})]; 89 | xlim(Obj.UserData{8},[0,Obj.UserData{11}]); 90 | 91 | Obj.UserData{12}{3}.YData(Obj.UserData{1})=vad_prob; 92 | xlim(Obj.UserData{10},[0 Obj.UserData{11}]); 93 | 94 | Obj.UserData{12}{4}.YData(Obj.UserData{1})=order; 95 | xlim(Obj.UserData{17},[0 Obj.UserData{11}]); 96 | 97 | Obj.UserData{1}=Obj.UserData{1}+1; 98 | Obj.UserData{2}=Obj.UserData{2}+Obj.UserData{3}; 99 | 100 | 101 | 102 | % toc 103 | end 104 | function pow=periodgram_shi(x,nfft,fs) 105 | if nargin<3 106 | fs=1; 107 | end 108 | x=x(:); 109 | data_len=length(x); 110 | % matr=fft_shi(data_len,nfft); 111 | %normalized rectangular window consistent with energy 112 | f=fft(x,nfft)/sqrt(data_len); 113 | %normalized rectangular window consistent with matlab 114 | % f=matr*x/sqrt(data_len); 115 | pow=abs(f).^2; 116 | end 117 | 118 | function ActivationCoeff = ActivationFunction(noisyPSD,AR_PSD_BasisMtx,... 119 | prev_Frame_Actv_Coeff) 120 | 121 | ActivationCoeff = rand(size(AR_PSD_BasisMtx,2),1); 122 | numberIterations = 40; 123 | 124 | for times = 1:numberIterations 125 | Factor=AR_PSD_BasisMtx'*(((AR_PSD_BasisMtx*ActivationCoeff).^(0-2)).*... 126 | noisyPSD)./(AR_PSD_BasisMtx'*(AR_PSD_BasisMtx*... 127 | ActivationCoeff).^(0-1)); 128 | ActivationCoeff = ActivationCoeff.*Factor; 129 | end 130 | end -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/pink.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_realtimeDemo_MATLAB/pink.mat -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/computeAllCostFunctions.m: -------------------------------------------------------------------------------- 1 | function costFunctions = computeAllCostFunctions(x, L, fullPitchGrid, ... 2 | fftShiftVector, crossCorrelationVectors, Gamma1, Gamma2, ... 3 | dcIsIncluded) 4 | % compute Zc'*y for all model orders and frequencies where Zc is the 5 | % complex-valued sinusoidal matrix 6 | [harmonicDfts, pitchGrids] = ... 7 | computeComplexHarmonicDfts(x, fullPitchGrid, L, fftShiftVector); 8 | nPitches = length(fullPitchGrid); 9 | costFunctions = nan(L, nPitches); 10 | 11 | for l = 1:L 12 | % Update the valid pitches and the DFT matrices 13 | nPitches = sum(~isnan(pitchGrids(l,:))); 14 | 15 | if dcIsIncluded 16 | gamma1 = Gamma1{l+1}; 17 | else 18 | gamma1 = Gamma1{l}; 19 | end 20 | gamma2 = Gamma2{l}; 21 | 22 | if l == 1 23 | if dcIsIncluded 24 | lsSol1 = sum(x)*Gamma1{1}; 25 | R1 = computeRowsOfToeplitzHankelMatrix(2, 2, ... 26 | crossCorrelationVectors(1:2*l+1, 1:nPitches), ... 27 | true, true); 28 | 29 | lambda1 = (ones(2, 1)*(real(harmonicDfts(l,1:nPitches))-... 30 | sum(R1(1:end-1, :).*lsSol1(:, 1:nPitches),1))); 31 | 32 | lsSol1 = [lsSol1; zeros(1, nPitches)]+lambda1.*gamma1; 33 | else 34 | lsSol1 = real(harmonicDfts(l,1:nPitches)).*gamma1; 35 | end 36 | 37 | lsSol2 = imag(harmonicDfts(l,1:nPitches)).*gamma2; 38 | else 39 | 40 | if dcIsIncluded 41 | ll = l+1; 42 | else 43 | ll = l; 44 | end 45 | 46 | R1 = computeRowsOfToeplitzHankelMatrix(ll, ll, ... 47 | crossCorrelationVectors(1:2*l+1, 1:nPitches), ... 48 | true, dcIsIncluded); 49 | 50 | lambda1 = (ones(ll, 1)*(real(harmonicDfts(l,1:nPitches))-... 51 | sum(R1(1:end-1, :).*lsSol1(:, 1:nPitches),1))); 52 | 53 | lsSol1 = [lsSol1(:, 1:nPitches); zeros(1, nPitches)] ... 54 | + lambda1.*gamma1; 55 | 56 | R2 = computeRowsOfToeplitzHankelMatrix(l, l, ... 57 | crossCorrelationVectors(1:2*l+1, 1:nPitches), ... 58 | false, dcIsIncluded); 59 | 60 | lambda2 = (ones(l, 1)*(imag(harmonicDfts(l,1:nPitches))-... 61 | sum(R2(1:end-1, :).*lsSol2(:, 1:nPitches),1))); 62 | 63 | lsSol2 = [lsSol2(:, 1:nPitches); zeros(1, nPitches)] ... 64 | + lambda2.*gamma2; 65 | 66 | end 67 | 68 | % compute the cost function 69 | if dcIsIncluded 70 | costFunctions(l, 1:nPitches) = sum(x)*lsSol1(1, :)+... 71 | sum(real(harmonicDfts(1:l,1:nPitches)).*lsSol1(2:l+1,:),1)+... 72 | sum(imag(harmonicDfts(1:l,1:nPitches)).*lsSol2,1); 73 | else 74 | costFunctions(l, 1:nPitches) = ... 75 | sum(real(harmonicDfts(1:l,1:nPitches)).*lsSol1,1)+... 76 | sum(imag(harmonicDfts(1:l,1:nPitches)).*lsSol2,1); 77 | end 78 | end -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/computeComplexHarmonicDfts.m: -------------------------------------------------------------------------------- 1 | function [harmonicDfts, pitchGrids] = ... 2 | computeComplexHarmonicDfts(dataVector, fullPitchGrid, ... 3 | pitchOrder, fftShiftVector) 4 | nDft = round(1/diff(fullPitchGrid(1:2))); 5 | dftData = fft(dataVector, nDft); 6 | % compensate for a symmetric time index (i.e., a start index of 7 | % -(nData-1)/2) 8 | fftShiftVectorLength = length(fftShiftVector); 9 | shiftedDftData = (dftData(1:fftShiftVectorLength).*fftShiftVector).'; 10 | for ii = 1:pitchOrder 11 | dftIndices = computeDftIndicesNHarmonic(nDft, ... 12 | fullPitchGrid([1,end]), ii); 13 | nPitches = length(dftIndices); 14 | if ii == 1 15 | % allocate memory 16 | pitchGrids = nan(pitchOrder, nPitches); 17 | harmonicDfts = nan(pitchOrder, nPitches); 18 | end 19 | pitchGrids(ii,1:nPitches) = fullPitchGrid(1:nPitches); 20 | harmonicDfts(ii, 1:nPitches) = shiftedDftData(dftIndices+1); 21 | end 22 | end 23 | 24 | function dftIndices = computeDftIndicesNHarmonic(nDft, pitchBounds, ... 25 | pitchOrder) 26 | % the rounding operation is only used for numerical reasons in this 27 | % function 28 | minPitchIdx = max(0, round(pitchBounds(1)*nDft)); 29 | % the max pitch must be smaller than 1/(2*modelOrder) to avoid 30 | % problems with aliasing 31 | maxPitchIdx = min(nDft/(2*pitchOrder)-1, ... 32 | round(pitchBounds(2)*nDft)); 33 | dftIndices = (minPitchIdx:maxPitchIdx)*pitchOrder; 34 | end 35 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/computeComplexHarmonicDftsTest.m: -------------------------------------------------------------------------------- 1 | function tests = computeComplexHarmonicDftsTest() 2 | tests = functiontests(localfunctions); 3 | end 4 | 5 | function testComputedDfts(testCase) 6 | % setup 7 | rng(2); 8 | nData = 200; 9 | startIndex = -(nData-1)/2; 10 | dataVector = randn(nData,1); 11 | maxPitchOrder = 10; 12 | pitchResolution = 1/(5*maxPitchOrder*nData); 13 | pitchBounds = [0,nData/2-1]/nData; 14 | fullPitchGrid = ... 15 | computePitchGrid(pitchResolution, pitchBounds, 1, true); 16 | nDft = round(1/diff(fullPitchGrid(1:2))); 17 | fftShiftVector = exp(-1i*2*pi*((0:nDft-1)'/nDft)*startIndex); 18 | for ii = 1:maxPitchOrder 19 | pitchGrid = ... 20 | computePitchGrid(pitchResolution, pitchBounds, ii, true); 21 | nPitches = length(pitchGrid); 22 | if ii == 1 23 | expHarmonicDfts = nan(maxPitchOrder, nPitches); 24 | expPitchGrids = nan(maxPitchOrder, nPitches); 25 | end 26 | expPitchGrids(ii,1:nPitches) = pitchGrid; 27 | for jj = 1:nPitches 28 | sinusoid = ... 29 | exp(1i*2*pi*pitchGrid(jj)*ii*((0:nData-1)+startIndex)'); 30 | expHarmonicDfts(ii,jj) = sinusoid'*dataVector; 31 | end 32 | end 33 | [actHarmonicDfts, actPitchGrids] = ... 34 | computeComplexHarmonicDfts(dataVector, fullPitchGrid, ... 35 | maxPitchOrder, fftShiftVector); 36 | testCase.assertEqual(actPitchGrids, expPitchGrids, ... 37 | 'absTol', 1e-11); 38 | testCase.assertEqual(actHarmonicDfts, expHarmonicDfts, ... 39 | 'absTol', 1e-11); 40 | end 41 | 42 | function pitchGrid = computePitchGrid(pitchResolution, pitchBounds, ... 43 | modelOrder, dataAreRealValued) 44 | if nargin < 4 45 | dataAreRealValued = false; 46 | end 47 | nPitches = ceil(1/pitchResolution); 48 | minPitchIdx = max(0, ceil(pitchBounds(1)*nPitches)); 49 | % the max pitch must be smaller than 1/modelOrder to avoid problems 50 | % with aliasing 51 | if dataAreRealValued 52 | maxPitchIdx = min(nPitches/(2*modelOrder)-1, ... 53 | floor(pitchBounds(2)*nPitches)); 54 | else 55 | maxPitchIdx = min(nPitches/modelOrder-1, ... 56 | floor(pitchBounds(2)*nPitches)); 57 | end 58 | % the pitch grid must a subset of the full dft grid 59 | dftPitchGrid = (0:nPitches-1)'/nPitches; 60 | pitchGrid = dftPitchGrid((minPitchIdx(1):maxPitchIdx(1))+1); 61 | end -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/computeGamma.m: -------------------------------------------------------------------------------- 1 | function [Gamma1, Gamma2] = computeGamma(L, F, pitchBounds, crossCorrelationVectors, nPitches,... 2 | validFftIndices, dcIsIncluded) 3 | 4 | if L == 1 5 | a1 = crossCorrelationVectors(2, :); 6 | a2 = a1; 7 | else 8 | if dcIsIncluded 9 | a1 = crossCorrelationVectors(2:L+1, :)+... 10 | [zeros(1, nPitches);... 11 | crossCorrelationVectors((1:L-1), :)]; 12 | else 13 | a1 = crossCorrelationVectors(2:L, :)+... 14 | [zeros(1,nPitches);... 15 | crossCorrelationVectors((1:L-2)+2, :)]; 16 | end 17 | 18 | a2 = crossCorrelationVectors(2:L, :)-... 19 | [zeros(1,nPitches);... 20 | crossCorrelationVectors((1:L-2)+2, :)]; 21 | end 22 | 23 | for l = 1:L 24 | maxFftIndex = floor(min(F*pitchBounds(2),F/(2*l)-1)); 25 | nPitches = nPitches-(validFftIndices(end)-maxFftIndex); 26 | validPitchIndices = 1:nPitches; 27 | validFftIndices = validFftIndices(validPitchIndices); 28 | 29 | if l == 1 30 | % compute the cost function for a model of one 31 | if dcIsIncluded 32 | [psi1, phi1, gammaOld1] = computeGammaSingleSinus(... 33 | crossCorrelationVectors(1, validPitchIndices), ... 34 | a1(1, validPitchIndices), true, true); 35 | Gamma1{1} = gammaOld1; 36 | 37 | [R1, alpha1, gammaNew1] = computeGammaTwoSinus(... 38 | crossCorrelationVectors(1:3,validPitchIndices), ... 39 | psi1, gammaOld1, true, true); 40 | Gamma1{2} = gammaNew1; 41 | 42 | else 43 | [psi1, phi1, gammaOld1] = computeGammaSingleSinus(... 44 | crossCorrelationVectors(1:3,validPitchIndices), ... 45 | a1(1,validPitchIndices), true, false); 46 | Gamma1{1} = gammaOld1; 47 | end 48 | 49 | [psi2, phi2, gammaOld2] = computeGammaSingleSinus(... 50 | crossCorrelationVectors(1:3,validPitchIndices), ... 51 | a2(1,validPitchIndices), false, dcIsIncluded); 52 | 53 | Gamma2{1} = gammaOld2; 54 | 55 | elseif l == 2 56 | % compute the cost function for a model of two 57 | if dcIsIncluded 58 | [R1, phi1, psi1, alpha1, gammaOld1, gammaNew1] = ... 59 | computeGammaMultipleSinus(... 60 | R1(1:end-1,validPitchIndices), 3, ... 61 | crossCorrelationVectors(1:5,validPitchIndices), ... 62 | a1(l,validPitchIndices), ... 63 | phi1(:,validPitchIndices), ... 64 | psi1(:,validPitchIndices), ... 65 | gammaOld1(:,validPitchIndices), ... 66 | gammaNew1(:,validPitchIndices), ... 67 | alpha1(validPitchIndices), ... 68 | true, true); 69 | Gamma1{3} = gammaNew1; 70 | else 71 | [R1, alpha1, gammaNew1] = computeGammaTwoSinus(... 72 | crossCorrelationVectors(1:5,validPitchIndices), ... 73 | psi1(validPitchIndices), ... 74 | gammaOld1(validPitchIndices), true, false); 75 | 76 | Gamma1{2} = gammaNew1; 77 | end 78 | 79 | [R2, alpha2, gammaNew2] = computeGammaTwoSinus(... 80 | crossCorrelationVectors(1:5,validPitchIndices), ... 81 | psi2(validPitchIndices), ... 82 | gammaOld2(validPitchIndices), false, false); 83 | 84 | 85 | Gamma2{2} = gammaNew2; 86 | 87 | 88 | else 89 | 90 | if dcIsIncluded 91 | ll = l; 92 | else 93 | ll = l-1; 94 | end 95 | 96 | % compute the cost function for a model of more than two 97 | [R1, phi1, psi1, alpha1, gammaOld1, gammaNew1] = ... 98 | computeGammaMultipleSinus(... 99 | R1(1:end-1, validPitchIndices), ll+1, ... 100 | crossCorrelationVectors(1:2*l+1, validPitchIndices), ... 101 | a1(ll, validPitchIndices), ... 102 | phi1(:, validPitchIndices), ... 103 | psi1(:, validPitchIndices), ... 104 | gammaOld1(:, validPitchIndices), ... 105 | gammaNew1(:, validPitchIndices), ... 106 | alpha1(validPitchIndices), ... 107 | true, dcIsIncluded); 108 | [R2, phi2, psi2, alpha2, gammaOld2, gammaNew2] = ... 109 | computeGammaMultipleSinus(... 110 | R2(1:end-1,validPitchIndices), l, ... 111 | crossCorrelationVectors(1:2*l+1, validPitchIndices), ... 112 | a2(l-1, validPitchIndices), ... 113 | phi2(:, validPitchIndices), ... 114 | psi2(:, validPitchIndices), ... 115 | gammaOld2(:, validPitchIndices), ... 116 | gammaNew2(:, validPitchIndices), ... 117 | alpha2(validPitchIndices), ... 118 | false, dcIsIncluded); 119 | 120 | if dcIsIncluded 121 | Gamma1{l+1} = gammaNew1; 122 | else 123 | Gamma1{l} = gammaNew1; 124 | end 125 | Gamma2{l} = gammaNew2; 126 | end 127 | end 128 | 129 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/computeGammaMultipleSinus.m: -------------------------------------------------------------------------------- 1 | function [RNew, phi, psi, alphaNew, gammaOld, gammaNew] = ... 2 | computeGammaMultipleSinus(... 3 | ROld, iOrder, crossCorrelationVectors, a, phi, psi, gammaOld, ... 4 | gammaNew, alphaOld, hankelMatrixIsAdded, dcIsIncluded) 5 | 6 | nPitches = length(a); 7 | RNew = computeRowsOfToeplitzHankelMatrix(iOrder, iOrder, ... 8 | crossCorrelationVectors, hankelMatrixIsAdded, dcIsIncluded); 9 | lambda = a-sum(ROld.*phi,1); 10 | mu = -sum(ROld.*psi,1); 11 | phi = [phi;zeros(1,nPitches)]+(ones(iOrder-1,1)*lambda).*gammaNew; 12 | psi = [psi;zeros(1,nPitches)]+(ones(iOrder-1,1)*mu).*gammaNew; 13 | alphaNew = sum(RNew(1:end-1,:).*gammaNew,1); 14 | b = (ones(iOrder-1,1)*(alphaOld-alphaNew)).*gammaNew+... 15 | [zeros(1,nPitches);gammaNew(1:iOrder-2,:)]+... 16 | [gammaNew(2:end,:);zeros(1,nPitches)]-... 17 | [gammaOld(1:iOrder-2,:);zeros(1,nPitches)]+... 18 | (ones(iOrder-1,1)*psi(end,:)).*phi-... 19 | (ones(iOrder-1,1)*phi(end,:)).*psi; 20 | nu = sum(RNew(1:end-1,:).*b)./gammaNew(end,:); 21 | gammaOld = gammaNew; 22 | gammaNew = nan(iOrder,nPitches); 23 | gammaNew(iOrder,:) = 1./(nu+RNew(iOrder,:)); 24 | gammaNew(1:iOrder-1,:) = (ones(iOrder-1,1)*... 25 | (gammaNew(iOrder,:)./gammaOld(end,:))).*b; 26 | 27 | end 28 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/computeGammaSingleSinus.m: -------------------------------------------------------------------------------- 1 | function [psi, phi, gamma] = computeGammaSingleSinus(... 2 | crossCorrelationVectors, a, hankelMatrixIsAdded, dcIsIncluded) 3 | 4 | R = computeRowsOfToeplitzHankelMatrix(1, 1, ... 5 | crossCorrelationVectors, ... 6 | hankelMatrixIsAdded, ... 7 | dcIsIncluded); 8 | psi = 1./R(1, :); 9 | gamma = psi; 10 | phi = a.*gamma; 11 | end 12 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/computeGammaTwoSinus.m: -------------------------------------------------------------------------------- 1 | function [R, alpha, gamma] = computeGammaTwoSinus(... 2 | crossCorrelationVectors, psi, gamma, ... 3 | hankelMatrixIsAdded, dcIsIncluded) 4 | 5 | nPitches = length(psi); 6 | R = computeRowsOfToeplitzHankelMatrix(2,... 7 | 2, crossCorrelationVectors, hankelMatrixIsAdded, dcIsIncluded); 8 | alpha = R(1,:).*gamma; 9 | 10 | gamma = ... 11 | [-R(1,:).*psi;ones(1,nPitches)]./(ones(2,1)*(R(2,:)-R(1,: ... 12 | ).^2.*psi)); 13 | 14 | end 15 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/computeLogMarginalLikelihood.m: -------------------------------------------------------------------------------- 1 | function logMarginalLikelihood = ... 2 | computeLogMarginalLikelihood(logPitchLikelihood, fullPitchGrid) 3 | % compute the unnormalised log marginal likelihood 4 | deltaFreq = diff(fullPitchGrid(1:2)); 5 | maxModelOrder = size(logPitchLikelihood,1); 6 | logMarginalLikelihood = ones(1,maxModelOrder); 7 | for iOrder = 1:maxModelOrder 8 | % find the non-NaN indices 9 | indices = find(~isnan(logPitchLikelihood(iOrder,:))); 10 | % find the maximum value 11 | maxLogMarginalLikelihood = max(logPitchLikelihood(iOrder,indices)); 12 | logMarginalLikelihood(iOrder) = maxLogMarginalLikelihood+... 13 | log(deltaFreq*trapz(exp(... 14 | logPitchLikelihood(iOrder,indices)-maxLogMarginalLikelihood))); 15 | end 16 | end -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/computePitchLogLikelihood.m: -------------------------------------------------------------------------------- 1 | function [pitchLikelihood, pitchLogLikelihood] = ... 2 | computePitchLogLikelihood(cod, nData, delta) 3 | [maxModelOrder, nFreqs] = size(cod); 4 | pitchLogLikelihood = nan(maxModelOrder, nFreqs); 5 | for iOrder = 1:maxModelOrder 6 | [gHat, tauVar] = computeLaplaceParameters(cod(iOrder,:), 1, ... 7 | (nData-2*iOrder-delta)/2, nData/2); 8 | pitchLogLikelihood(iOrder,:) = ... 9 | log(gHat*(delta-2)/2)+(nData-2*iOrder-delta)/2*log(1+gHat)-... 10 | nData/2*log(1+gHat.*(1-cod(iOrder,:)))+... 11 | 1/2*log(2*pi*tauVar); 12 | end 13 | pitchLikelihood = exp(pitchLogLikelihood); 14 | end 15 | 16 | function [gHat, tauVar] = computeLaplaceParameters(cod, v, w, u) 17 | a = (1-cod)*(v+w-u); 18 | b = (u-v)*cod+2*v+w-u; 19 | gHat = (b+sqrt(b.^2-4*a*v))./(-2*a); 20 | tauVar = 1./(gHat.*(1-cod)*u./(1+gHat.*(1-cod)).^2-... 21 | gHat.*w./(1+gHat).^2); 22 | end 23 | 24 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/computePostModelPmf.m: -------------------------------------------------------------------------------- 1 | function postModelPmf = computePostModelPmf(logMarginalLikelihood, ... 2 | logModelPrior) 3 | scaledLogPostModelPmf = logMarginalLikelihood + logModelPrior; 4 | scaledPostModelPmf = ... 5 | exp(scaledLogPostModelPmf-max(scaledLogPostModelPmf)); 6 | postModelPmf = scaledPostModelPmf/sum(scaledPostModelPmf); 7 | end 8 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/computeRowsOfToeplitzHankelMatrix.m: -------------------------------------------------------------------------------- 1 | function rowMatrix = computeRowsOfToeplitzHankelMatrix(rowNumber,... 2 | nColumns, crossCorrelationVectors, hankelMatrixIsAdded, dcIsIncluded) 3 | if rowNumber == 1 4 | toeplitzRows = crossCorrelationVectors(1:nColumns,:); 5 | else 6 | toeplitzRows = ... 7 | [flip(crossCorrelationVectors(2:rowNumber,:),1);... 8 | crossCorrelationVectors(1:nColumns-rowNumber+1,:)]; 9 | end 10 | 11 | 12 | if dcIsIncluded && hankelMatrixIsAdded 13 | hankelOffset = 1; 14 | else 15 | hankelOffset = 3; 16 | end 17 | 18 | hankelRows = crossCorrelationVectors((0:nColumns-1)+... 19 | hankelOffset+rowNumber-1,:); 20 | 21 | if hankelMatrixIsAdded 22 | rowMatrix = toeplitzRows + hankelRows; 23 | else 24 | rowMatrix = toeplitzRows - hankelRows; 25 | end 26 | 27 | end -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/generator.m: -------------------------------------------------------------------------------- 1 | function x = generator(N, ell, f0, alpha) 2 | % 3 | % Generates a harmonic signal 4 | % 5 | 6 | modelOrders = (1:ell)'; 7 | n = (-(N-1)/2:-(N-1)/2+N-1)'; 8 | Z = exp(1i*2*pi*f0*n*modelOrders'); 9 | sinusoidalMatrix = [ones(N, 1), real(Z), -imag(Z)]; 10 | x = sinusoidalMatrix*alpha; 11 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/goldenSectionSearch.m: -------------------------------------------------------------------------------- 1 | %% goldenSectionSearch 2 | % Single variable bounded minisation using a golden section search 3 | % 4 | %% Syntax: 5 | % [lowerFinalBound, upperFinalBound] = goldenSectionSearch(objectiveFunction,... 6 | % lowerInitialBound, upperInitialBound, requiredInterval); 7 | % 8 | %% Description: 9 | % Narrows down the minimum of a function from an initial interval to smaller 10 | % interval using af golden section search. 11 | % The implementation is based on Sec. 4.4 in 12 | % A. Antoniou and W.-S. Lu, Practical Optimization: Algorithms and Engineering 13 | % Applications. Springer, Mar. 2007. 14 | % * objectiveFunction: A function handle of the function to be minimised 15 | % * lowerInitialBound: The lower initial bound of the minimiser 16 | % * upperInitialBound: The upper initial bound of the minimiser 17 | % * requiredInterval: The required final interval of uncertainty 18 | % * lowerFinalBound: The final lower bound 19 | % * upperFinalBound: The final upper bound 20 | %% Examples: 21 | % f = @(x) x.^2-2*x-3; 22 | % lowerBound = -2; 23 | % upperBound = 5; 24 | % requiredUncertainty = 1e-3; 25 | % [lowerBound, upperBound] = goldenSectionSearch(f,lowerBound,upperBound,... 26 | % requiredUncertainty); 27 | % estimatedMinimiser = (upperBound+lowerBound)/2; 28 | % 29 | function [lowerFinalBound, upperFinalBound] = goldenSectionSearch(objectiveFunction,... 30 | lowerInitialBound, upperInitialBound, requiredInterval) 31 | % Check the input arguments 32 | if nargin<4 33 | error('goldenSectionSearch:argChk','Four input arguments are required.'); 34 | end 35 | validateObjectiveFunction(objectiveFunction); 36 | validateBound(lowerInitialBound); 37 | validateBound(upperInitialBound); 38 | initialInterval = upperInitialBound-lowerInitialBound; 39 | if initialInterval<=0 40 | error('goldenSectionSearch:argChk',... 41 | 'The lower bound must be smaller than the upper bound.'); 42 | end 43 | validateInterval(requiredInterval); 44 | % Perform the golden section search 45 | [lowerFinalBound, upperFinalBound] = narrowBounds(objectiveFunction,... 46 | lowerInitialBound, upperInitialBound, requiredInterval); 47 | end 48 | 49 | % Return an error if the objective function is invalid 50 | function validateObjectiveFunction(objectiveFunction) 51 | if ~isa(objectiveFunction, 'function_handle') 52 | error('goldenSectionSearch:argChk',... 53 | 'The input argument must be a function handle'); 54 | end 55 | end 56 | 57 | % Return an error if the bound is invalid 58 | function validateBound(bound) 59 | if ~isscalar(bound) || ~isfinite(bound) 60 | error('goldenSectionSearch:argChk',... 61 | 'The bounds must be real-valued scalars.'); 62 | end 63 | end 64 | 65 | % Return an error if the interval is invalid 66 | function validateInterval(interval) 67 | if ~isscalar(interval) || ~isfinite(interval) ||... 68 | interval<=0 69 | error('goldenSectionSearch:argChk',... 70 | 'The required interval must be a positive real-valued scalar.'); 71 | end 72 | end 73 | 74 | % Run the golden section search algorithm to narrow down the lower and upper 75 | % bound for the minimiser to within a tolerance of at most +/-requiredInterval/2. 76 | % The algorithm is based on algorithm 4.2 in A. Antoniou and W.-S. Lu, 77 | % Practical Optimization: Algorithms and Engineering Applications. 78 | % Springer, Mar. 2007. 79 | function [lowerBound, upperBound] = narrowBounds(objectiveFunction,... 80 | lowerBound, upperBound, requiredInterval) 81 | goldenRatio = 0.5+sqrt(1.25); 82 | startInterval = upperBound-lowerBound; 83 | iInterval = startInterval/goldenRatio; 84 | variableLowerVal = upperBound-iInterval; 85 | funcLowerVal = objectiveFunction(variableLowerVal); 86 | variableUpperVal = lowerBound+iInterval; 87 | funcUpperVal = objectiveFunction(variableUpperVal); 88 | while iInterval > requiredInterval 89 | iInterval = iInterval/goldenRatio; 90 | if funcLowerVal > funcUpperVal 91 | % The minimum is in the interval [variableLowerVal;upperBound] 92 | lowerBound = variableLowerVal; 93 | variableLowerVal = variableUpperVal; 94 | variableUpperVal = lowerBound+iInterval; 95 | funcLowerVal = funcUpperVal; 96 | funcUpperVal = objectiveFunction(variableUpperVal); 97 | else 98 | % The minimum is in the interval [lowerBound;variableUpperVal] 99 | upperBound = variableUpperVal; 100 | variableUpperVal = variableLowerVal; 101 | variableLowerVal = upperBound-iInterval; 102 | funcUpperVal = funcLowerVal; 103 | funcLowerVal = objectiveFunction(variableLowerVal); 104 | end 105 | % If the final search tolerance is within the precision of 106 | % the computer, then stop 107 | if variableLowerVal>variableUpperVal 108 | break; 109 | end 110 | end 111 | % When iInterval is smaller than the required interval, we make one final 112 | % comparison so that (upperBound-lowerBound) funcUpperVal 114 | % The minimum is in the interval [variableLowerVal;upperBound] 115 | lowerBound = variableLowerVal; 116 | elseif funcLowerVal == funcUpperVal 117 | % The minimum is in the interval [variableLowerVal;variableUpperVal] 118 | lowerBound = variableLowerVal; 119 | upperBound = variableUpperVal; 120 | else 121 | % The minimum is in the interval [lowerBound;variableUpperVal] 122 | upperBound = variableUpperVal; 123 | end 124 | end 125 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/listdlg2.m: -------------------------------------------------------------------------------- 1 | function [selection,value] = listdlg2(varargin) 2 | %LISTDLG List selection dialog box. 3 | % [SELECTION,OK] = LISTDLG2('ListString',S) creates a modal dialog box 4 | % which allows you to select a string or multiple strings from a list. 5 | % SELECTION is a vector of indices of the selected strings (length 1 in 6 | % the single selection mode). This will be [] when OK is 0. OK is 1 if 7 | % you push the OK button, or 0 if you push the Cancel button or close the 8 | % figure. 9 | % 10 | % Double-clicking on an item or pressing when multiple items are 11 | % selected has the same effect as clicking the OK button. Pressing 12 | % is the same as clicking the OK button. Pressing is the same as 13 | % clicking the Cancel button. 14 | % 15 | % Inputs are in parameter,value pairs: 16 | % 17 | % Parameter Description 18 | % 'ListString' cell array of strings for the list box. 19 | % 'SelectionMode' string; can be 'single' or 'multiple'; defaults to 20 | % 'multiple'. 21 | % 'ListSize' [width height] of listbox in pixels; defaults 22 | % to [160 300]. 23 | % 'InitialValue' vector of indices of which items of the list box 24 | % are initially selected; defaults to the first item. 25 | % 'Name' String for the figure's title; defaults to ''. 26 | % 'PromptString' string matrix or cell array of strings which appears 27 | % as text above the list box; defaults to {}. 28 | % 'OKString' string for the OK button; defaults to 'OK'. 29 | % 'CancelString' string for the Cancel button; defaults to 'Cancel'. 30 | % 31 | % A 'Select all' button is provided in the multiple selection case. 32 | % 33 | % Example: 34 | % d = dir; 35 | % str = {d.name}; 36 | % [s,v] = listdlg('PromptString','Select a file:',... 37 | % 'SelectionMode','single',... 38 | % 'ListString',str) 39 | % 40 | % See also DIALOG, ERRORDLG, HELPDLG, INPUTDLG, 41 | % MSGBOX, QUESTDLG, WARNDLG. 42 | 43 | % Copyright 1984-2014 The MathWorks, Inc. 44 | 45 | % 'uh' uicontrol button height, in pixels; default = 22. 46 | % 'fus' frame/uicontrol spacing, in pixels; default = 8. 47 | % 'ffs' frame/figure spacing, in pixels; default = 8. 48 | 49 | % simple test: 50 | % 51 | % d = dir; [s,v] = listdlg2('PromptString','Select a file:','ListString',{d.name}); 52 | % 53 | 54 | % Generate a warning in -nodisplay and -noFigureWindows mode. 55 | % warnfiguredialog('listdlg'); 56 | % usedpath=strcat(matlabroot,'/toolbox/matlab/uitools/private'); 57 | % addpath(genpath(usedpath)); 58 | narginchk(1,inf) 59 | 60 | figname = ''; 61 | smode = 2; % (multiple) 62 | promptstring = {}; 63 | liststring = []; 64 | listsize = [160 300]; 65 | initialvalue = []; 66 | okstring = getString(message('MATLAB:uistring:popupdialogs:OK')); 67 | cancelstring = getString(message('MATLAB:uistring:popupdialogs:Cancel')); 68 | fus = 8; 69 | ffs = 8; 70 | uh = 22; 71 | 72 | % custom change 73 | pos = []; 74 | 75 | if mod(length(varargin),2) ~= 0 76 | % input args have not com in pairs, woe is me 77 | error(message('MATLAB:listdlg:InvalidArgument')) 78 | end 79 | for i=1:2:length(varargin) 80 | switch lower(varargin{i}) 81 | case 'name' 82 | figname = varargin{i+1}; 83 | case 'promptstring' 84 | promptstring = varargin{i+1}; 85 | case 'selectionmode' 86 | switch lower(varargin{i+1}) 87 | case 'single' 88 | smode = 1; 89 | case 'multiple' 90 | smode = 2; 91 | end 92 | case 'listsize' 93 | listsize = varargin{i+1}; 94 | case 'liststring' 95 | liststring = varargin{i+1}; 96 | case 'initialvalue' 97 | initialvalue = varargin{i+1}; 98 | case 'uh' 99 | uh = varargin{i+1}; 100 | case 'fus' 101 | fus = varargin{i+1}; 102 | case 'ffs' 103 | ffs = varargin{i+1}; 104 | case 'okstring' 105 | okstring = varargin{i+1}; 106 | case 'cancelstring' 107 | cancelstring = varargin{i+1}; 108 | 109 | % custom change 110 | case 'position' 111 | pos = varargin{i+1}; 112 | 113 | % original code 114 | otherwise 115 | error(message('MATLAB:listdlg:UnknownParameter', varargin{ i })) 116 | end 117 | end 118 | 119 | if ischar(promptstring) 120 | promptstring = cellstr(promptstring); 121 | end 122 | 123 | if isempty(initialvalue) 124 | initialvalue = 1; 125 | end 126 | 127 | if isempty(liststring) 128 | error(message('MATLAB:listdlg:NeedParameter')) 129 | end 130 | 131 | ex = get(0,'DefaultUicontrolFontSize')*1.7; % height extent per line of uicontrol text (approx) 132 | 133 | fp = get(0,'DefaultFigurePosition'); 134 | w = 2*(fus+ffs)+listsize(1); 135 | h = 2*ffs+6*fus+ex*length(promptstring)+listsize(2)+uh+(smode==2)*(fus+uh); 136 | fp = [fp(1) fp(2)+fp(4)-h w h]; % keep upper left corner fixed 137 | 138 | fig_props = { ... 139 | 'windowstyle' 'modal' ... 140 | 'name' figname ... 141 | 'color' get(0,'DefaultUicontrolBackgroundColor') ... 142 | 'resize' 'off' ... 143 | 'numbertitle' 'off' ... 144 | 'menubar' 'none' ... 145 | 'visible' 'off' ... 146 | 'createfcn' '' ... 147 | 'position' fp ... 148 | 'closerequestfcn' 'delete(gcbf)' ... 149 | }; 150 | 151 | liststring=cellstr(liststring); 152 | 153 | fig = figure(fig_props{:}); 154 | 155 | if ~isempty(promptstring) 156 | prompt_text = uicontrol('Style','text','String',promptstring,... 157 | 'HorizontalAlignment','left',... 158 | 'Position',[ffs+fus fp(4)-(ffs+fus+ex*length(promptstring)) ... 159 | listsize(1) ex*length(promptstring)]); %#ok 160 | end 161 | 162 | btn_wid = (fp(3)-2*(ffs+fus)-fus)/2; 163 | 164 | listbox = uicontrol('Style','listbox',... 165 | 'Position',[ffs+fus ffs+uh+4*fus+(smode==2)*(fus+uh) listsize],... 166 | 'String',liststring,... 167 | 'BackgroundColor','w',... 168 | 'Max',smode,... 169 | 'Tag','listbox',... 170 | 'Value',initialvalue, ... 171 | 'Callback', {@doListboxClick}); 172 | 173 | ok_btn = uicontrol('Style','pushbutton',... 174 | 'String',okstring,... 175 | 'Position',[ffs+fus ffs+fus btn_wid uh],... 176 | 'Tag','ok_btn',... 177 | 'Callback',{@doOK,listbox}); 178 | 179 | cancel_btn = uicontrol('Style','pushbutton',... 180 | 'String',cancelstring,... 181 | 'Position',[ffs+2*fus+btn_wid ffs+fus btn_wid uh],... 182 | 'Tag','cancel_btn',... 183 | 'Callback',{@doCancel,listbox}); 184 | 185 | if smode == 2 186 | selectall_btn = uicontrol('Style','pushbutton',... 187 | 'String',getString(message('MATLAB:uistring:popupdialogs:SelectAll')),... 188 | 'Position',[ffs+fus 4*fus+ffs+uh listsize(1) uh],... 189 | 'Tag','selectall_btn',... 190 | 'Callback',{@doSelectAll, listbox}); 191 | 192 | if length(initialvalue) == length(liststring) 193 | set(selectall_btn,'Enable','off') 194 | end 195 | set(listbox,'Callback',{@doListboxClick, selectall_btn}) 196 | end 197 | 198 | set([fig, ok_btn, cancel_btn, listbox], 'KeyPressFcn', {@doKeypress, listbox}); 199 | 200 | 201 | % custom change 202 | if isempty(pos) 203 | set(fig,'Position',getnicedialoglocation(fp, get(fig,'Units'))); % only this line existed in original code 204 | else 205 | set(fig, 'Position', pos); % set the figure position as desired using custom code 206 | end 207 | 208 | % Make ok_btn the default button. 209 | setdefaultbutton(fig, ok_btn); 210 | 211 | % make sure we are on screen 212 | movegui(fig) 213 | set(fig, 'Visible','on'); drawnow; 214 | 215 | try 216 | % Give default focus to the listbox *after* the figure is made visible 217 | uicontrol(listbox); 218 | c = matlab.ui.internal.dialog.DialogUtils.disableAllWindowsSafely(); 219 | uiwait(fig); 220 | delete(c); 221 | catch 222 | if ishghandle(fig) 223 | delete(fig) 224 | end 225 | end 226 | 227 | if isappdata(0,'ListDialogAppData__') 228 | ad = getappdata(0,'ListDialogAppData__'); 229 | selection = ad.selection; 230 | value = ad.value; 231 | rmappdata(0,'ListDialogAppData__') 232 | else 233 | % figure was deleted 234 | selection = []; 235 | value = 0; 236 | end 237 | drawnow; % Update the view to remove the closed figure (g1031998) 238 | 239 | %% figure, OK and Cancel KeyPressFcn 240 | function doKeypress(src, evd, listbox) %#ok 241 | switch evd.Key 242 | case 'escape' 243 | doCancel([],[],listbox); 244 | end 245 | 246 | %% OK callback 247 | function doOK(ok_btn, evd, listbox) %#ok 248 | if (~isappdata(0, 'ListDialogAppData__')) 249 | ad.value = 1; 250 | ad.selection = get(listbox,'Value'); 251 | setappdata(0,'ListDialogAppData__',ad); 252 | delete(gcbf); 253 | end 254 | 255 | %% Cancel callback 256 | function doCancel(cancel_btn, evd, listbox) %#ok 257 | ad.value = 0; 258 | ad.selection = []; 259 | setappdata(0,'ListDialogAppData__',ad) 260 | delete(gcbf); 261 | 262 | %% SelectAll callback 263 | function doSelectAll(selectall_btn, evd, listbox) %#ok 264 | set(selectall_btn,'Enable','off') 265 | set(listbox,'Value',1:length(get(listbox,'String'))); 266 | 267 | %% Listbox callback 268 | function doListboxClick(listbox, evd, selectall_btn) %#ok 269 | % if this is a doubleclick, doOK 270 | if strcmp(get(gcbf,'SelectionType'),'open') 271 | doOK([],[],listbox); 272 | elseif nargin == 3 273 | if length(get(listbox,'String'))==length(get(listbox,'Value')) 274 | set(selectall_btn,'Enable','off') 275 | else 276 | set(selectall_btn,'Enable','on') 277 | end 278 | end -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/objFunction.m: -------------------------------------------------------------------------------- 1 | function varargout = objFunction(f0, x, l, dcIsIncluded, varargin) 2 | % 3 | % Computes the objective of the function 4 | % 5 | % f(f0, l) = x^T Z_l(f0)(Z_l(f0)^T Z_l(f0))^-1 Z_l^T(f0) x 6 | % 7 | % Input: 8 | % omega: fundamental frequency in radians 9 | % x: x length N 10 | % l: model order 11 | % epsilon: Regularization (default epsilon=0) 12 | % 13 | % Output: 14 | % objective: f(\omega, l) 15 | % alpha : (optional) least-squares solution 16 | % 17 | 18 | N = length(x); 19 | 20 | epsilon = 0; 21 | if length(varargin) == 2 22 | epsilon = N*varargin{2}; 23 | end 24 | 25 | n = (0:N-1)'-(N-1)/2; 26 | 27 | E = exp(1i*2*pi*f0*n*(1:l)); 28 | if dcIsIncluded 29 | C = [ones(N, 1), real(E)]; %cos(omega*n'*(1:l)); 30 | else 31 | C = real(E); 32 | end 33 | 34 | S = imag(E); %sin(omega*n'*(1:l)); 35 | bc = C'*x; 36 | bs = -S'*x; 37 | 38 | ac = (C'*C+epsilon*eye(size(C, 2)))\bc; % just solve it using an O(n^3) algorithm for now 39 | as = (S'*S+epsilon*eye(l))\bs; 40 | 41 | obj = bc'*ac + bs'*as; 42 | varargout{1} = obj; 43 | 44 | if nargout >= 2 45 | alpha = [ac; as]; 46 | varargout{2} = alpha; 47 | end 48 | 49 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/offlineprocessData.m: -------------------------------------------------------------------------------- 1 | function Obj=offlineprocessData(Obj,FullDictionarySpec1,numberSpeechVectors,NumberNoiseCodebookEntries) 2 | % tic 3 | % this is a so-called callback function. See more here 4 | % https://se.mathworks.com/help/matlab/matlab_prog/timer-callback-functions.html 5 | x= Obj.UserData{25}; 6 | x_clean= Obj.UserData{26}; 7 | time_indx=Obj.UserData{2}; 8 | frame=x(time_indx); 9 | frame_clean=x_clean(time_indx); 10 | 11 | win_input=frame_clean.*gausswin(length(frame)); 12 | pow_spec=periodgram_shi(win_input,256); 13 | 14 | % % % % % % rng(1); 15 | 16 | spec_pow=abs(fft(frame,256)).^2/length(frame); 17 | all_actC= ActivationFunction(spec_pow,FullDictionarySpec1); 18 | 19 | sp_actC = all_actC(1:numberSpeechVectors); 20 | noise_actC = all_actC(numberSpeechVectors+1:end); 21 | speechPower = FullDictionarySpec1(:,1:numberSpeechVectors)*sp_actC; 22 | noisePower = FullDictionarySpec1(:,numberSpeechVectors+1:end)*noise_actC; 23 | aprioriSNR = speechPower./max(noisePower,1e-12); 24 | %aprioriSNR = max(10^(-15/10),aprioriSNR); 25 | wghtPSD = (((1./(1+aprioriSNR))).^2).*spec_pow; 26 | wghtNoiseVar = (aprioriSNR./(1+aprioriSNR)).*noisePower; 27 | NMFPSDhat= wghtPSD+wghtNoiseVar; 28 | nmf_covariance = real(ifft(NMFPSDhat')); 29 | % nmf_covariance=NoiseNMF_PSD; 30 | %%Compute the LPC pre-whitener based on parametric NMF 31 | [nmf_lpc,erro_var] = levinson(nmf_covariance,22); 32 | [frame_p] = filter([nmf_lpc],1,... 33 | frame); 34 | frame=frame_p/std(frame_p)*std(frame); 35 | 36 | 37 | 38 | 39 | 40 | [f0Estimates,order,vad_prob]=Obj.UserData{4}(frame,1); 41 | if vad_prob<=.5 42 | f0Estimates=nan; 43 | end 44 | Obj.UserData{6}(Obj.UserData{1})=f0Estimates*Obj.UserData{5}; 45 | 46 | % Obj.UserData{7}(Obj.UserData{1},Obj.UserData{6}(Obj.UserData{1}),order,pow_spec); 47 | % plot(Obj.UserData{1},f0Estimates*Obj.UserData{5},'.');hold on; 48 | 49 | % Obj.UserData{8}{1}.XData(time_indx)=time_indx/Obj.UserData{5}; 50 | % Obj.UserData{8}{1}.YData(time_indx)=x(time_indx); 51 | if Obj.UserData{1}==1 52 | sample_vec=[1:Obj.UserData{11}*Obj.UserData{5}]/Obj.UserData{5}; 53 | Obj.UserData{12}{1}=plot(Obj.UserData{9},sample_vec,nan(length(sample_vec),1)); 54 | xlabel(Obj.UserData{9},'Time [s]') 55 | ylabel(Obj.UserData{9},'Time series'); 56 | 57 | Obj.UserData{12}{2}(1)=imagesc(Obj.UserData{8},Obj.UserData{20}, Obj.UserData{21},nan(Obj.UserData{22},length(Obj.UserData{20}))); 58 | ylim(Obj.UserData{8},[0,Obj.UserData{23}]) 59 | xlim(Obj.UserData{8},[0 Obj.UserData{11}]) 60 | axis(Obj.UserData{8},'xy'); 61 | hold on; 62 | Obj.UserData{12}{2}(2)=plot(Obj.UserData{15},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r-', 'linewidth',2); 63 | ylim(Obj.UserData{15},[0,Obj.UserData{23}]) 64 | xlim(Obj.UserData{15},[0 Obj.UserData{11}]) 65 | axis(Obj.UserData{15},'off'); 66 | ylabel(Obj.UserData{8},'Frequency') 67 | 68 | 69 | Obj.UserData{12}{3}=plot(Obj.UserData{10},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r-', 'linewidth',2); 70 | ylim(Obj.UserData{10},[0,1]) 71 | xlim(Obj.UserData{10},[0 Obj.UserData{11}]) 72 | ylabel(Obj.UserData{10},'Voicing Probability'); 73 | 74 | 75 | Obj.UserData{12}{4}=plot(Obj.UserData{17},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r.', 'linewidth',2); 76 | ylim(Obj.UserData{17},[0,Obj.UserData{24}]) 77 | xlim(Obj.UserData{17},[0 Obj.UserData{11}]) 78 | ylabel(Obj.UserData{17},'Order'); 79 | 80 | end 81 | % soundsc(x(time_indx)) 82 | Obj.UserData{12}{1}.YData(time_indx)=x(time_indx); 83 | xlim(Obj.UserData{9},[0,Obj.UserData{11}]); 84 | Obj.UserData{12}{2}(1).CData(:,Obj.UserData{1})=10*log10(abs(pow_spec(1:Obj.UserData{22}))); 85 | Obj.UserData{12}{2}(2).YData(Obj.UserData{1})=[ Obj.UserData{6}(Obj.UserData{1})]; 86 | xlim(Obj.UserData{8},[0,Obj.UserData{11}]); 87 | 88 | Obj.UserData{12}{3}.YData(Obj.UserData{1})=vad_prob; 89 | xlim(Obj.UserData{10},[0 Obj.UserData{11}]); 90 | 91 | Obj.UserData{12}{4}.YData(Obj.UserData{1})=order; 92 | xlim(Obj.UserData{17},[0 Obj.UserData{11}]); 93 | 94 | Obj.UserData{1}=Obj.UserData{1}+1; 95 | Obj.UserData{2}=Obj.UserData{2}+Obj.UserData{3}; 96 | 97 | 98 | 99 | % toc 100 | end 101 | function pow=periodgram_shi(x,nfft,fs) 102 | if nargin<3 103 | fs=1; 104 | end 105 | x=x(:); 106 | data_len=length(x); 107 | % matr=fft_shi(data_len,nfft); 108 | %normalized rectangular window consistent with energy 109 | f=fft(x,nfft)/sqrt(data_len); 110 | %normalized rectangular window consistent with matlab 111 | % f=matr*x/sqrt(data_len); 112 | pow=abs(f).^2; 113 | end 114 | 115 | function ActivationCoeff = ActivationFunction(noisyPSD,AR_PSD_BasisMtx,... 116 | prev_Frame_Actv_Coeff) 117 | 118 | ActivationCoeff = rand(size(AR_PSD_BasisMtx,2),1); 119 | numberIterations = 40; 120 | 121 | for times = 1:numberIterations 122 | Factor=AR_PSD_BasisMtx'*(((AR_PSD_BasisMtx*ActivationCoeff).^(0-2)).*... 123 | noisyPSD)./(AR_PSD_BasisMtx'*(AR_PSD_BasisMtx*... 124 | ActivationCoeff).^(0-1)); 125 | ActivationCoeff = ActivationCoeff.*Factor; 126 | end 127 | end 128 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/offlineprocessData_orig.m: -------------------------------------------------------------------------------- 1 | function Obj=offlineprocessData_orig(Obj, event) 2 | % tic 3 | % this is a so-called callback function. See more here 4 | % https://se.mathworks.com/help/matlab/matlab_prog/timer-callback-functions.html 5 | x= Obj.UserData{25}; 6 | x_clean= Obj.UserData{26}; 7 | time_indx=Obj.UserData{2}; 8 | frame=x(time_indx); 9 | frame_clean=x_clean(time_indx); 10 | [f0Estimates,order,vad_prob]=Obj.UserData{4}(frame,1); 11 | if vad_prob<=.5 12 | f0Estimates=nan; 13 | end 14 | Obj.UserData{6}(Obj.UserData{1})=f0Estimates*Obj.UserData{5}; 15 | win_input=frame_clean.*gausswin(length(frame)); 16 | pow_spec=periodgram_shi(win_input,256); 17 | % Obj.UserData{7}(Obj.UserData{1},Obj.UserData{6}(Obj.UserData{1}),order,pow_spec); 18 | % plot(Obj.UserData{1},f0Estimates*Obj.UserData{5},'.');hold on; 19 | 20 | % Obj.UserData{8}{1}.XData(time_indx)=time_indx/Obj.UserData{5}; 21 | % Obj.UserData{8}{1}.YData(time_indx)=x(time_indx); 22 | if Obj.UserData{1}==1 23 | sample_vec=[1:Obj.UserData{11}*Obj.UserData{5}]/Obj.UserData{5}; 24 | Obj.UserData{12}{1}=plot(Obj.UserData{9},sample_vec,nan(length(sample_vec),1)); 25 | xlabel(Obj.UserData{9},'Time [s]') 26 | ylabel(Obj.UserData{9},'Time series'); 27 | 28 | Obj.UserData{12}{2}(1)=imagesc(Obj.UserData{8},Obj.UserData{20}, Obj.UserData{21},nan(Obj.UserData{22},length(Obj.UserData{20}))); 29 | ylim(Obj.UserData{8},[0,Obj.UserData{23}]) 30 | xlim(Obj.UserData{8},[0 Obj.UserData{11}]) 31 | axis(Obj.UserData{8},'xy'); 32 | hold on; 33 | Obj.UserData{12}{2}(2)=plot(Obj.UserData{15},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r-', 'linewidth',2); 34 | ylim(Obj.UserData{15},[0,Obj.UserData{23}]) 35 | xlim(Obj.UserData{15},[0 Obj.UserData{11}]) 36 | axis(Obj.UserData{15},'off'); 37 | ylabel(Obj.UserData{8},'Frequency') 38 | 39 | 40 | Obj.UserData{12}{3}=plot(Obj.UserData{10},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r-', 'linewidth',2); 41 | ylim(Obj.UserData{10},[0,1]) 42 | xlim(Obj.UserData{10},[0 Obj.UserData{11}]) 43 | ylabel(Obj.UserData{10},'Voicing Probability'); 44 | 45 | 46 | Obj.UserData{12}{4}=plot(Obj.UserData{17},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r.', 'linewidth',2); 47 | ylim(Obj.UserData{17},[0,Obj.UserData{24}]) 48 | xlim(Obj.UserData{17},[0 Obj.UserData{11}]) 49 | ylabel(Obj.UserData{17},'Order'); 50 | 51 | end 52 | % soundsc(x(time_indx)) 53 | Obj.UserData{12}{1}.YData(time_indx)=x(time_indx); 54 | xlim(Obj.UserData{9},[0,Obj.UserData{11}]); 55 | Obj.UserData{12}{2}(1).CData(:,Obj.UserData{1})=10*log10(abs(pow_spec(1:Obj.UserData{22}))); 56 | Obj.UserData{12}{2}(2).YData(Obj.UserData{1})=[ Obj.UserData{6}(Obj.UserData{1})]; 57 | xlim(Obj.UserData{8},[0,Obj.UserData{11}]); 58 | 59 | Obj.UserData{12}{3}.YData(Obj.UserData{1})=vad_prob; 60 | xlim(Obj.UserData{10},[0 Obj.UserData{11}]); 61 | 62 | Obj.UserData{12}{4}.YData(Obj.UserData{1})=order; 63 | xlim(Obj.UserData{17},[0 Obj.UserData{11}]); 64 | 65 | Obj.UserData{1}=Obj.UserData{1}+1; 66 | Obj.UserData{2}=Obj.UserData{2}+Obj.UserData{3}; 67 | 68 | 69 | 70 | % toc 71 | end 72 | function pow=periodgram_shi(x,nfft,fs) 73 | if nargin<3 74 | fs=1; 75 | end 76 | x=x(:); 77 | data_len=length(x); 78 | % matr=fft_shi(data_len,nfft); 79 | %normalized rectangular window consistent with energy 80 | f=fft(x,nfft)/sqrt(data_len); 81 | %normalized rectangular window consistent with matlab 82 | % f=matr*x/sqrt(data_len); 83 | pow=abs(f).^2; 84 | end -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/processData.m: -------------------------------------------------------------------------------- 1 | function processData(Obj, event) 2 | % tic 3 | % this is a so-called callback function. See more here 4 | % https://se.mathworks.com/help/matlab/matlab_prog/timer-callback-functions.html 5 | 6 | 7 | FullDictionarySpec1=Obj.UserData{25}; 8 | numberSpeechVectors=Obj.UserData{26}; 9 | NumberNoiseCodebookEntries=Obj.UserData{27}; 10 | x=getaudiodata(Obj); 11 | % sqrt(3.1623e-5)/(sqrt(x'*x/length(x))) 12 | if length(x)>=8000 13 | x=x*sqrt(3.1623e-5)/(sqrt(x'*x/length(x))); 14 | end 15 | time_indx=Obj.UserData{2}; 16 | frame=x(time_indx); 17 | 18 | 19 | 20 | 21 | 22 | 23 | spec_pow=abs(fft(frame,256)).^2/length(frame); 24 | all_actC= ActivationFunction(spec_pow,FullDictionarySpec1); 25 | 26 | sp_actC = all_actC(1:numberSpeechVectors); 27 | noise_actC = all_actC(numberSpeechVectors+1:end); 28 | speechPower = FullDictionarySpec1(:,1:numberSpeechVectors)*sp_actC; 29 | noisePower = FullDictionarySpec1(:,numberSpeechVectors+1:end)*noise_actC; 30 | aprioriSNR = speechPower./max(noisePower,1e-12); 31 | %aprioriSNR = max(10^(-15/10),aprioriSNR); 32 | wghtPSD = (((1./(1+aprioriSNR))).^2).*spec_pow; 33 | wghtNoiseVar = (aprioriSNR./(1+aprioriSNR)).*noisePower; 34 | NMFPSDhat= wghtPSD+wghtNoiseVar; 35 | nmf_covariance = real(ifft(NMFPSDhat')); 36 | % nmf_covariance=NoiseNMF_PSD; 37 | %%Compute the LPC pre-whitener based on parametric NMF 38 | [nmf_lpc,erro_var] = levinson(nmf_covariance,22); 39 | [frame_p] = filter([nmf_lpc],1,... 40 | frame); 41 | frame=frame_p/std(frame_p)*std(frame); 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | [f0Estimates,order,vad_prob]=Obj.UserData{4}(frame,1); 50 | if vad_prob<=.5 51 | f0Estimates=nan; 52 | end 53 | Obj.UserData{6}(Obj.UserData{1})=f0Estimates*Obj.UserData{5}; 54 | win_input=frame.*gausswin(length(frame)); 55 | pow_spec=periodgram_shi(win_input,1024); 56 | % Obj.UserData{7}(Obj.UserData{1},Obj.UserData{6}(Obj.UserData{1}),order,pow_spec); 57 | % plot(Obj.UserData{1},f0Estimates*Obj.UserData{5},'.');hold on; 58 | 59 | % Obj.UserData{8}{1}.XData(time_indx)=time_indx/Obj.UserData{5}; 60 | % Obj.UserData{8}{1}.YData(time_indx)=x(time_indx); 61 | if Obj.UserData{1}==1 62 | sample_vec=[1:Obj.UserData{11}*Obj.UserData{5}]/Obj.UserData{5}; 63 | Obj.UserData{12}{1}=plot(Obj.UserData{9},sample_vec,nan(length(sample_vec),1)); 64 | ylabel(Obj.UserData{9},'Time [s]'); 65 | ylabel(Obj.UserData{9},'Time series'); 66 | 67 | Obj.UserData{12}{2}(1)=imagesc(Obj.UserData{8},Obj.UserData{20}, Obj.UserData{21},nan(Obj.UserData{22},length(Obj.UserData{20}))); 68 | ylim(Obj.UserData{8},[0,Obj.UserData{23}]) 69 | xlim(Obj.UserData{8},[0 Obj.UserData{11}-2]) 70 | axis(Obj.UserData{8},'xy'); 71 | hold on; 72 | Obj.UserData{12}{2}(2)=plot(Obj.UserData{15},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r-', 'linewidth',2); 73 | ylim(Obj.UserData{15},[0,Obj.UserData{23}]) 74 | xlim(Obj.UserData{15},[0 Obj.UserData{11}-2]) 75 | axis(Obj.UserData{15},'off'); 76 | ylabel(Obj.UserData{8},'Frequency') 77 | 78 | 79 | Obj.UserData{12}{3}=plot(Obj.UserData{10},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r-', 'linewidth',2); 80 | ylim(Obj.UserData{10},[0,1]) 81 | xlim(Obj.UserData{10},[0 Obj.UserData{11}-2]) 82 | ylabel(Obj.UserData{10},'Voicing Probability'); 83 | 84 | 85 | Obj.UserData{12}{4}=plot(Obj.UserData{17},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r.', 'linewidth',2); 86 | ylim(Obj.UserData{17},[0,Obj.Userdata{24}]) 87 | xlim(Obj.UserData{17},[0 Obj.UserData{11}-2]) 88 | ylabel(Obj.UserData{17},'Order'); 89 | 90 | end 91 | Obj.UserData{12}{1}.YData(time_indx)=x(time_indx); 92 | xlim(Obj.UserData{9},[0,Obj.UserData{11}-2]); 93 | Obj.UserData{12}{2}(1).CData(:,Obj.UserData{1})=10*log10(abs(pow_spec(1:Obj.Userdata{22}))); 94 | Obj.UserData{12}{2}(2).YData(Obj.UserData{1})=[ Obj.UserData{6}(Obj.UserData{1})]; 95 | xlim(Obj.UserData{8},[0,Obj.UserData{11}-2]); 96 | 97 | Obj.UserData{12}{3}.YData(Obj.UserData{1})=vad_prob; 98 | xlim(Obj.UserData{10},[0 Obj.UserData{11}-2]); 99 | 100 | Obj.UserData{12}{4}.YData(Obj.UserData{1})=order; 101 | xlim(Obj.UserData{17},[0 Obj.UserData{11}-2]); 102 | 103 | Obj.UserData{1}=Obj.UserData{1}+1; 104 | Obj.UserData{2}=Obj.UserData{2}+Obj.UserData{3}; 105 | 106 | 107 | 108 | % toc 109 | end 110 | function pow=periodgram_shi(x,nfft,fs) 111 | if nargin<3 112 | fs=1; 113 | end 114 | x=x(:); 115 | data_len=length(x); 116 | % matr=fft_shi(data_len,nfft); 117 | %normalized rectangular window consistent with energy 118 | f=fft(x,nfft)/sqrt(data_len); 119 | %normalized rectangular window consistent with matlab 120 | % f=matr*x/sqrt(data_len); 121 | pow=abs(f).^2; 122 | end 123 | 124 | function ActivationCoeff = ActivationFunction(noisyPSD,AR_PSD_BasisMtx,... 125 | prev_Frame_Actv_Coeff) 126 | 127 | ActivationCoeff = rand(size(AR_PSD_BasisMtx,2),1); 128 | numberIterations = 40; 129 | 130 | for times = 1:numberIterations 131 | Factor=AR_PSD_BasisMtx'*(((AR_PSD_BasisMtx*ActivationCoeff).^(0-2)).*... 132 | noisyPSD)./(AR_PSD_BasisMtx'*(AR_PSD_BasisMtx*... 133 | ActivationCoeff).^(0-1)); 134 | ActivationCoeff = ActivationCoeff.*Factor; 135 | end 136 | end 137 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/processData_orig.m: -------------------------------------------------------------------------------- 1 | function Obj=processData_orig(Obj, event) 2 | % tic 3 | % this is a so-called callback function. See more here 4 | % https://se.mathworks.com/help/matlab/matlab_prog/timer-callback-functions.html 5 | 6 | % x=x*sqrt(3.1623e-5)/(sqrt(x'*x/length(x))); 7 | % end 8 | 9 | reg_parameter=.1; 10 | frame=reg_parameter*Obj.frame; 11 | 12 | 13 | 14 | 15 | % 16 | % if time_indx(1) == 1 17 | % spec_pow=abs(fft(frame,2048)).^2/length(frame); 18 | % [mmsePSD,mmseState]=estnoiseg(spec_pow',length(frame)/Obj.UserData{5}); 19 | % mmse_covariance = real(ifft(mmsePSD')); 20 | % mmse_lpc = levinson(mmse_covariance,30); 21 | % [frame_p,filter_state] = filter([mmse_lpc],1,... 22 | % frame); 23 | % frame=frame_p/norm(frame_p)*norm(frame); 24 | % end 25 | 26 | 27 | 28 | 29 | [f0Estimates,order,vad_prob]=Obj.UserData{4}(frame,1); 30 | if vad_prob<=.5 31 | f0Estimates=nan; 32 | end 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Obj.UserData{6}(Obj.UserData{1})=f0Estimates*Obj.UserData{5}; 45 | win_input=frame.*gausswin(length(frame)); 46 | pow_spec=periodgram_shi(win_input,1024); 47 | % Obj.UserData{7}(Obj.UserData{1},Obj.UserData{6}(Obj.UserData{1}),order,pow_spec); 48 | % plot(Obj.UserData{1},f0Estimates*Obj.UserData{5},'.');hold on; 49 | 50 | % Obj.UserData{8}{1}.XData(time_indx)=time_indx/Obj.UserData{5}; 51 | % Obj.UserData{8}{1}.YData(time_indx)=x(time_indx); 52 | if Obj.UserData{1}==1 53 | sample_vec=[1:Obj.UserData{11}*Obj.UserData{5}]/Obj.UserData{5}; 54 | Obj.UserData{12}{1}=plot(Obj.UserData{9},sample_vec,nan(length(sample_vec),1)); 55 | ylabel(Obj.UserData{9},'Time [s]'); 56 | ylabel(Obj.UserData{9},'Time series'); 57 | 58 | Obj.UserData{12}{2}(1)=imagesc(Obj.UserData{8},Obj.UserData{20}, Obj.UserData{21},nan(Obj.UserData{22},length(Obj.UserData{20}))); 59 | ylim(Obj.UserData{8},[0,Obj.UserData{23}]) 60 | xlim(Obj.UserData{8},[0 Obj.UserData{11}-2]) 61 | axis(Obj.UserData{8},'xy'); 62 | hold on; 63 | Obj.UserData{12}{2}(2)=plot(Obj.UserData{15},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r-', 'linewidth',2); 64 | ylim(Obj.UserData{15},[0,Obj.UserData{23}]) 65 | xlim(Obj.UserData{15},[0 Obj.UserData{11}-2]) 66 | axis(Obj.UserData{15},'off'); 67 | ylabel(Obj.UserData{8},'Frequency') 68 | 69 | 70 | Obj.UserData{12}{3}=plot(Obj.UserData{10},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r-', 'linewidth',2); 71 | ylim(Obj.UserData{10},[0,1]) 72 | xlim(Obj.UserData{10},[0 Obj.UserData{11}-2]) 73 | ylabel(Obj.UserData{10},'Voicing Probability'); 74 | 75 | 76 | Obj.UserData{12}{4}=plot(Obj.UserData{17},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r.', 'linewidth',2); 77 | ylim(Obj.UserData{17},[0, Obj.UserData{24}]) 78 | xlim(Obj.UserData{17},[0 Obj.UserData{11}-2]) 79 | ylabel(Obj.UserData{17},'Order'); 80 | 81 | end 82 | Obj.UserData{12}{1}.YData(Obj.UserData{2})=frame; 83 | xlim(Obj.UserData{9},[0,Obj.UserData{11}-2]); 84 | Obj.UserData{12}{2}(1).CData(:,Obj.UserData{1})=10*log10(abs(pow_spec(1:[Obj.UserData{22}]))); 85 | Obj.UserData{12}{2}(2).YData(Obj.UserData{1})=[ Obj.UserData{6}(Obj.UserData{1})]; 86 | xlim(Obj.UserData{8},[0,Obj.UserData{11}-2]); 87 | 88 | Obj.UserData{12}{3}.YData(Obj.UserData{1})=vad_prob; 89 | xlim(Obj.UserData{10},[0 Obj.UserData{11}-2]); 90 | 91 | Obj.UserData{12}{4}.YData(Obj.UserData{1})=order; 92 | xlim(Obj.UserData{17},[0 Obj.UserData{11}-2]); 93 | 94 | Obj.UserData{1}=Obj.UserData{1}+1; 95 | Obj.UserData{2}=Obj.UserData{2}+Obj.UserData{3}; 96 | 97 | 98 | 99 | % toc 100 | end 101 | function pow=periodgram_shi(x,nfft,fs) 102 | if nargin<3 103 | fs=1; 104 | end 105 | x=x(:); 106 | data_len=length(x); 107 | % matr=fft_shi(data_len,nfft); 108 | %normalized rectangular window consistent with energy 109 | f=fft(x,nfft)/sqrt(data_len); 110 | %normalized rectangular window consistent with matlab 111 | % f=matr*x/sqrt(data_len); 112 | pow=abs(f).^2; 113 | end -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/private/singlePitchNLSCostsNaive.m: -------------------------------------------------------------------------------- 1 | %% singlePitchMlCostFunctionNaiveImplementationMod 2 | % A naive implementation of the single pitch ML cost-function. 3 | % 4 | %% Syntax: 5 | %# [costFunctionMatrix,fullPitchGrid] = ... 6 | %# singlePitchMlCostFunctionNaiveImplementation(data, maxModelOrder, ... 7 | %# resolution, pitchBounds) 8 | % 9 | %% Description: 10 | % A naive implementation of the single pitch ML cost-function. 11 | % The cost function is computed on a uniform (Fourier) grid for all model 12 | % orders up to the model orders specified by maxModelOrder. DC is also 13 | % included in the model. 14 | % 15 | % * data: A data vector of real- or complex-valued data. 16 | % * maxModelOrder: The maximum number of harmonic components that the cost 17 | % function is evaluated for. 18 | % * resolution: The resolution of the uniform pitch grid that the cost functions 19 | % are evaluated for. 20 | % * pitchBounds: A 2D vector specifiyng the lower and upper bound for the pitch 21 | % in cycles/sample. 22 | % * costFunctionMatrix: A matrix of cost functions. Each row corresponds to the 23 | % the cost function for a candidate model order. 24 | % * fullPitchGrid: The pitches corresponding to the values in the rows of the 25 | % cost function matrix. 26 | % 27 | %% Examples: 28 | %# data = recordedData; 29 | %# nData = length(data); 30 | %# maxModelOrder = 10; 31 | %# resolution = 1/(5*nData); 32 | %# pitchBounds = [1/nData;0.5-1/nData]; 33 | %# [costFunctionMatrix,fullPitchGrid] = ... 34 | %# singlePitchMlCostFunctionNaiveImplementationMod(data, maxModelOrder, ... 35 | %# resolution, pitchBounds); 36 | % 37 | function [costFunctionMatrix,fullPitchGrid, varargout] = ... 38 | singlePitchNLSCostsNaive(data,maxModelOrder,... 39 | resolution,pitchBounds,dcIsIncluded) 40 | 41 | nData = length(data); 42 | dataAreRealValued = isreal(data); 43 | time = (0:nData-1)'-(nData-1)/2; 44 | nFftGrid = ceil(1/resolution); 45 | minFftIndex = ceil(nFftGrid*pitchBounds(1)); 46 | maxFftIndex = floor(nFftGrid*pitchBounds(2)); 47 | validFftIndices = (minFftIndex:maxFftIndex)'; 48 | fullPitchGrid = validFftIndices/nFftGrid; 49 | nPitches = length(fullPitchGrid); 50 | % initialisation 51 | costFunctionMatrix = nan(maxModelOrder,maxFftIndex-minFftIndex+1); 52 | if dcIsIncluded 53 | phiMatrix = costFunctionMatrix; 54 | dcMatrix = costFunctionMatrix; 55 | end 56 | 57 | for iOrder = 1:maxModelOrder 58 | if dataAreRealValued 59 | maxFftIndex = ... 60 | floor(min(nFftGrid*pitchBounds(2),nFftGrid/(2*iOrder)-1)); 61 | else 62 | maxFftIndex = ... 63 | floor(min(nFftGrid*pitchBounds(2),nFftGrid/iOrder-1)); 64 | end 65 | pitchGrid = (minFftIndex:maxFftIndex)'/nFftGrid; 66 | nPitches = length(pitchGrid); 67 | modelOrders = 1:iOrder; 68 | for jPitch = 1:nPitches 69 | pitch = pitchGrid(jPitch); 70 | expMatrix = exp(1i*2*pi*pitch*time*modelOrders); 71 | if dataAreRealValued 72 | if dcIsIncluded 73 | sinusoidalMatrix = [ones(nData,1), real(expMatrix),... 74 | imag(expMatrix)]; 75 | else 76 | sinusoidalMatrix = [real(expMatrix),... 77 | imag(expMatrix)]; 78 | end 79 | else 80 | if dcIsIncluded 81 | sinusoidalMatrix = [ones(nData,1), expMatrix]; 82 | else 83 | sinusoidalMatrix = expMatrix; 84 | end 85 | 86 | end 87 | linearParameters = sinusoidalMatrix\data; 88 | if dcIsIncluded 89 | inverseFirstColumn = ... 90 | (sinusoidalMatrix'*sinusoidalMatrix)\[1;zeros(2*iOrder,1)]; 91 | dcMatrix(iOrder,jPitch) = linearParameters(1); 92 | phiMatrix(iOrder,jPitch) = inverseFirstColumn(1); 93 | end 94 | costFunctionMatrix(iOrder,jPitch) = ... 95 | real((data'*sinusoidalMatrix)*linearParameters); 96 | end 97 | end 98 | if dcIsIncluded 99 | varargout{1} = phiMatrix; 100 | varargout{2} = dcMatrix; 101 | else 102 | varargout = {}; 103 | end 104 | end 105 | -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/processData_MMSE.m: -------------------------------------------------------------------------------- 1 | function Obj=processData_MMSE(Obj, event) 2 | % tic 3 | % this is a so-called callback function. See more here 4 | % https://se.mathworks.com/help/matlab/matlab_prog/timer-callback-functions.html 5 | 6 | 7 | 8 | reg_parameter=0.1; 9 | frame=reg_parameter*Obj.frame; 10 | 11 | 12 | 13 | 14 | 15 | 16 | spec_pow=abs(fft(frame,2048)).^2/length(frame); 17 | if Obj.UserData{2}(1) == 1 18 | [mmsePSD,mmseState]=estnoiseg(spec_pow',length(frame)/Obj.UserData{5}); 19 | Obj.UserData{25}=mmseState; 20 | else %(i.e., for all the frames except the first one) 21 | 22 | [mmsePSD, Obj.UserData{25}]=estnoiseg(spec_pow',Obj.UserData{25}); 23 | end 24 | mmse_covariance = real(ifft(mmsePSD')); 25 | %%Compute MMSE LPC coefficients which will be also added to the dictionary 26 | %%spectral envelopes 27 | mmse_lpc = levinson(mmse_covariance,30); 28 | if Obj.UserData{2} == 1 29 | [frame_p,filter_state] = filter([mmse_lpc],1,... 30 | frame); 31 | Obj.UserData{26}=filter_state; 32 | else 33 | [frame_p,Obj.UserData{26}] = filter([mmse_lpc],1,... 34 | frame,Obj.UserData{26}); 35 | end 36 | 37 | frame=frame_p/norm(frame_p)*norm(frame); 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | [f0Estimates,order,vad_prob]=Obj.UserData{4}(frame,1); 46 | if vad_prob<=.5 47 | f0Estimates=nan; 48 | end 49 | Obj.UserData{6}(Obj.UserData{1})=f0Estimates*Obj.UserData{5}; 50 | win_input=frame.*gausswin(length(frame)); 51 | pow_spec=periodgram_shi(win_input,1024); 52 | % Obj.UserData{7}(Obj.UserData{1},Obj.UserData{6}(Obj.UserData{1}),order,pow_spec); 53 | % plot(Obj.UserData{1},f0Estimates*Obj.UserData{5},'.');hold on; 54 | 55 | % Obj.UserData{8}{1}.XData(time_indx)=time_indx/Obj.UserData{5}; 56 | % Obj.UserData{8}{1}.YData(time_indx)=x(time_indx); 57 | if Obj.UserData{1}==1 58 | sample_vec=[1:Obj.UserData{11}*Obj.UserData{5}]/Obj.UserData{5}; 59 | Obj.UserData{12}{1}=plot(Obj.UserData{9},sample_vec,nan(length(sample_vec),1)); 60 | ylabel(Obj.UserData{9},'Time [s]'); 61 | ylabel(Obj.UserData{9},'Time series'); 62 | 63 | Obj.UserData{12}{2}(1)=imagesc(Obj.UserData{8},Obj.UserData{20}, Obj.UserData{21},nan(Obj.UserData{22},length(Obj.UserData{20}))); 64 | ylim(Obj.UserData{8},[0,Obj.UserData{23}]) 65 | xlim(Obj.UserData{8},[0 Obj.UserData{11}-2]) 66 | axis(Obj.UserData{8},'xy'); 67 | hold on; 68 | Obj.UserData{12}{2}(2)=plot(Obj.UserData{15},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r-', 'linewidth',2); 69 | ylim(Obj.UserData{15},[0,Obj.UserData{23}]) 70 | xlim(Obj.UserData{15},[0 Obj.UserData{11}-2]) 71 | axis(Obj.UserData{15},'off'); 72 | ylabel(Obj.UserData{8},'Frequency') 73 | 74 | 75 | Obj.UserData{12}{3}=plot(Obj.UserData{10},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r-', 'linewidth',2); 76 | ylim(Obj.UserData{10},[0,1]) 77 | xlim(Obj.UserData{10},[0 Obj.UserData{11}-2]) 78 | ylabel(Obj.UserData{10},'Voicing Probability'); 79 | 80 | 81 | Obj.UserData{12}{4}=plot(Obj.UserData{17},Obj.UserData{20},nan(length(Obj.UserData{20}),1),'r.', 'linewidth',2); 82 | ylim(Obj.UserData{17},[0, Obj.UserData{24}]) 83 | xlim(Obj.UserData{17},[0 Obj.UserData{11}-2]) 84 | ylabel(Obj.UserData{17},'Order'); 85 | 86 | end 87 | Obj.UserData{12}{1}.YData(Obj.UserData{2})=frame; 88 | xlim(Obj.UserData{9},[0,Obj.UserData{11}-2]); 89 | Obj.UserData{12}{2}(1).CData(:,Obj.UserData{1})=10*log10(abs(pow_spec(1:[Obj.UserData{22}]))); 90 | Obj.UserData{12}{2}(2).YData(Obj.UserData{1})=[ Obj.UserData{6}(Obj.UserData{1})]; 91 | xlim(Obj.UserData{8},[0,Obj.UserData{11}-2]); 92 | 93 | Obj.UserData{12}{3}.YData(Obj.UserData{1})=vad_prob; 94 | xlim(Obj.UserData{10},[0 Obj.UserData{11}-2]); 95 | 96 | Obj.UserData{12}{4}.YData(Obj.UserData{1})=order; 97 | xlim(Obj.UserData{17},[0 Obj.UserData{11}-2]); 98 | 99 | Obj.UserData{1}=Obj.UserData{1}+1; 100 | Obj.UserData{2}=Obj.UserData{2}+Obj.UserData{3}; 101 | 102 | 103 | 104 | 105 | % toc 106 | end 107 | function pow=periodgram_shi(x,nfft,fs) 108 | if nargin<3 109 | fs=1; 110 | end 111 | x=x(:); 112 | data_len=length(x); 113 | % matr=fft_shi(data_len,nfft); 114 | %normalized rectangular window consistent with energy 115 | f=fft(x,nfft)/sqrt(data_len); 116 | %normalized rectangular window consistent with matlab 117 | % f=matr*x/sqrt(data_len); 118 | pow=abs(f).^2; 119 | end 120 | 121 | function ActivationCoeff = ActivationFunction(noisyPSD,AR_PSD_BasisMtx,... 122 | prev_Frame_Actv_Coeff) 123 | 124 | ActivationCoeff = rand(size(AR_PSD_BasisMtx,2),1); 125 | numberIterations = 40; 126 | 127 | for times = 1:numberIterations 128 | Factor=AR_PSD_BasisMtx'*(((AR_PSD_BasisMtx*ActivationCoeff).^(0-2)).*... 129 | noisyPSD)./(AR_PSD_BasisMtx'*(AR_PSD_BasisMtx*... 130 | ActivationCoeff).^(0-1)); 131 | ActivationCoeff = ActivationCoeff.*Factor; 132 | end 133 | end -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/sAudioRealTimeRecord.m: -------------------------------------------------------------------------------- 1 | % Based on https://se.mathworks.com/help/audio/ref/audiodevicereader-system-object.html 2 | clear 3 | clc 4 | close all 5 | 6 | % setup 7 | samplingFreq = 8000; % Hz 8 | recordingTime = 10; % s 9 | segmentTime = 0.025; % s 10 | segmentLength = round(segmentTime*samplingFreq); 11 | deviceName = 'Default'; % use getAudioDevices(audioDeviceReader) to see available devices 12 | micChannelNo = 1; 13 | 14 | % initialise the recording object 15 | % too see avai 16 | AudioRecObj = audioDeviceReader(... 17 | 'SampleRate', samplingFreq, ... 18 | 'SamplesPerFrame', segmentLength, ... 19 | 'NumChannels', length(micChannelNo), ... 20 | 'Device', deviceName); 21 | 22 | 23 | % 24 | % AudioRecObj = audioDeviceReader(... 25 | % 'SampleRate', samplingFreq, ... 26 | % 'SamplesPerFrame', segmentLength, ... 27 | % 'NumChannels', length(micChannelNo), ... 28 | % 'Device', deviceName); 29 | % Call setup to reduce the computational load of initialization in an 30 | % audio stream loop. 31 | AudioRecObj.setup(); 32 | 33 | % make a recording 34 | nSegments = floor(recordingTime/segmentTime); 35 | recordedData = nan(segmentLength, nSegments); 36 | actFrameTimes = nan(1,nSegments); 37 | for ii = 1:nSegments 38 | % tic 39 | [recordedSegment, numOverrun] = AudioRecObj(); 40 | % toc 41 | % here we do some processing 42 | recordedData(:,ii) = recordedSegment(:); 43 | pause(0.01) 44 | % end of processing 45 | actFrameTimes(ii) = toc; 46 | end 47 | AudioRecObj.release(); 48 | 49 | %% plotting 50 | figure(1) 51 | plot((1:recordingTime*samplingFreq)'/samplingFreq, recordedData(:)) 52 | xlabel('time [s]') 53 | ylabel('value [.]') 54 | title('Recorded signal') 55 | 56 | figure(2) 57 | plot((1:nSegments)*segmentTime, cumsum(actFrameTimes),'.') 58 | hold on 59 | plot((1:nSegments)*segmentTime, (1:nSegments)*segmentTime, '--') 60 | hold off 61 | legend('Processed segment time', 'Real-time limit') 62 | xlabel('sample recording time [s]') 63 | ylabel('finished processing a segment [s]') 64 | title('Processing time vs recorded time') -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/wb2ext.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_realtimeDemo_MATLAB/wb2ext.wav -------------------------------------------------------------------------------- /BF0NLS_realtimeDemo_MATLAB/white.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/BF0NLS_realtimeDemo_MATLAB/white.mat -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bayesian Pitch Tracking Using Harmonic model 2 | 3 | A fast pitch tracking algorithm using the harmonic model. 4 | 5 | The article for this work is available in 6 | [PUBLISHED](https://ieeexplore.ieee.org/abstract/document/8771212), 7 | [PREPRINT](https://www.researchgate.net/publication/334660108_Robust_Bayesian_Pitch_Tracking_Based_on_the_Harmonic_Model) 8 | 9 | # How to run 10 | This project contains both the MATLAB and CPP code 11 | 12 | For the MATLAB code: 13 | 14 | Run run_white_example.m (white Gaussian noise) or run_colored_example.m (factory noise) in MATLAB in the BF0NLS_MATLAB folder 15 | 16 | Run main.m in MATLAB in the BF0NLS_realtimeDemo_MATLAB folder 17 | 18 | 19 | 20 | 21 | # Examples 22 |

23 | 24 |

25 |
Figure 1: Pitch estimates for speech signals under 0 dB white Gaussian noise (Running time on my laptop is around 2.6 s).
26 | 27 | 28 |

29 | 30 |

31 | 32 |
Figure 2: Pitch estimates for speech signals under 0 dB factory noise (Running time on my laptop is around 9.3 s, and prewhitening is used).
33 | 34 |

35 | 36 |

37 | 38 |
Figure 3: Pitch estimates for music signals (vibrato flute sound) under 0 dB white Gaussian noise (Running time on my laptop is around 32.2 s).
39 | 40 | 41 | 42 | # How to cite 43 | L. Shi, J. K. Nielsen, J. R. Jensen, M. A. Little, and M. G. Chris- tensen, “Robust bayesian pitch tracking based on the harmonic model,” IEEE/ACM Trans. Audio, Speech, and Lang. Process., vol. 27, no. 11, pp. 1737–1751, Nov 2019. 44 | 45 | # References 46 | This fast computation of the likelihood function is based on the fast pitch estimation method proposed in 47 | 48 | Fast fundamental frequency estimation: Making a statistically efficient estimator computationally efficient. Nielsen, Jesper Kjær; Jensen, Tobias Lindstrøm; Jensen, Jesper Rindom; Christensen, Mads Græsbøll; Jensen, Søren Holdt. In: Signal Processing, 135, 2017, pp. 188-197. 49 | 50 | Bayesian Model Comparison With the g-Prior. Nielsen, Jesper Kjær; Christensen, Mads Græsbøll; Cemgil, Ali Taylan; Jensen, Søren Holdt. In: IEEE Transactions on Signal Processing, 62 (1), 2014, pp. 225-238. 51 | 52 | where the source code is available in 53 | https://github.com/jkjaer/fastF0Nls 54 | 55 | 56 | This noise PSD tracker used for prewhitening is based on the method proposed in 57 | 58 | Gerkmann, T. & Hendriks, R. C. Unbiased MMSE-Based Noise Power Estimation With Low Complexity and Low Tracking Delay, IEEE Trans Audio, Speech, Language Processing, 2012, 20, 1383-1393 59 | 60 | where the source code is available in 61 | http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html 62 | 63 | # Questions 64 | If you have any question regarding to the theory and code, feel free to contact 65 | 66 | Liming Shi, Aalborg university, Email: ls@create.aau.dk 67 | -------------------------------------------------------------------------------- /figures/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/figures/.DS_Store -------------------------------------------------------------------------------- /figures/1111.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/figures/1111.png -------------------------------------------------------------------------------- /figures/2222.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/figures/2222.png -------------------------------------------------------------------------------- /figures/3333.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LimingShi/Bayesian-Pitch-Tracking-Using-Harmonic-model/ad9a3fcfe60d2e97a635a92c2076ff1978ae3697/figures/3333.png --------------------------------------------------------------------------------