Пример #1
0
void Test::test_PolyMult_works() {
  srand(time(0));

  int n = 4;

  int randMin = -100, randMax = 100;

  Vector<Complex> P(n), Q(n);

  for(int i = 0; i < n; ++i) {

    double real = rand()%(randMax-randMin)+randMin;
    double imaginary = rand()%(randMax-randMin)+randMin;

    P[i] = Complex(real, imaginary);
    Q[i] = Complex(real, imaginary);
  }

  FFT fft;

  fft.preComputeOmega(n);
  Vector<Complex> resultsR = fft.polyMultR(P, Q, n);
  fft.preComputeRBS(n);
  Vector<Complex> resultsD = fft.polyMultD(P, Q, n);

  for(int i = 0; i < n; ++i) {
    if(resultsD[i] != resultsR[i])
      std::cout << "*** Failed ***" << std::endl;

    std::cout << resultsR[i] << " " << resultsD[i] << std::endl;
  }
}
Пример #2
0
void ofApp::audioIn(float * input, int bufferSize, int nChannels){

    if( !processAudio ) return;

    for (int i=0; i<bufferSize; i++) {
        trainingSample[i][0] = input[i];
    }

    if( record ){
        trainingData.addSample( trainingClassLabel, trainingSample );
    }

    if( pipeline.getTrained() ){

        //Run the prediction using the matrix of audio data
        pipeline.predict( trainingSample );

        //Update the FFT plot
        FFT *fft = pipeline.getFeatureExtractionModule< FFT >( 0 );
        if( fft ){
            vector< FastFourierTransform > &results =  fft->getFFTResultsPtr();
            magnitudePlot.setData( results[0].getMagnitudeData() );
        }

        //Update the likelihood plot
        classLikelihoodsPlot.update( pipeline.getClassLikelihoods() );
    }
}
Пример #3
0
bool test3() {
    FFT fft;

    vector<complex<double> > in, out, expected, temp;
    in.push_back(complex<double>(0.0,0.0));
    in.push_back(complex<double>(1.0,0.0));
    in.push_back(complex<double>(0.0,0.0));
    in.push_back(complex<double>(0.0,0.0));
    in.push_back(complex<double>(0.0,0.0));

    expected.push_back(complex<double>( 0.125,  0.0));
    expected.push_back(complex<double>( 0.088, -0.088));
    expected.push_back(complex<double>( 0.000, -0.125));
    expected.push_back(complex<double>(-0.088, -0.088));
    expected.push_back(complex<double>(-0.125,  0.0));
    expected.push_back(complex<double>(-0.088,  0.088));
    expected.push_back(complex<double>( 0.000,  0.125));
    expected.push_back(complex<double>( 0.088,  0.088));

    fft.FT(in,out);
    
    if (!checkEqual(expected,out)) {
	printError(expected,out);
	cout << __FILE__ << ": " << __LINE__ << endl;
	return false;
    } 
    
    fft.inverseFT(out, temp);

    return true;

}
Пример #4
0
//--------------------------------------------------------------
void ofApp::setup(){
    
    ofSetFrameRate(60);
    
    //Setup the FFT
    FFT fft;
    fft.init(FFT_WINDOW_SIZE,FFT_HOP_SIZE,1,FFT::RECTANGULAR_WINDOW,true,false,DATA_TYPE_MATRIX);

    //Setup the classifier
    RandomForests forest;
    forest.setForestSize( 10 );
    forest.setNumRandomSplits( 100 );
    forest.setMaxDepth( 10 );
    forest.setMinNumSamplesPerNode( 10 );

    //Add the feature extraction and classifier to the pipeline
    pipeline.addFeatureExtractionModule( fft );
    pipeline.setClassifier( forest );

    trainingClassLabel = 1;
    record = false;
    processAudio = true;
    trainingData.setNumDimensions( 1 ); //We are only going to use the data from one microphone channel, so the dimensions are 1
    trainingSample.resize( AUDIO_BUFFER_SIZE, 1 ); //We will set the training matrix to match the audio buffer size

    //Setup the audio card
    ofSoundStreamSetup(2, 1, this, AUDIO_SAMPLE_RATE, AUDIO_BUFFER_SIZE, 4);
}
Пример #5
0
void test_scalar_generic(int nfft)
{
    typedef typename FFT<T>::Complex Complex;
    typedef typename FFT<T>::Scalar Scalar;
    typedef typename VectorType<Container, Scalar>::type ScalarVector;
    typedef typename VectorType<Container, Complex>::type ComplexVector;

    FFT<T>        fft;
    ScalarVector  tbuf(nfft);
    ComplexVector freqBuf;

    for (int k = 0; k < nfft; ++k)
        tbuf[k] = (T)(rand() / (double)RAND_MAX - .5);

    // make sure it DOESN'T give the right full spectrum answer
    // if we've asked for half-spectrum
    fft.SetFlag(fft.HalfSpectrum);
    fft.fwd(freqBuf, tbuf);
    VERIFY((size_t)freqBuf.size() == (size_t)((nfft >> 1) + 1));
    VERIFY(fft_rmse(freqBuf, tbuf) < test_precision<T>());  // gross check

    fft.ClearFlag(fft.HalfSpectrum);
    fft.fwd(freqBuf, tbuf);
    VERIFY((size_t)freqBuf.size() == (size_t)nfft);
    VERIFY(fft_rmse(freqBuf, tbuf) < test_precision<T>());  // gross check

    if (nfft & 1)
        return; // odd FFTs get the wrong size inverse FFT

    ScalarVector tbuf2;
    fft.inv(tbuf2, freqBuf);
    VERIFY(dif_rmse(tbuf, tbuf2) < test_precision<T>());  // gross check


    // verify that the Unscaled flag takes effect
    ScalarVector tbuf3;
    fft.SetFlag(fft.Unscaled);

    fft.inv(tbuf3, freqBuf);

    for (int k = 0; k < nfft; ++k)
        tbuf3[k] *= T(1. / nfft);


    // for (size_t i=0;i<(size_t) tbuf.size();++i)
    //    cout << "freqBuf=" << freqBuf[i] << " in2=" << tbuf3[i] << " -  in=" << tbuf[i] << " => " << (tbuf3[i] - tbuf[i] ) <<  endl;

    VERIFY(dif_rmse(tbuf, tbuf3) < test_precision<T>());  // gross check

    // verify that ClearFlag works
    fft.ClearFlag(fft.Unscaled);
    fft.inv(tbuf2, freqBuf);
    VERIFY(dif_rmse(tbuf, tbuf2) < test_precision<T>());  // gross check
}
Пример #6
0
void fft_Y(MultiArray<complex<float>, 3> &a) {
    FFT<float> fft;
    int ny = a.dims()[1];
    for (int z = 0; z < a.dims()[2]; z++) {
        for (int x = 0; x < a.dims()[0]; x++) {
            VectorXcf fft_in = a.slice<1>({x,0,z},{0,ny,0}).asArray();
            VectorXcf fft_out(ny);
            fft.fwd(fft_out, fft_in);
            a.slice<1>({x,0,z},{0,ny,0}).asArray() = fft_out;
        }
    }
}
Пример #7
0
void fft_Z(MultiArray<complex<float>, 3> &a) {
    FFT<float> fft;
    int nz = a.dims()[2];
    for (int x = 0; x < a.dims()[0]; x++) {
        for (int y = 0; y < a.dims()[1]; y++) {
            VectorXcf fft_in = a.slice<1>({x,y,0},{0,0,nz}).asArray();
            VectorXcf fft_out(nz);
            fft.fwd(fft_out, fft_in);
            a.slice<1>({x,y,0},{0,0,nz}).asArray() = fft_out;
        }
    }
}
Пример #8
0
void fft_X(MultiArray<complex<float>, 3> &a) {
    FFT<float> fft;
    int nx = a.dims()[0];
    for (int z = 0; z < a.dims()[2]; z++) {
        for (int y = 0; y < a.dims()[1]; y++) {
            VectorXcf fft_in = a.slice<1>({0,y,z},{nx,0,0}).asArray();
            VectorXcf fft_out(nx);
            fft.fwd(fft_out, fft_in);
            a.slice<1>({0,y,z},{nx,0,0}).asArray() = fft_out;
        }
    }
}
Пример #9
0
void test_return_by_value(int len)
{
    VectorXf in;
    VectorXf in1;
    in.setRandom( len );
    VectorXcf out1,out2;
    FFT<float> fft;

    fft.SetFlag(fft.HalfSpectrum );

    fft.fwd(out1,in);
    out2 = fft.fwd(in);
    VERIFY( (out1-out2).norm() < test_precision<float>() );
    in1 = fft.inv(out1);
    VERIFY( (in1-in).norm() < test_precision<float>() );
}
Пример #10
0
void fwd_inv(size_t nfft)
{
    typedef typename NumTraits<T_freq>::Real Scalar;
    vector<T_time> timebuf(nfft);
    RandomFill(timebuf);

    vector<T_freq> freqbuf;
    static FFT<Scalar> fft;
    fft.fwd(freqbuf,timebuf);

    vector<T_time> timebuf2;
    fft.inv(timebuf2,freqbuf);

    long double rmse = mag2(timebuf - timebuf2) / mag2(timebuf);
    cout << "roundtrip rmse: " << rmse << endl;
}
Пример #11
0
void test_complex_generic(int nfft)
{
    typedef typename FFT<T>::Complex Complex;
    typedef typename VectorType<Container,Complex>::type ComplexVector;

    FFT<T> fft;

    ComplexVector inbuf(nfft);
    ComplexVector outbuf;
    ComplexVector buf3;
    for (int k=0;k<nfft;++k)
        inbuf[k]= Complex( (T)(rand()/(double)RAND_MAX - .5), (T)(rand()/(double)RAND_MAX - .5) );
    fft.fwd( outbuf , inbuf);

    VERIFY( fft_rmse(outbuf,inbuf) < test_precision<T>()  );// gross check
    fft.inv( buf3 , outbuf);

    VERIFY( dif_rmse(inbuf,buf3) < test_precision<T>()  );// gross check

    // verify that the Unscaled flag takes effect
    ComplexVector buf4;
    fft.SetFlag(fft.Unscaled);
    fft.inv( buf4 , outbuf);
    for (int k=0;k<nfft;++k)
        buf4[k] *= T(1./nfft);
    VERIFY( dif_rmse(inbuf,buf4) < test_precision<T>()  );// gross check

    // verify that ClearFlag works
    fft.ClearFlag(fft.Unscaled);
    fft.inv( buf3 , outbuf);
    VERIFY( dif_rmse(inbuf,buf3) < test_precision<T>()  );// gross check
}
Пример #12
0
int main()
{
	int n;
	scanf("%d", &n);
	while(n--)
	{
		string a, b;
		cin>>a>>b;
		if(a == "0" || b == "0")
		{
			cout<<"0\n";
			continue;
		}
		vector<int> ai;
		vector<int> bi;
		vector<int> res;
		for(int i = a.size()-1; i >= 0; --i)
		{
			ai.pb((a[i]-'0'));
		}
		for(int i = b.size()-1; i >= 0; --i)
		{
			bi.pb((b[i]-'0'));
		}
		FFT f;
		f.multiply(ai, bi, res);
		int carry=0;
		for(size_t i = 0; i < res.size(); i++)
		{
			res[i] += carry;
			carry = res[i]/10;
			res[i] %= 10;
		}
		int i = res.size()-1;
		while(res[i] == 0)
			i--;
		while(i >= 0)
		{
			cout<<res[i];
			--i;
		}
		cout<<endl;
	}
	return 0;
}
Пример #13
0
void Test::test_PolyMult_recursive() {
  int n = 2;
  Vector<Complex> P(n),Q(n);

  P[0] = Complex(2,0);
  P[1] = Complex(2,0);

  Q[0] = Complex(2,0);
  Q[1] = Complex(2,0);

  FFT fft;

  fft.preComputeOmega(n);
  Vector<Complex> results = fft.polyMultR(P, Q, n);

  for(Complex c : results) {
    std::cout << c << std::endl;
  }
}
Пример #14
0
vector<vector<double> > compute(vector<double> sound)
{
    FFT fft;
    vector<vector<double> > res;
    vector<complex<double> > tmp;
    while(sound.size()%SMPLS_PR_BLCK)
        sound.push_back(0);
    for(int i=0;i<sound.size();i+=SMPLS_PR_BLCK)
    {
        vector<complex<double> > t;
        for(int j=0;j<SMPLS_PR_BLCK;j++)
            t.push_back(complex<double>(sound[i+j],0));
        tmp = fft.compute(t);
        vector<double> tmp2;
        for(int i=0;i<tmp.size();i++)
            tmp2.push_back(tmp[i].real());
        res.push_back(transform(tmp2));
    }
    return res;
}
Пример #15
0
void Test::test_FFT_works() {
  srand(time(0));

  int n = 4;
  Vector<Complex> P(n);

  int randMin = -100, randMax = 100;

  for(int i = 0; i < n; ++i) {

    double real = rand()%(randMax-randMin)+randMin;
    double imaginary = rand()%(randMax-randMin)+randMin;

    P[i] = Complex(real, imaginary);
  }

  // P[0] = Complex(2,0);
  // P[1] = Complex(2,0);
  // P[2] = Complex(2,0);
  // P[3] = Complex(2,0);

  Vector<Complex> x = Vector<Complex> (n);

  for(int i = 0; i < n; i++) {
    x[i] = Complex(cos(2*PI/n * i), sin(2*PI/n * i));
  }

  FFT fft;
  fft.preComputeRBS(n);

  Vector<Complex> algebraic = fft.algebraic(P, n, x);
  Vector<Complex> recursive = fft.recursive(P, n, x, 1);
  Vector<Complex> dynamic = fft.dynamic(P, n, x);

  for(int i = 0; i < n; ++i) {
    std::cout << "A(" << i << "): " << algebraic[i] << std::endl;
    std::cout << "R(" << i << "): " << recursive[i] << std::endl;
    std::cout << "D(" << i << "): " << dynamic[i] << std::endl;
    std::cout << std::endl;
  }
}
Пример #16
0
int main(int argc, char*argv[])
{
        // create FFT class implementation
        // each implementation has its own plan map.
        FFT<double> fft;
        // create some data
        size_t N = 1024 * 1024;
        std::vector<complex<double>,fftalloc<complex<double> > > data(N);
        std::vector<complex<double>,fftalloc<complex<double> > > dataFourier(N);
        std::vector<complex<double>,fftalloc<complex<double> > > dataCalc(N);
        std::cout << "1) --- original data ---" << endl;
        for(std::vector<complex<double> >::size_type i = 0; i != data.size(); i++) {
            data[i] = polar(sin(double(i)/N * M_PI * 2), 0.0);
//            std::cout << i << data[i] << endl;
        }

        // fft
        std::cout << "2) --- fft data ---" << endl;
        fft.fwd(dataFourier, data);
        std::cout << "speed / ms: " << fft.speed()/1000 << endl;
//        for(std::vector<complex<double> >::size_type i = 0; i != dataFourier.size(); i++) {
//            std::cout << i << dataFourier[i] << endl;
//        }

        // ifft
        std::cout << "3) --- ifft data ---" << endl;
        fft.inv(dataCalc, dataFourier);
        std::cout << "speed / ms: " << fft.speed()/1000 << endl;
//        for(std::vector<complex<double> >::size_type i = 0; i != dataCalc.size(); i++) {
//            std::cout << i << dataCalc[i] << endl;
//        }
//        std::cout << "4) --- comparison data ---" << endl;
//        for(std::vector<complex<double> >::size_type i = 0; i != dataCalc.size(); i++) {
//            std::cout << i << data[i] - dataCalc[i] << endl;
//        }

    std::getchar();
    return 0;
}
Пример #17
0
bool test1() {
    FFT fft;
    vector<complex<double> > in, out, expected, temp;
    in.push_back(complex<double>(1.0,0.0));
    in.push_back(complex<double>(0.0,0.0));
    in.push_back(complex<double>(0.0,0.0));
    in.push_back(complex<double>(0.0,0.0));
    in.push_back(complex<double>(0.0,0.0));
    in.push_back(complex<double>(0.0,0.0));
    in.push_back(complex<double>(0.0,0.0));
    in.push_back(complex<double>(0.0,0.0));

    expected.push_back(complex<double>(0.125,0.0));
    expected.push_back(complex<double>(0.125,0.0));
    expected.push_back(complex<double>(0.125,0.0));
    expected.push_back(complex<double>(0.125,0.0));
    expected.push_back(complex<double>(0.125,0.0));
    expected.push_back(complex<double>(0.125,0.0));
    expected.push_back(complex<double>(0.125,0.0));
    expected.push_back(complex<double>(0.125,0.0));

    fft.FT(in,out);
    
    if (!checkEqual(expected,out)) {
	printError(expected,out);
	return false;
    } 

    fft.inverseFT(out, temp);

    if (!checkEqual(in,temp)) {
	printError(in,temp);
	return false;
    }

    return true;
    
}
Пример #18
0
int main()
{
  int N = 32768;
  double Temp = 1.0/8192.0;
  printf("N: %d, Temp: %.15le\n",N, Temp);

  IAGRID iagrid(N,N,Temp);
  double* omega;
  double* tau;
  iagrid.GetGrid(omega,tau);

  complex<double>* G_f = new complex<double>[N];
  complex<double>* G_t = new complex<double>[N];

  iagrid.InitG(G_f,0.3,0.5,0);
  PrintFunc("gfin",N,G_f,omega);
  
//-----------------glavni deo koda----------------//
  FFT fft;                        //pravimo objekat fft
  fft.Initialize(&iagrid);        //inicijalizujemo ga za temperaturu 0.05 i broj tachaka N
  for (int n=0; n<20; n++)           //ovde staviti koliko puta da uradi FFT u oba smera
  { 
    char str_fn_f[20];  //priprema naziva fajlova za ispis
    char str_fn_t[20]; 
    sprintf(str_fn_f, "gfout.dat.%d", n); 
    sprintf(str_fn_t, "gtout.dat.%d", n); 

    fft.FtoT(G_f, G_t);           //FFT freq to time

    fft.TtoF(G_t, G_f);           //FFT time to freq 

    //ispis rezultata u fajl
    PrintFunc(str_fn_f,N,G_f,omega);
    PrintFunc(str_fn_t,N,G_t,tau);
  }
//-------------------------------------------------//  
  return 0;
}
Пример #19
0
void Test::run_FFT_recursive() {
  int minN = 32, maxN = 20000000;

  std::cout << "FFT recursive" << std::endl
            << "N" << '\t' << "Time" << std::endl;

  for(int n = minN; n <= maxN; n*=2) {

    FFT fft;
    fft.preComputeOmega(n);

    int runTime = averageRuntime([&](){

      Vector<Complex> P = fft.makeRandomVector(n, -1, 1);
      Vector<Complex> Q = fft.makeRandomVector(n, -1, 1);

      Vector<Complex> result = fft.polyMultR(P, Q, n);

    }, RUNS);

    std::cout << n << '\t' << runTime << std::endl;
  }
}
Пример #20
0
void bench(int nfft,bool fwd,bool unscaled=false, bool halfspec=false)
{
    typedef typename NumTraits<T>::Real Scalar;
    typedef typename std::complex<Scalar> Complex;
    int nits = NDATA/nfft;
    vector<T> inbuf(nfft);
    vector<Complex > outbuf(nfft);
    FFT< Scalar > fft;

    if (unscaled) {
        fft.SetFlag(fft.Unscaled);
        cout << "unscaled ";
    }
    if (halfspec) {
        fft.SetFlag(fft.HalfSpectrum);
        cout << "halfspec ";
    }


    std::fill(inbuf.begin(),inbuf.end(),0);
    fft.fwd( outbuf , inbuf);

    BenchTimer timer;
    timer.reset();
    for (int k=0;k<8;++k) {
        timer.start();
        if (fwd)
            for(int i = 0; i < nits; i++)
                fft.fwd( outbuf , inbuf);
        else
            for(int i = 0; i < nits; i++)
                fft.inv(inbuf,outbuf);
        timer.stop();
    }

    cout << nameof<Scalar>() << " ";
    double mflops = 5.*nfft*log2((double)nfft) / (1e6 * timer.value() / (double)nits );
    if ( NumTraits<T>::IsComplex ) {
        cout << "complex";
    }else{
        cout << "real   ";
        mflops /= 2;
    }


    if (fwd)
        cout << " fwd";
    else
        cout << " inv";

    cout << " NFFT=" << nfft << "  " << (double(1e-6*nfft*nits)/timer.value()) << " MS/s  " << mflops << "MFLOPS\n";
}
Пример #21
0
		virtual void DoProcess()
		{
			Int complexsize = ComplexSize();//(UInt)(this->PeriodSize() / 2) + 1;
			//asdf++;
			//if(asdf>1)
			//{
			//fftw_execute(p1);
			//cout << this->PeriodSize() << endl;
			fft.Forward(this->tmpbuffer,this->PeriodSize());
			memcpy(lastSpectrum,fft.Data_c,ComplexSize()*sizeof(fftw_complex));
#ifdef CEPSTRUM
			for(UInt i=0;i<complexsize;i++) {
				auto sine=fft.Data_c[i][1];
				auto cosine=fft.Data_c[i][0];
				double amplitude=sqrt(sine*sine+cosine*cosine);
				//double phase=atan2(cosine,sine);
				if(amplitude<0.00001) //10^-5
					fft2.Data[i]=-5;
				else fft2.Data[i]=logf(amplitude)/M_LN10;
				//fft2.Data[i]=amplitude;
			}
			fft2.Forward();
			for(UInt i=0;i<ComplexSize2();i++)
			{
				fft2.Data_c[i][0] = fft2.Data_c[i][0]*coefficients2[i];
				fft2.Data_c[i][1] = fft2.Data_c[i][1]*coefficients2[i];
			}
			fft2.Reverse();
			for(UInt i=0;i<complexsize;i++) {
				auto sine=fft.Data_c[i][1];
				auto cosine=fft.Data_c[i][0];
				double amplitude=pow(10,fft2.Data[i]/fft2.size);
				double phase=atan2(cosine,sine);
				fft.Data_c[i][1] = cos(phase)*amplitude;
				fft.Data_c[i][0] = sin(phase)*amplitude;
			}
#endif
			
				//int shift=21;
				/*for(UInt i=0;i<complexsize;i++)
				{
					tmpcomplex[i][0] = tmpcomplex[i][0]*coefficients[i];
					tmpcomplex[i][1] = tmpcomplex[i][1]*coefficients[i];
				}*/
				//asdf=0;
			//}

			//tmpcomplex[0][0]=0;
			//tmpcomplex[0][1]=0;


			/*for(UInt i=(complexsize-1)/2+1;i<complexsize;i++)
			{
				tmpcomplex[i][0]=0;
				tmpcomplex[i][1]=0;
			}*/
			//memcpy(tmpcomplex,fft.Data_c,complexsize*sizeof(fftw_complex));
			if(freq_scale==1.)
			{
				for(UInt i=0;i<complexsize;i++)
				{
					fft.Data_c[i][0] = fft.Data_c[i][0]*coefficients[i];
					fft.Data_c[i][1] = fft.Data_c[i][1]*coefficients[i];
				}
				goto trolled;
			}
			/*Int skip=this->BuffersPerPeriod/this->overlapcount;
			if(skip<1)skip=1;
			UInt overlapcount=this->BuffersPerPeriod/skip;
			Int skip_samples=this->PeriodSize()/overlapcount;*/

			//for(Int i=complexsize-1;i>=0;i--)
			bool rev;
			rev=freq_scale>1.;
			for(Int i=rev?Int(complexsize)-1:0;rev?(i>=0):(i<Int(complexsize));rev?i--:i++)
			{
				int i2;
				//if(i>50)
				double asdf=((double)i)/freq_scale; //source frequency
				i2=(int)asdf;
				if(i2==0 || i==0)	//prevent division by zero
					continue;
				if(i2+1>=(int)complexsize)
				{
					fft.Data_c[i][0]=fft.Data_c[i][1]=0.;
					continue;
				}
				double trololo=asdf-i2;
				//double freq1=(asdf/(double)(complexsize-1))*0.5;
				double period1=(double)fft.size/(double)asdf;
				//double freq2=(double)i/(double)(complexsize-1)*0.5;
				double period2=(double)fft.size/(double)i;
				double sine=(tmpcomplex[i2][1]*(1.0-trololo) + tmpcomplex[i2+1][1]*trololo);
				double cosine=(tmpcomplex[i2][0]*(1.0-trololo) + tmpcomplex[i2+1][0]*trololo);

				double amplitude=sqrt(sine*sine+cosine*cosine);
				
				
				double phase=atan2(cosine,sine);	//radians; [-pi,pi]
				//double phase_delta1=(skip_samples%period1)/period1*(2*M_PI);
				phase=phase*((double)period1);
				//phase=phase/((double)(M_PI*2));
				//phase=phase*((double)(M_PI*2));
				phase=phase/((double)period2);
				
				//double phase=atan2(tmpcomplex[i][0],tmpcomplex[i][1]);
				
				//phase*=1.5;
				//if(i==100)cout << phase << endl;
				//else i2=i;
				//fft.Data_c[i][0] = (fft.Data_c[i2][0]*(1.0-trololo) + fft.Data_c[i2+1][0]*trololo)*coefficients[i];
				//fft.Data_c[i][1] = (fft.Data_c[i2][1]*(1.0-trololo) + fft.Data_c[i2+1][1]*trololo)*coefficients[i];
				amplitude*=coefficients[i];
				fft.Data_c[i][1] = cos(phase)*amplitude;
				fft.Data_c[i][0] = sin(phase)*amplitude;
			}
		trolled:
			//fftw_execute(p2);
			/*int shift=50;
			for(Int i=complexsize-1-shift;i>=0;i--)
			{
				fft.Data_c[i+shift][0]=fft.Data_c[i][0]*coefficients[i+shift];
				fft.Data_c[i+shift][1]=fft.Data_c[i][1]*coefficients[i+shift];
			}*/
			double* d=fft.Reverse(this->PeriodSize());
			memcpy(this->tmpbuffer,d,sizeof(double)*this->PeriodSize());
			Int ps=this->PeriodSize();
			for(Int i=0;i<ps;i++)
				this->tmpbuffer[i] /= fft.size;
		}
