头文件:
/* * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), [email protected] * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 2 or any later version. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. A copy of the GNU General Public License is available at: * http://www.fsf.org/licensing/licenses */ /***************************************************************************** * dgt.h * * Discrete Gabor Transform. * * These routines are designed for calculating discrete Gabor transform and * its inversion of 1D signals. In order to eliminate the border effect, the * input signal("signal") is extended by three forms: zeros padded("zpd"), * periodized extension("ppd") and symetric extension("sym"). * * The analysis/synthesis function is given by users, and it's daul * (synthesis/analysis) function can be computed by "daul" routine. The over * sampling rate is equal to N/dM, where N denotes frequency sampling numbers * and dM denotes the time sampling interval. * * N and dM should can be devided evenly by the window length "Lw". The * recovered signal just has the elements from 1 to dM*floor(Ls/dM) of the * original signal. So you'd better let dM can be deviede evenly by the * original signal length "Ls". * * Zhang Ming, 2010-03, Xi'an Jiaotong University. *****************************************************************************/ #ifndef DGT_H #define DGT_H #include <string> #include <fft.h> #include <matrix.h> #include <linequs1.h> //#include <linequs3.h> #include <utilities.h> namespace splab { template<typename Type> Vector<Type> daul( const Vector<Type>&, int, int ); template<typename Type> Matrix< complex<Type> > dgt( const Vector<Type>&, const Vector<Type>&, int, int, const string &mode = "zpd" ); template<typename Type> Vector<Type> idgt( const Matrix< complex<Type> >&, const Vector<Type>&, int, int ); #include <dgt-impl.h> } // namespace splab #endif // DGT_H
实现文件:
/* * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), [email protected] * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 2 or any later version. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. A copy of the GNU General Public License is available at: * http://www.fsf.org/licensing/licenses */ /***************************************************************************** * dgt-impl.h * * Implementation for Discrete Gabor Transform. * * Zhang Ming, 2010-03, Xi'an Jiaotong University. *****************************************************************************/ /** * Return the daul function of input window "g". */ template <typename Type> Vector<Type> daul( const Vector<Type> &gn, int N, int dM ) { int L = gn.size(), NL = 2*L-N; Vector<Type> hn(L); Vector<Type> gg = wextend( gn, NL, "right", "zpd" ); // coefficient matrix and constant vector Matrix<Type> H(NL/N,L/dM); Vector<Type> u(NL/N); u[0] = Type(1.0/N); // evaluate matrix H for( int k=0; k<dM; ++k ) { for( int q=0; q<NL/N; ++q ) for( int p=0; p<L/dM; ++p ) { int index = mod( k+p*dM+q*N, NL ); H[q][p] = gg[index]; } // calculate the kth part value of h Vector<Type> tmp = trMult( H, luSolver( multTr(H,H), u ) ); // Vector<Type> tmp = tsvd( H, u ); for( int i=0; i<tmp.dim(); ++i ) hn[k+i*dM] = tmp[i]; } return hn; } /** * Compute the discrete Gabor transform of "signal". The coeffitions are * stored in "coefs", a Ls+Lw by Lw (Ls: lengthof "signsl", Lw: * length of "window") matrix. The row represents frequency ordinate * and column represents the time ordinate. */ template <typename Type> Matrix< complex<Type> > dgt( const Vector<Type> &signal, const Vector<Type> &anaWin, int N, int dM, const string &mode ) { int Ls = signal.dim(); int Lw = anaWin.dim(); int M = (Ls+Lw)/dM; Vector<Type> sn = wextend( signal, Lw, "both", mode ); Matrix< complex<Type> > coefs(N,M); Vector<Type> segment(Lw); Vector< complex<Type> > segDFT(Lw); Vector< complex<Type> > tmp(N); complex<Type> W = polar( Type(1), Type(-2*PI/N) ); for( int m=0; m<M; ++m ) { // intercept signal by window function for( int i=0; i<Lw; ++i ) segment[i] = sn[i+m*dM]*anaWin[i]; // Fourier transform segDFT = fft( segment ); // calculate the mth culumn coefficients for( int n=0; n<N; ++n ) tmp[n] = pow(W,n*m*dM) * segDFT[n*Lw/N]; coefs.setColumn( tmp, m ); } return coefs; } /** * Compute the inverse discrete Gabor transform from "coefs". */ template <typename Type> Vector<Type> idgt( const Matrix< complex<Type> > &coefs, const Vector<Type> &synWin, int N, int dM ) { int M = coefs.cols(); int Lw = synWin.size(); int Ls = dM*M-Lw; // reallocate for signal and initialize it by "0" Vector<Type> signal(Ls); Matrix<Type> idftCoefs(N,M); Vector<Type> sn(N); Vector< complex<Type> > Sk(N); for( int i=0; i<M; ++i ) { Sk = coefs.getColumn(i); sn = ifftc2r(Sk); sn *= Type(N); idftCoefs.setColumn( sn, i ); } // compulate the ith element of signal for( int i=0; i<Ls; ++i ) { int p = ceil(i+1, dM); for( int m=p; m<p+Lw/dM; ++m ) { int n = mod(i,N); signal[i] += idftCoefs[n][m]*synWin[Lw-m*dM+i]; } } return signal; }
测试代码:
/***************************************************************************** * dgt_test.cpp * * Discrete Gabor transform testing. * * Zhang Ming, 2010-03, Xi'an Jiaotong University. *****************************************************************************/ #define BOUNDS_CHECK #include <iostream> #include <vectormath.h> #include <timing.h> #include <dgt.h> using namespace std; using namespace splab; typedef double Type; const int Fs = 1000; const int Ls = 10000; const int Lg = 80; const int N = 40; const int dM = 10; // over sampling ratio is N/dM int main() { /******************************* [ signal ] ******************************/ Type a = 0; Type b = Ls-1; Vector<Type> t = linspace( a, b, Ls ) / Type(Fs); Vector<Type> st = cos( Type(400*PI) * pow(t,Type(2.0)) ); /******************************* [ widow ] ******************************/ a = 0; b = Type( Lg-1 ); Type r = sqrt( dM*N / Type(2*PI) ); Type u = (Lg-1) / Type(2.0); t = linspace( a, b, Lg ); Vector<Type> h = gauss( t, u, r ); h = h / norm(h); /***************************** [ daul function ] *************************/ Type runtime = 0.0; Timing cnt; cout << "Compute daul function." << endl; cnt.start(); Vector<Type> g = daul( h, N, dM ); cnt.stop(); runtime = cnt.read(); cout << "The running time = " << runtime << " (ms)" << endl << endl; /******************************** [ DGT ] ********************************/ cout << "Taking discrete Gabor transform." << endl; cnt.start(); Matrix< complex<Type> > C = dgt( st, g, N, dM, "sym" ); cnt.stop(); runtime = cnt.read(); cout << "The running time = " << runtime << " (ms)" << endl << endl; /******************************** [ IDGT ] *******************************/ cout << "Taking inverse discrete Gabor transform." << endl; cnt.start(); Vector<Type> xt = idgt( C, h, N, dM ); cnt.stop(); runtime = cnt.read(); cout << "The running time = " << runtime << " (ms)" << endl << endl; cout <<"The relative error : norm(s-x) / norm(s) = " << norm(st-xt)/norm(st) << endl << endl; return 0; }
运行结果:
Compute daul function. The running time = 8.67362e-019 (ms) Taking discrete Gabor transform. The running time = 0.063 (ms) Taking inverse discrete Gabor transform. The running time = 0.016 (ms) The relative error : norm(s-x) / norm(s) = 5.79937e-012 Process returned 0 (0x0) execution time : 0.172 s Press any key to continue.