Пример #22
0
boolean CAlgorithmHilbertTransform::process(void)
{

	uint32 l_ui32ChannelCount = ip_pMatrix->getDimensionSize(0);
	uint32 l_ui32SamplesPerChannel = ip_pMatrix->getDimensionSize(1);

	IMatrix* l_pInputMatrix = ip_pMatrix;
	IMatrix* l_pOutputEnvelopeMatrix = op_pEnvelopeMatrix;
	IMatrix* l_pOutputPhaseMatrix = op_pPhaseMatrix;

	FFT< double, internal::kissfft_impl<double > > fft;

	if(this->isInputTriggerActive(OVP_Algorithm_HilbertTransform_InputTriggerId_Process))
	{
		//Computing Hilbert transform for all channels
		for(uint32 channel=0; channel<l_ui32ChannelCount; channel++)
		{
			//Initialization of buffer vectors
			m_vecXcdSignalBuffer = RowVectorXcd::Zero(l_ui32SamplesPerChannel);
			m_vecXcdSignalFourier = RowVectorXcd::Zero(l_ui32SamplesPerChannel);

			//Initialization of vector h used to compute analytic signal
			m_vecXdHilbert.resize(l_ui32SamplesPerChannel);
			m_vecXdHilbert(0) = 1.0;
			if(l_ui32SamplesPerChannel%2 == 0)
			{
				m_vecXdHilbert(l_ui32SamplesPerChannel/2) = 1.0;
				for(uint32 i=1; i<l_ui32SamplesPerChannel/2; i++)
				{
					m_vecXdHilbert(i) = 2.0;
				}
				for(uint32 i=(l_ui32SamplesPerChannel/2)+1; i<l_ui32SamplesPerChannel; i++)
				{
					m_vecXdHilbert(i) = 0.0;
				}
			}
			else
			{
				m_vecXdHilbert((l_ui32SamplesPerChannel/2)+1) = 1.0;
				for(uint32 i=1; i<(l_ui32SamplesPerChannel/2)+1; i++)
				{
					m_vecXdHilbert(i) = 2.0;
				}
					for(uint32 i=(l_ui32SamplesPerChannel/2)+2; i<l_ui32SamplesPerChannel; i++)
				{
					m_vecXdHilbert(i) = 0.0;
				}
			}

			//Copy input signal chunk on buffer
			for(uint32 samples=0; samples<l_ui32SamplesPerChannel;samples++)
			{
				m_vecXcdSignalBuffer(samples).real(l_pInputMatrix->getBuffer()[samples + channel * (l_ui32SamplesPerChannel)]);
				m_vecXcdSignalBuffer(samples).imag(0.0);
			}

			//Fast Fourier Transform of input signal
			fft.fwd(m_vecXcdSignalFourier, m_vecXcdSignalBuffer);

			//Apply Hilbert transform by element-wise multiplying fft vector by h
			m_vecXcdSignalFourier = m_vecXcdSignalFourier * m_vecXdHilbert;

			//Inverse Fast Fourier transform
			fft.inv(m_vecXcdSignalBuffer, m_vecXcdSignalFourier); //m_vecXcdSignalBuffer is now the analytical signal of the initial input signal

			//Compute envelope and phase and pass it to the corresponding output
			for(uint32 samples=0; samples<l_ui32SamplesPerChannel;samples++)
			{
				l_pOutputEnvelopeMatrix->getBuffer()[samples + channel*samples] = abs(m_vecXcdSignalBuffer(samples));
				l_pOutputPhaseMatrix->getBuffer()[samples + channel*samples] = arg(m_vecXcdSignalBuffer(samples));
			}

		}
	}
	return true;
}
Пример #23
0
void process(int input_fd, int output_fd) {
    off_t current_offset = 0;
    std::complex<float> *frame_data = NULL;
    std::complex<float> *last_frame_data = NULL;

    size_t count = 0;
    size_t frame_count = 0, hop_factor = 8;

    FFT<float> *ifft = NULL;
    std::complex<float> *ifft_result = NULL;
    int16_t *samples = NULL;
    float scale_factor = 1.0;

    for (;;) {
        BlockSet blkset;
        try {
            blkset.begin_read(input_fd, current_offset);
            delete [] last_frame_data;
            last_frame_data = frame_data;
            frame_data = blkset.load_alloc_block<std::complex<float> >(REPLAY_PVOC_BLOCK, count);

            if (ifft == NULL) {
                ifft = new FFT<float>(count, FFT<float>::INVERSE);
                ifft_result = new std::complex<float>[count];
                samples = new int16_t[count];
                scale_factor = float(count) * float(hop_factor);
            }

        } catch (...) {
            /* 
             * if it bombs out we are probably past end of file but who knows
             * so we just close the output_fd and rethrow. This is really ugly
             * but will make sure that any really bad errors get printed
             * rather than ignored.
             */
            close(input_fd);
            close(output_fd);
            throw;
        }

        /* 
         * phase information is stored as a delta from last_frame_data.
         * If last_frame_data is not NULL, we add the phase values into
         * those in frame_data.
         */
        if (last_frame_data != NULL) {
            for (size_t i = 0; i < count; i++) {
                frame_data[i] = std::polar(
                    std::abs(frame_data[i]),
                    std::arg(frame_data[i]) + std::arg(last_frame_data[i])
                );
            }
        }

        /* 
         * now if frame_count % hop_factor == 0, take the IFFT.
         * This should yield a block of (approximately) original
         * audio data.
         */
        if (frame_count % hop_factor == 0) {
            ifft->compute(ifft_result, frame_data); 

            /* take real part and scale as needed */
            for (size_t i = 0; i < count; i++) {
                samples[i] = std::real(ifft_result[i]) / scale_factor;
            }

            write_all(output_fd, samples, count * sizeof(*samples));
        }

        frame_count++;
        current_offset = blkset.end_offset( );
    }
}
void UnbiasedSquaredPhaseLagIndex::compute(ConnectivitySettings::IntermediateTrialData& inputData,
                                           QVector<QPair<int,MatrixXcd> >& vecPairCsdSum,
                                           QVector<QPair<int,MatrixXd> >& vecPairCsdImagSignSum,
                                           QMutex& mutex,
                                           int iNRows,
                                           int iNFreqs,
                                           int iNfft,
                                           const QPair<MatrixXd, VectorXd>& tapers)
{
    if(inputData.vecPairCsdImagSign.size() == iNRows) {
        //qDebug() << "UnbiasedSquaredPhaseLagIndex::compute - vecPairCsdImagSign was already computed for this trial.";
        return;
    }

    inputData.vecPairCsdImagSign.clear();

    int i,j;

    // Calculate tapered spectra if not available already
    // This code was copied and changed modified Utils/Spectra since we do not want to call the function due to time loss.
    if(inputData.vecTapSpectra.size() != iNRows) {
        inputData.vecTapSpectra.clear();

        RowVectorXd vecInputFFT, rowData;
        RowVectorXcd vecTmpFreq;

        MatrixXcd matTapSpectrum(tapers.first.rows(), iNFreqs);

        QVector<Eigen::MatrixXcd> vecTapSpectra;

        FFT<double> fft;
        fft.SetFlag(fft.HalfSpectrum);

        for (i = 0; i < iNRows; ++i) {
            // Substract mean
            rowData.array() = inputData.matData.row(i).array() - inputData.matData.row(i).mean();

            // Calculate tapered spectra if not available already
            for(j = 0; j < tapers.first.rows(); j++) {
                vecInputFFT = rowData.cwiseProduct(tapers.first.row(j));
                // FFT for freq domain returning the half spectrum and multiply taper weights
                fft.fwd(vecTmpFreq, vecInputFFT, iNfft);
                matTapSpectrum.row(j) = vecTmpFreq * tapers.second(j);
            }

            inputData.vecTapSpectra.append(matTapSpectrum);
        }
    }

    // Compute CSD
    if(inputData.vecPairCsd.isEmpty()) {
        double denomCSD = sqrt(tapers.second.cwiseAbs2().sum()) * sqrt(tapers.second.cwiseAbs2().sum()) / 2.0;

        bool bNfftEven = false;
        if (iNfft % 2 == 0){
            bNfftEven = true;
        }

        MatrixXcd matCsd = MatrixXcd(iNRows, iNFreqs);

        for (i = 0; i < iNRows; ++i) {
            for (j = i; j < iNRows; ++j) {
                // Compute CSD (average over tapers if necessary)
                matCsd.row(j) = inputData.vecTapSpectra.at(i).cwiseProduct(inputData.vecTapSpectra.at(j).conjugate()).colwise().sum() / denomCSD;

                // Divide first and last element by 2 due to half spectrum
                matCsd.row(j)(0) /= 2.0;
                if(bNfftEven) {
                    matCsd.row(j).tail(1) /= 2.0;
                }
            }

            inputData.vecPairCsd.append(QPair<int,MatrixXcd>(i,matCsd));
            inputData.vecPairCsdImagSign.append(QPair<int,MatrixXd>(i,matCsd.imag().cwiseSign()));
        }

        mutex.lock();

        if(vecPairCsdSum.isEmpty()) {
            vecPairCsdSum = inputData.vecPairCsd;
            vecPairCsdImagSignSum = inputData.vecPairCsdImagSign;
        } else {
            for (int j = 0; j < vecPairCsdSum.size(); ++j) {
                vecPairCsdSum[j].second += inputData.vecPairCsd.at(j).second;
                vecPairCsdImagSignSum[j].second += inputData.vecPairCsdImagSign.at(j).second;
            }
        }

        mutex.unlock();
    } else {
        if(inputData.vecPairCsdImagSign.isEmpty()) {
            for (i = 0; i < inputData.vecPairCsd.size(); ++i) {
                inputData.vecPairCsdImagSign.append(QPair<int,MatrixXd>(i,inputData.vecPairCsd.at(i).second.imag().cwiseSign()));
            }

            mutex.lock();

            if(vecPairCsdImagSignSum.isEmpty()) {
                vecPairCsdImagSignSum = inputData.vecPairCsdImagSign;
            } else {
                for (int j = 0; j < vecPairCsdImagSignSum.size(); ++j) {
                    vecPairCsdImagSignSum[j].second += inputData.vecPairCsdImagSign.at(j).second;
                }
            }

            mutex.unlock();
        }
    }
}
Пример #25
0
void TMSI::run()
{
    while(m_bIsRunning)
    {
        //std::cout<<"TMSI::run(s)"<<std::endl;

        //pop matrix only if the producer thread is running
        if(m_pTMSIProducer->isRunning())
        {
            MatrixXf matValue = m_pRawMatrixBuffer_In->pop();

            // Set Beep trigger (if activated)
            if(m_bBeepTrigger && m_qTimerTrigger.elapsed() >= m_iTriggerInterval)
            {
                QFuture<void> future = QtConcurrent::run(Beep, 450, 700);
                //Set trigger in received data samples - just for one sample, so that this event is easy to detect
                matValue(136, m_iSamplesPerBlock-1) = 252;
                m_qTimerTrigger.restart();

                Q_UNUSED(future);
            }

            // Set keyboard trigger (if activated and !=0)
            if(m_bUseKeyboardTrigger && m_iTriggerType!=0)
                matValue(136, m_iSamplesPerBlock-1) = m_iTriggerType;

            //Write raw data to fif file
            if(m_bWriteToFile)
                m_pOutfid->write_raw_buffer(matValue.cast<double>(), m_cals);

            // TODO: Use preprocessing if wanted by the user
            if(m_bUseFiltering)
            {
                MatrixXf temp = matValue;

                matValue = matValue - m_matOldMatrix;
                m_matOldMatrix = temp;

                //    //Check filter class - will be removed in the future - testing purpose only!
                //    FilterTools* filterObject = new FilterTools();

                //    //kaiser window testing
                //    qint32 numberCoeff = 51;
                //    QVector<float> impulseResponse(numberCoeff);
                //    filterObject->createDynamicFilter(QString('LP'), numberCoeff, (float)0.3, impulseResponse);

                //    ofstream outputFileStream("mne_x_plugins/resources/tmsi/filterToolsTest.txt", ios::out);

                //    outputFileStream << "impulseResponse:\n";
                //    for(int i=0; i<impulseResponse.size(); i++)
                //        outputFileStream << impulseResponse[i] << " ";
                //    outputFileStream << endl;

                //    //convolution testing
                //    QVector<float> in (12, 2);
                //    QVector<float> kernel (4, 2);

                //    QVector<float> out = filterObject->convolve(in, kernel);

                //    outputFileStream << "convolution result:\n";
                //    for(int i=0; i<out.size(); i++)
                //        outputFileStream << out[i] << " ";
                //    outputFileStream << endl;
            }

            // TODO: Perform a fft if wanted by the user
            if(m_bUseFFT)
            {
                QElapsedTimer timer;
                timer.start();

                FFT<float> fft;
                Matrix<complex<float>, 138, 16> freq;

                for(qint32 i = 0; i < matValue.rows(); ++i)
                    fft.fwd(freq.row(i), matValue.row(i));

//                cout<<"FFT postprocessing done in "<<timer.nsecsElapsed()<<" nanosec"<<endl;
//                cout<<"matValue before FFT:"<<endl<<matValue<<endl;
//                cout<<"freq after FFT:"<<endl<<freq<<endl;
//                matValue = freq.cwiseAbs();
//                cout<<"matValue after FFT:"<<endl<<matValue<<endl;
            }

            //Change values of the trigger channel for better plotting - this change is not saved in the produced fif file
            if(m_iNumberOfChannels>137)
            {
                for(int i = 0; i<matValue.row(137).cols(); i++)
                {
                    // Left keyboard or capacitive
                    if(matValue.row(136)[i] == 254)
                        matValue.row(136)[i] = 4000;

                    // Right keyboard
                    if(matValue.row(136)[i] == 253)
                        matValue.row(136)[i] = 8000;

                    // Beep
                    if(matValue.row(136)[i] == 252)
                        matValue.row(136)[i] = 2000;
                }
            }

            //emit values to real time multi sample array
            for(qint32 i = 0; i < matValue.cols(); ++i)
                m_pRMTSA_TMSI->data()->setValue(matValue.col(i).cast<double>());

            // Reset keyboard trigger
            m_iTriggerType = 0;
        }
    }

    //Close the fif output stream
    if(m_bWriteToFile)
        m_pOutfid->finish_writing_raw();

    //std::cout<<"EXITING - TMSI::run()"<<std::endl;
}
Пример #26
0
void Test::test_FFT_vs_previous_approaches() {
  std::cout << "Simple Test" << std::endl;

  {
    int n = 2;
    double p[] = {3,5};
    double q[] = {2,1};

    Vector<double> P(p, p+n);
    Vector<double> Q(q, q+n);

    Vector<Complex> PFFT (P.begin(), P.end());
    Vector<Complex> QFFT (Q.begin(), Q.end());

    PolyMult polyMultSB;
    Vector<double> pqActualSB = polyMultSB.schoolBook(n, P, Q);

    PolyMult polyMultDnC4;
    std::vector<double> pqActualDnC4 = polyMultDnC4.divideAndConquer4(n, P, Q);

    PolyMult polyMultDnC3;
    std::vector<double> pqActualDnC3 = polyMultDnC3.divideAndConquer3(n, P, Q);

    FFT fft;
    fft.preComputeOmega(n);
    Vector<Complex> pqActualFFTR = fft.polyMultR(PFFT, QFFT, n);
    fft.preComputeRBS(n);
    Vector<Complex> pqActualFFTD = fft.polyMultD(PFFT, QFFT, n);

    double pqExpected[] = {6,13,5};

    int w1 = 10;

    std::cout << std::setw(w1) << "Expected"
              << std::setw(w1) << "SB"
              << std::setw(w1) << "DnC 4"
              << std::setw(w1) << "DnC 3"
              << std::setw(w1) << "FFT R"
              << std::setw(w1) << "FFT D"
              << std::endl;

    std::cout << std::right;

    for(int index = 0; index < 2*n-1; ++index) {
      std::cout << std::setw(w1) << pqExpected[index]
                << std::setw(w1) << pqActualSB[index]
                << std::setw(w1) << pqActualDnC4[index]
                << std::setw(w1) << pqActualDnC3[index]
                << std::setw(w1) << pqActualFFTR[index].real()
                << std::setw(w1) << pqActualFFTD[index].real()
                << std::endl;
    }
  }

  std::cout << std::endl
            << "Random Test" << std::endl;

  {
    srand(time(0));

    int n = 8;
    int randMin = 0, randMax = 100;

    Vector<double> P(n), Q(n);

    Vector<Complex> PFFT(n), QFFT(n);

    for(int i = 0; i < n; ++i) {
      double randomP = rand()%(randMax-randMin)+randMin;
      double randomQ = rand()%(randMax-randMin)+randMin;

      P[i] = randomP;
      Q[i] = randomQ;

      PFFT[i] = Complex(randomP, 0);
      QFFT[i] = Complex(randomQ, 0);
    }

    PolyMult polyMultSB;
    Vector<double> pqActualSB = polyMultSB.schoolBook(n, P, Q);

    PolyMult polyMultDnC4;
    std::vector<double> pqActualDnC4 = polyMultDnC4.divideAndConquer4(n, P, Q);

    PolyMult polyMultDnC3;
    std::vector<double> pqActualDnC3 = polyMultDnC3.divideAndConquer3(n, P, Q);

    FFT fft;
    fft.preComputeOmega(n);
    Vector<Complex> pqActualFFTR = fft.polyMultR(PFFT, QFFT, n);
    fft.preComputeRBS(n);
    Vector<Complex> pqActualFFTD = fft.polyMultD(PFFT, QFFT, n);

    int w1 = 10;

    std::cout << std::setw(w1) << "SB"
              << std::setw(w1) << "DnC 4"
              << std::setw(w1) << "DnC 3"
              << std::setw(w1) << "FFT R"
              << std::setw(w1) << "FFT D"
              << std::endl;

    std::cout << std::right << std::fixed;

    for(int index = 0; index < 2*n-1; ++index) {
      std::cout << std::setprecision(0) << std::setw(w1) << pqActualSB[index]
                << std::setprecision(0) << std::setw(w1) << pqActualDnC4[index]
                << std::setprecision(0) << std::setw(w1) << pqActualDnC3[index]
                << std::setprecision(0) << std::setw(w1) << pqActualFFTR[index].real()
                << std::setprecision(0) << std::setw(w1) << pqActualFFTD[index].real()
                << std::endl;
    }
  }
}
Пример #27
0
int main(int argc, char **argv) {
	if(argc != 2) exit(0);

	if(!glfwInit()) {
		fprintf(stderr, "Failed to initialize GLFW\n");
		return -1;
	}

	glfwWindowHint(GLFW_SAMPLES, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	window = glfwCreateWindow(1920, 1080, "Audio Visualization", glfwGetPrimaryMonitor(), NULL);
	if(window == NULL) {
		fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);

	glewExperimental = true; //Needed for core profile
	if(glewInit() != GLEW_OK) {
		fprintf(stderr, "Failed to initialize GLEW\n");
		return -1;
	}

	glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
	glfwSetInputMode(window, GLFW_CURSOR_DISABLED, GL_TRUE);



//	glClearColor(0.f / 255.f, 63.f / 255.f, 0.f / 255.f, 1.0f);
	glClearColor(0.1, 0.1, 0.1, 1.0);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS); 

	GLuint VertexArrayID;
	glGenVertexArrays(1, &VertexArrayID);
	glBindVertexArray(VertexArrayID);

/*	ShaderInfo shaders[] = {
		{GL_VERTEX_SHADER, "VertexShader.vert"},
		{GL_FRAGMENT_SHADER, "FragmentShader.frag"},
		{GL_GEOMETRY_SHADER, "GeometryShader.geom"},
		{GL_NONE, NULL}};
	GLuint programID = LoadShaders(shaders);*/
	GLuint programID = LoadShaders("shaders/VertexShader.vert", "shaders/FragmentShader.frag", NULL);//"shaders/GeometryShader.geom");

	GLuint MatrixID = glGetUniformLocation(programID, "MVP");
	GLuint objectID = glGetUniformLocation(programID, "object");
	GLuint topID = glGetUniformLocation(programID, "top");

	glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
	glm::mat4 View       = glm::lookAt(
		glm::vec3(10,15,20),	//Camera is at (4,3,-3), in World Space
		glm::vec3(0,0,0),		//and looks at the origin
		glm::vec3(0,1,0));		//Head is up (set to 0,-1,0 to look upside-down)
	glm::mat4 Model      = glm::mat4(1.0f);
	glm::mat4 PV         = Projection * View;
	glm::mat4 MVP        = PV * Model;



	static const GLfloat g_vertex_buffer_data1[] = { 
		-1.0f,-1.0f,-1.0f, //left
		-1.0f,-1.0f, 1.0f,
		-1.0f, 1.0f, 1.0f,
		-1.0f,-1.0f,-1.0f,
		-1.0f, 1.0f,-1.0f,
		-1.0f, 1.0f, 1.0f,
		 1.0f,-1.0f,-1.0f, //right
		 1.0f,-1.0f, 1.0f,
		 1.0f, 1.0f, 1.0f,
		 1.0f,-1.0f,-1.0f,
		 1.0f, 1.0f,-1.0f,
		 1.0f, 1.0f, 1.0f,
		-1.0f,-1.0f, 1.0f, //front
		 1.0f,-1.0f, 1.0f,
		 1.0f, 1.0f, 1.0f,
		-1.0f,-1.0f, 1.0f,
		-1.0f, 1.0f, 1.0f,
		 1.0f, 1.0f, 1.0f,
		-1.0f, 1.0f,-1.0f, //top
		 1.0f, 1.0f,-1.0f,
		 1.0f, 1.0f, 1.0f,
		-1.0f, 1.0f,-1.0f,
		-1.0f, 1.0f, 1.0f,
		 1.0f, 1.0f, 1.0f,
		-1.0f,-1.0f,-1.0f, //back
		 1.0f,-1.0f,-1.0f,
		 1.0f, 1.0f,-1.0f,
		-1.0f,-1.0f,-1.0f,
		-1.0f, 1.0f,-1.0f,
		 1.0f, 1.0f,-1.0f,
		-1.0f,-1.0f,-1.0f, //bottom
		 1.0f,-1.0f,-1.0f,
		 1.0f,-1.0f, 1.0f,
		-1.0f,-1.0f,-1.0f,
		-1.0f,-1.0f, 1.0f,
		 1.0f,-1.0f, 1.0f
	};

	static const GLfloat g_vertex_buffer_data2[] = { 
		-1.0f,-1.0f,-1.0f, //left
		-1.0f,-1.0f, 1.0f,
		-1.0f, 1.0f, 1.0f,
		-1.0f,-1.0f,-1.0f,
		-1.0f, 1.0f,-1.0f,
		-1.0f, 1.0f, 1.0f,
		 1.0f,-1.0f,-1.0f, //right
		 1.0f,-1.0f, 1.0f,
		 1.0f, 1.0f, 1.0f,
		 1.0f,-1.0f,-1.0f,
		 1.0f, 1.0f,-1.0f,
		 1.0f, 1.0f, 1.0f,
		-1.0f,-1.0f, 1.0f, //front
		 1.0f,-1.0f, 1.0f,
		 1.0f, 1.0f, 1.0f,
		-1.0f,-1.0f, 1.0f,
		-1.0f, 1.0f, 1.0f,
		 1.0f, 1.0f, 1.0f,
		-1.0f, 1.0f,-1.0f, //top
		 1.0f, 1.0f,-1.0f,
		 1.0f, 1.0f, 1.0f,
		-1.0f, 1.0f,-1.0f,
		-1.0f, 1.0f, 1.0f,
		 1.0f, 1.0f, 1.0f,
		-1.0f,-1.0f,-1.0f, //back
		 1.0f,-1.0f,-1.0f,
		 1.0f, 1.0f,-1.0f,
		-1.0f,-1.0f,-1.0f,
		-1.0f, 1.0f,-1.0f,
		 1.0f, 1.0f,-1.0f,
		-1.0f,-1.0f,-1.0f, //bottom
		 1.0f,-1.0f,-1.0f,
		 1.0f,-1.0f, 1.0f,
		-1.0f,-1.0f,-1.0f,
		-1.0f,-1.0f, 1.0f,
		 1.0f,-1.0f, 1.0f
	};

	static const GLfloat g_color_buffer_data1[] = { 
		1.0f, 0.2f, 0.2f, //left
		1.0f, 0.5f, 0.5f,
		1.0f, 1.0f, 1.0f,
		1.0f, 0.2f, 0.2f,
		1.0f, 0.5f, 0.5f,
		1.0f, 1.0f, 1.0f,
		1.0f, 0.2f, 0.2f, //right
		1.0f, 0.5f, 0.5f,
		1.0f, 1.0f, 1.0f,
		1.0f, 0.2f, 0.2f,
		1.0f, 0.5f, 0.5f,
		1.0f, 1.0f, 1.0f,
		1.0f, 0.5f, 0.5f, //front
		1.0f, 0.5f, 0.5f,
		1.0f, 1.0f, 1.0f,
		1.0f, 0.5f, 0.5f,
		1.0f, 1.0f, 1.0f,
		1.0f, 1.0f, 1.0f,
		1.0f, 0.5f, 0.5f, //top
		1.0f, 0.5f, 0.5f,
		1.0f, 1.0f, 1.0f,
		1.0f, 0.5f, 0.5f,
		1.0f, 1.0f, 1.0f,
		1.0f, 1.0f, 1.0f,
		1.0f, 0.2f, 0.2f, //back
		1.0f, 0.2f, 0.2f,
		1.0f, 0.5f, 0.5f,
		1.0f, 0.2f, 0.2f,
		1.0f, 0.5f, 0.5f,
		1.0f, 0.5f, 0.5f,
		1.0f, 0.2f, 0.2f, //bottom
		1.0f, 0.2f, 0.2f,
		1.0f, 0.5f, 0.5f,
		1.0f, 0.2f, 0.2f,
		1.0f, 0.5f, 0.5f,
		1.0f, 0.5f, 0.5f
	};

	static const GLfloat g_color_buffer_data2[] = { 
		0.2f, 0.2f, 1.0f, //left
		0.5f, 0.5f, 1.0f,
		1.0f, 1.0f, 1.0f,
		0.2f, 0.2f, 1.0f,
		0.5f, 0.5f, 1.0f,
		1.0f, 1.0f, 1.0f,
		0.2f, 0.2f, 1.0f, //right
		0.5f, 0.5f, 1.0f,
		1.0f, 1.0f, 1.0f,
		0.2f, 0.2f, 1.0f,
		0.5f, 0.5f, 1.0f,
		1.0f, 1.0f, 1.0f,
		0.5f, 0.5f, 1.0f, //front
		0.5f, 0.5f, 1.0f,
		1.0f, 1.0f, 1.0f,
		0.5f, 0.5f, 1.0f,
		1.0f, 1.0f, 1.0f,
		1.0f, 1.0f, 1.0f,
		0.5f, 0.5f, 1.0f, //top
		0.5f, 0.5f, 1.0f,
		1.0f, 1.0f, 1.0f,
		0.5f, 0.5f, 1.0f,
		1.0f, 1.0f, 1.0f,
		1.0f, 1.0f, 1.0f,
		0.2f, 0.2f, 1.0f, //back
		0.2f, 0.2f, 1.0f,
		0.5f, 0.5f, 1.0f,
		0.2f, 0.2f, 1.0f,
		0.5f, 0.5f, 1.0f,
		0.5f, 0.5f, 1.0f,
		0.2f, 0.2f, 1.0f, //bottom
		0.2f, 0.2f, 1.0f,
		0.5f, 0.5f, 1.0f,
		0.2f, 0.2f, 1.0f,
		0.5f, 0.5f, 1.0f,
		0.5f, 0.5f, 1.0f
	};



	GLuint vertexbuffer1; //left column
	glGenBuffers(1, &vertexbuffer1);
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer1);
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data1), g_vertex_buffer_data1, GL_STATIC_DRAW);

	GLuint vertexbuffer2; //right column
	glGenBuffers(1, &vertexbuffer2);
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data2), g_vertex_buffer_data2, GL_STATIC_DRAW);

	GLuint vertexbuffer3; //waveform
	glGenBuffers(1, &vertexbuffer3);

	GLuint vertexbuffer4; //z
	glGenBuffers(1, &vertexbuffer4);

	GLuint vertexbuffer5; //spectrum
	glGenBuffers(1, &vertexbuffer5);

	GLuint colorbuffer1;
	glGenBuffers(1, &colorbuffer1);
	glBindBuffer(GL_ARRAY_BUFFER, colorbuffer1);
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data1), g_color_buffer_data1, GL_STATIC_DRAW);

	GLuint colorbuffer2;
	glGenBuffers(1, &colorbuffer2);
	glBindBuffer(GL_ARRAY_BUFFER, colorbuffer2);
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data2), g_color_buffer_data2, GL_STATIC_DRAW);



	audio_data data = get_audio_data(argv[1]);
	int bpf = data.sampling_rate / fps;
	int data_index = 0;
	double current_time;
	double last_time;
	double total_time = data.size / data.sampling_rate / 4;
	float z[bpf * 2];
	for(int i = 0; i < bpf; i++) z[i * 2] = z[i * 2 + 1] = waveform_length / bpf * i - waveform_length / 2;
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer4);
	glBufferData(GL_ARRAY_BUFFER, bpf * 8, z, GL_STATIC_DRAW);

	int res;
	pthread_t a_thread;
	void *thread_result;
	res = pthread_create(&a_thread, NULL, play_wav_d, argv[1]);
	if(res != 0) {
		perror("Thread creation failed!");
		exit(EXIT_FAILURE);
	}

	FFT fft;
	fft.setDataSize(bpf);
	fft.setSampleRate(data.sampling_rate);

	float max_l = 0, max_r = 0;
	glfwSetTime(0);
	do {
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glUseProgram(programID);

		glEnableVertexAttribArray(0);
		glEnableVertexAttribArray(1);
		glEnableVertexAttribArray(2);

		computeMatricesFromInputs();
		glm::mat4 Projection  = getProjectionMatrix();
		glm::mat4 View        = getViewMatrix();
		glm::mat4 ModelMatrix = glm::mat4(1.0);
		PV                    = Projection * View;
		MVP                   = PV * ModelMatrix;
		glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);



		float *FFTdata = fft.calculateFFT((short *)data.data + data_index);
		int spectrum_interval = fps / 2;
		for(int i = 0; i < bpf; i++) {
			for(int j = 1; j < spectrum_interval; j++)
				FFTdata[i * spectrum_interval] += FFTdata[i * spectrum_interval + j];
			FFTdata[i * spectrum_interval] /= spectrum_interval * 10;
			FFTdata[i * spectrum_interval + spectrum_interval / 2] = 0;
		}



		glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer4); //z
		glVertexAttribPointer(
			2,						//attribute. No particular reason for 0, but must match the layout in the shader.
			1,						//size
			GL_FLOAT,				//type
			GL_FALSE,				//normalized?
			0,						//stride
			(void *)0				//array buffer offset
		);

		glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer5); //spectrum
		glBufferData(GL_ARRAY_BUFFER, spectrum_interval * bpf * 4, FFTdata, GL_STATIC_DRAW);
		glVertexAttribPointer(
			0,						//attribute. No particular reason for 0, but must match the layout in the shader.
			1,						//size
			GL_FLOAT,				//type
			GL_FALSE,				//normalized?
			spectrum_interval * 2,	//stride
			(void *)0				//array buffer offset
		);
		glUniform1i(objectID, 6);
		glDrawArrays(GL_LINES, 0, bpf * 2); //draw spectrum



		glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer4); //z
		glVertexAttribPointer(
			2,						//attribute. No particular reason for 0, but must match the layout in the shader.
			1,						//size
			GL_FLOAT,				//type
			GL_FALSE,				//normalized?
			(waveform_interval + 1) * 4,
									//stride
			(void *)0				//array buffer offset
		);

		glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer3); //waveform
		glBufferData(GL_ARRAY_BUFFER, bpf * 4, (short *)data.data + data_index, GL_DYNAMIC_DRAW);

		glVertexAttribPointer(
			0,						//attribute. No particular reason for 0, but must match the layout in the shader.
			1,						//size
			GL_SHORT,				//type
			GL_FALSE,				//normalized?
			waveform_interval * 4,	//stride
			(void *)0				//array buffer offset
		);
		glUniform1i(objectID, 2);
		glDrawArrays(GL_LINE_STRIP, 0, bpf / waveform_interval); //draw left waveform

		glVertexAttribPointer(
			0,						//attribute. No particular reason for 0, but must match the layout in the shader.
			1,						//size
			GL_SHORT,				//type
			GL_FALSE,				//normalized?
			waveform_interval * 4,	//stride
			(void *)2				//array buffer offset
		);
		glUniform1i(objectID, 3);
		glDrawArrays(GL_LINE_STRIP, 0, bpf / waveform_interval); //draw right waveform



		float sum_l = 0, sum_r = 0;
		for(int i = 0; i < bpf; i++) {
			sum_l = max(sum_l, abs(((short*)data.data)[data_index++])); //max
			sum_r = max(sum_r, abs(((short*)data.data)[data_index++]));
//			sum_l += abs(((short*)data.data)[data_index++]); //avg
//			sum_r += abs(((short*)data.data)[data_index++]);
		}
//		sum_l /= bpf; //avg
//		sum_r /= bpf;



		float scale_l = sum_l / 32768 * column_height;
		Model = glm::mat4(
			 1.0, 0.0, 0.0, 0.0,
			 0.0, 1.0, 0.0, 0.0,
			 0.0, 0.0, 1.0, 0.0,
			-2.0, 1.0, 0.0, 1.0);
		glm::mat4 scale1 = glm::mat4(
			1.0, 0.0, 0.0, 0.0,
			0.0, scale_l, 0.0, 0.0,
			0.0, 0.0, 1.0, 0.0,
			0.0, 0.0, 0.0, 1.0);
		MVP = PV * scale1 * Model;
		glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);

		glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer1); //left column vertex
		glVertexAttribPointer(
			0,			// attribute. No particular reason for 0, but must match the layout in the shader.
			3,			// size
			GL_FLOAT,	// type
			GL_FALSE,	// normalized?
			0,			// stride
			(void *)0	// array buffer offset
		);
		glBindBuffer(GL_ARRAY_BUFFER, colorbuffer1);  //left column color
		glVertexAttribPointer(
			1,			// attribute. No particular reason for 1, but must match the layout in the shader.
			3,			// size
			GL_FLOAT,	// type
			GL_FALSE,	// normalized?
			0,			// stride
			(void *)0	// array buffer offset
		);
		glUniform1i(objectID, 0);
		glDrawArrays(GL_TRIANGLES, 0, 12*3); //draw left column
		
		if(scale_l> max_l) max_l = scale_l;
		else max_l -= top_speed;
		glm::mat4 translate1 = glm::mat4(
			 1.0, 0.0, 0.0, 0.0,
			 0.0, 1.0, 0.0, 0.0,
			 0.0, 0.0, 1.0, 0.0,
			-2.0, max_l * 2, 0.0, 1.0);
		scale1 = glm::mat4(
			max_l / 2, 0.0, 0.0, 0.0,
			0.0, max_l / 2 * top_height, 0.0, 0.0,
			0.0, 0.0, max_l / 2, 0.0,
			0.0, 0.0, 0.0, 1.0);
		MVP = PV * translate1 * scale1;
		glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
		glUniform1i(objectID, 4);
		glUniform1f(topID, max_l);
		glDrawArrays(GL_TRIANGLES, 0, 12*3); //draw left upper top

		translate1 = glm::mat4(
			 1.0, 0.0, 0.0, 0.0,
			 0.0, 1.0, 0.0, 0.0,
			 0.0, 0.0, 1.0, 0.0,
			-2.0, scale_l * 2, 0.0, 1.0);
		scale1 = glm::mat4(
			scale_l / 2, 0.0, 0.0, 0.0,
			0.0, scale_l / 2 * top_height, 0.0, 0.0,
			0.0, 0.0, scale_l / 2, 0.0,
			0.0, 0.0, 0.0, 1.0);
		MVP = PV * translate1 * scale1;
		glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
		glUniform1i(objectID, 4);
		glUniform1f(topID, scale_l);
		glDrawArrays(GL_TRIANGLES, 0, 12*3); //draw left lower top



		float scale_r = sum_r / 32768 * column_height;
		Model = glm::mat4(
			 1.0, 0.0, 0.0, 0.0,
			 0.0, 1.0, 0.0, 0.0,
			 0.0, 0.0, 1.0, 0.0,
			 2.0, 1.0, 0.0, 1.0);
		glm::mat4 scale2 = glm::mat4(
			1.0, 0.0, 0.0, 0.0,
			0.0, scale_r, 0.0, 0.0,
			0.0, 0.0, 1.0, 0.0,
			0.0, 0.0, 0.0, 1.0);
		MVP = PV * scale2 * Model;
		glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);

		glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2); //right column vertex
		glVertexAttribPointer(
			0,			// attribute. No particular reason for 0, but must match the layout in the shader.
			3,			// size
			GL_FLOAT,	// type
			GL_FALSE,	// normalized?
			0,			// stride
			(void*)0	// array buffer offset
		);
		glBindBuffer(GL_ARRAY_BUFFER, colorbuffer2); //right column vertex
		glVertexAttribPointer(
			1,			// attribute. No particular reason for 1, but must match the layout in the shader.
			3,			// size
			GL_FLOAT,	// type
			GL_FALSE,	// normalized?
			0,			// stride
			(void*)0	// array buffer offset
		);
		glUniform1i(objectID, 1);
		glDrawArrays(GL_TRIANGLES, 0, 12*3); //draw right column

		if(scale_r > max_r) max_r = scale_r;
		else max_r -= top_speed;
		glm::mat4 translate2 = glm::mat4(
			 1.0, 0.0, 0.0, 0.0,
			 0.0, 1.0, 0.0, 0.0,
			 0.0, 0.0, 1.0, 0.0,
			 2.0, max_r * 2, 0.0, 1.0);
		scale2 = glm::mat4(
			max_r / 2, 0.0, 0.0, 0.0,
			0.0, max_r / 2 * top_height, 0.0, 0.0,
			0.0, 0.0, max_r / 2, 0.0,
			0.0, 0.0, 0.0, 1.0);//0.25 / max_r);//(4.0 - max_r) * (4.0 - max_r));
		MVP = PV * translate2 * scale2;
		glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
		glUniform1i(objectID, 5);
		glUniform1f(topID, max_r);
		glDrawArrays(GL_TRIANGLES, 0, 12*3); //draw right upper top

		translate2 = glm::mat4(
			 1.0, 0.0, 0.0, 0.0,
			 0.0, 1.0, 0.0, 0.0,
			 0.0, 0.0, 1.0, 0.0,
			 2.0, scale_r * 2, 0.0, 1.0);
		scale2 = glm::mat4(
			scale_r / 2, 0.0, 0.0, 0.0,
			0.0, scale_r / 2 * top_height, 0.0, 0.0,
			0.0, 0.0, scale_r / 2, 0.0,
			0.0, 0.0, 0.0, 1.0);//0.25 / max_r);//(4.0 - max_r) * (4.0 - max_r));
		MVP = PV * translate2 * scale2;
		glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
		glUniform1i(objectID, 5);
		glUniform1f(topID, scale_r);
		glDrawArrays(GL_TRIANGLES, 0, 12*3); //draw right lower top



		glDisableVertexAttribArray(0);
		glDisableVertexAttribArray(1);
		glDisableVertexAttribArray(2);

		if(data_index >= data.size / 2) break;
		current_time = glfwGetTime();
		double left_time = total_time - current_time;
		if(left_time <= 0) break;
		double accurate_time = data_index / 2.0 / bpf / fps;
		double delta = accurate_time - current_time;
		printf("%lf %lf %lf %lf %lf\n", current_time - last_time, accurate_time, current_time, delta, left_time);
		delta = delta > 0 ? delta : 0;
		last_time = current_time;
		usleep(delta * 1000000);
		glfwSwapBuffers(window);
		glfwPollEvents();
	} while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && !glfwWindowShouldClose(window));

	pthread_cancel(a_thread);
	res = pthread_join(a_thread, &thread_result);
	if(res != 0) {
		perror("Thread join failed!");
		exit(EXIT_FAILURE);
	}

	glDeleteBuffers(1, &vertexbuffer1);
	glDeleteBuffers(1, &vertexbuffer2);
	glDeleteBuffers(1, &vertexbuffer3);
	glDeleteBuffers(1, &vertexbuffer4);
	glDeleteBuffers(1, &vertexbuffer5);
	glDeleteBuffers(1, &colorbuffer1);
	glDeleteBuffers(1, &colorbuffer2);
	glDeleteProgram(programID);
	glDeleteVertexArrays(1, &VertexArrayID);

	glfwTerminate();

	return 0;
}
boolean CAlgorithmHilbertTransform::process(void)
{

	uint32 l_ui32ChannelCount = ip_pMatrix->getDimensionSize(0);
	uint32 l_ui32SamplesPerChannel = ip_pMatrix->getDimensionSize(1);


	IMatrix* l_pInputMatrix = ip_pMatrix;
	IMatrix* l_pOutputHilbertMatrix = op_pHilbertMatrix;
	IMatrix* l_pOutputEnvelopeMatrix = op_pEnvelopeMatrix;
	IMatrix* l_pOutputPhaseMatrix = op_pPhaseMatrix;

	FFT< double, internal::kissfft_impl<double > > fft; //create instance of fft transform

	if(this->isInputTriggerActive(OVP_Algorithm_HilbertTransform_InputTriggerId_Initialize)) //Check if the input is correct
	{
		if( l_pInputMatrix->getDimensionCount() != 2)
		{
			this->getLogManager() << LogLevel_Error << "The input matrix must have 2 dimensions, here the dimension is ";
			std::cout<<l_pInputMatrix->getDimensionCount()<<std::endl;
			return false;
		}

		//Setting size of outputs

		l_pOutputHilbertMatrix->setDimensionCount(2);
		l_pOutputHilbertMatrix->setDimensionSize(0,l_ui32ChannelCount);
		l_pOutputHilbertMatrix->setDimensionSize(1,l_ui32SamplesPerChannel);

		l_pOutputEnvelopeMatrix->setDimensionCount(2);
		l_pOutputEnvelopeMatrix->setDimensionSize(0,l_ui32ChannelCount);
		l_pOutputEnvelopeMatrix->setDimensionSize(1,l_ui32SamplesPerChannel);

		l_pOutputPhaseMatrix->setDimensionCount(2);
		l_pOutputPhaseMatrix->setDimensionSize(0,l_ui32ChannelCount);
		l_pOutputPhaseMatrix->setDimensionSize(1,l_ui32SamplesPerChannel);

	}

	if(this->isInputTriggerActive(OVP_Algorithm_HilbertTransform_InputTriggerId_Process))
	{

		//Computing Hilbert transform for all channels
		for(uint32 channel=0; channel<l_ui32ChannelCount; channel++)
		{
			//Initialization of buffer vectors
			m_vecXcdSignalBuffer = VectorXcd::Zero(l_ui32SamplesPerChannel);
			m_vecXcdSignalFourier = VectorXcd::Zero(l_ui32SamplesPerChannel);

			//Initialization of vector h used to compute analytic signal
			m_vecXdHilbert.resize(l_ui32SamplesPerChannel);
			m_vecXdHilbert(0) = 1.0;

			if(l_ui32SamplesPerChannel%2 == 0)
			{
				m_vecXdHilbert(l_ui32SamplesPerChannel/2) = 1.0;
				for(uint32 i=1; i<l_ui32SamplesPerChannel/2; i++)
				{
					m_vecXdHilbert(i) = 2.0;
				}
				for(uint32 i=(l_ui32SamplesPerChannel/2)+1; i<l_ui32SamplesPerChannel; i++)
				{
					m_vecXdHilbert(i) = 0.0;
				}
			}
			else
			{
				m_vecXdHilbert((l_ui32SamplesPerChannel+1)/2) = 1.0;
				for(uint32 i=1; i<(l_ui32SamplesPerChannel+1); i++)
				{
					m_vecXdHilbert(i) = 2.0;
				}
				for(uint32 i=(l_ui32SamplesPerChannel+1)/2+1; i<l_ui32SamplesPerChannel; i++)
				{
					m_vecXdHilbert(i) = 0.0;
				}
			}

			//Copy input signal chunk on buffer
			for(uint32 samples=0; samples<l_ui32SamplesPerChannel;samples++)
			{
				m_vecXcdSignalBuffer(samples).real(l_pInputMatrix->getBuffer()[samples + channel * (l_ui32SamplesPerChannel)]);
				m_vecXcdSignalBuffer(samples).imag(0.0);
			}

			//Fast Fourier Transform of input signal
			fft.fwd(m_vecXcdSignalFourier, m_vecXcdSignalBuffer);

			//Apply Hilbert transform by element-wise multiplying fft vector by h
			for(uint32 samples=0; samples<l_ui32SamplesPerChannel;samples++)
			{
				m_vecXcdSignalFourier(samples) = m_vecXcdSignalFourier(samples)*m_vecXdHilbert(samples);
			}

			//Inverse Fast Fourier transform
			fft.inv(m_vecXcdSignalBuffer, m_vecXcdSignalFourier); // m_vecXcdSignalBuffer is now the analytical signal of the initial input signal

			//Compute envelope and phase and pass it to the corresponding output
			for(uint32 samples=0; samples<l_ui32SamplesPerChannel;samples++)
			{
				l_pOutputHilbertMatrix->getBuffer()[samples + channel*l_ui32SamplesPerChannel] = m_vecXcdSignalBuffer(samples).imag();
				l_pOutputEnvelopeMatrix->getBuffer()[samples + channel*l_ui32SamplesPerChannel] = abs(m_vecXcdSignalBuffer(samples));
				l_pOutputPhaseMatrix->getBuffer()[samples + channel*l_ui32SamplesPerChannel] = arg(m_vecXcdSignalBuffer(samples));
			}

		}

	}
	return true;
}