⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atom_interpolate.c

📁 LastWave
💻 C
📖 第 1 页 / 共 2 页
字号:
/*..........................................................................*//*                                                                          *//*      L a s t W a v e    P a c k a g e 'stft' 2.1                         *//*                                                                          *//*      Copyright (C) 2000 Remi Gribonval, Emmanuel Bacry and Javier Abadia *//*      email  : remi.gribonval@inria.fr                                    *//*               lastwave@cmapx.polytechnique.fr                            *//*                                                                          *//*..........................................................................*//*                                                                          *//*      This program is a 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 of the  *//*      License, or (at your option) any later version                      *//*                                                                          *//*      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.                        *//*                                                                          *//*      You should have received a copy of the GNU General Public License   *//*      along with this program (in a file named COPYRIGHT);                *//*      if not, write to the Free Software Foundation, Inc.,                *//*      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA             *//*                                                                          *//*..........................................................................*/#include "lastwave.h"#include "mp_book.h"//#define DEBUG_SCALE 1/*******************************************************//* *	FUNCTIONS WHICH PERFORM AN INTERPOLATION *	IN ORDER TO ADJUST THE FIELDS OF A GIVEN ATOM *//*******************************************************//*  * For timeId/freqId interpolation * (resolution = 0  => integers)  * (resolution > 0  => precision = pow(2,-resolution) * (resolution < 0  => infinite precision) */static LWFLOAT AtomTimeResolution  =  0.0;static LWFLOAT AtomFreqResolution  = -1.0;/* * For chirp interpolation  * (resolution < 0  => infinite precision) * (resolution >= 0  => precision = pow(2,-resolution)/scale^2 where 's' = scale = TODO : precise! */static LWFLOAT AtomChirpResolution = -1.0;static LWFLOAT QuantizeParameter(LWFLOAT parameter,LWFLOAT resolution){  LWFLOAT precision;  if (resolution >= 0) {    precision = pow(2.0,-(LWFLOAT) resolution);    if (parameter >= 0) return(((int) (parameter/precision+0.5))*precision);    else          return(((int) (parameter/precision-0.5))*precision);  }  return(parameter);}/* * The various types of parameters that can be estimated */enum {  TimeParameter,  FreqParameter,  ChirpParameter,  ScaleParameter};/* * Fits a parabola y(x) = (a/2)*k^2+b*k+c with x = k*rate * If the parabola is indeed a line, an error is generated. * * Input  : 3 points (-rate,yM) (0,yC) (rate,yP) and 'rate' * Output : parameters a,b,c and local extremum x. */static void ParabolaInterpolate(LWFLOAT yM,LWFLOAT yC,LWFLOAT yP,LWFLOAT rate,LWFLOAT *pA, LWFLOAT *pB, LWFLOAT *pC,LWFLOAT *pX){  LWFLOAT a,b,c;  /* The parameters of the parabola */  *pA = a = (yP-2*yC+yM);  *pB = b = (yP-yM)/2;  *pC = c = yC;  /* The parabola should not be a line ! */  if(a == 0.0) Errorf("ParabolaInterpolate : second derivative is zero");  /* The location of the extremum */  *pX = -rate*b/a;}/*  * Same as above, but generates an error if the parabola (or flat line) * has no maximum strictly within the interval [-rate,rate] */static void ParabolaInterpolateMax(LWFLOAT yM,LWFLOAT yC,LWFLOAT yP,LWFLOAT rate,LWFLOAT *pX){  LWFLOAT a,b,c;  /* Checking that the maximum will be within the range [-rate,rate] */  if (yC < yM || yP > yC) Errorf("ParabolaInterpolateMax : no strict maximum with data %g %g %g\n",yM,yC,yP);  /* Case of a flat line */  if (yC == yM && yC == yP) {    *pX = 0.0;    return;  }  ParabolaInterpolate(yM,yC,yP,rate,&a,&b,&c,pX);}/* * Simple conversion of a complex number from cartesian coordinates z= real+i*imag * to 'logpolar' coordinates   z=exp(logAmp+i*arg)  with -M_PI/2 <= ang <= 3*M+PI/2 */static void Cartesian2LogPolar(LWFLOAT re,LWFLOAT im,LWFLOAT *logAmp,LWFLOAT *arg){  /* Cannot deal with z==0 */  if(re==0.0&&im==0.0)   Errorf("Cartesian2LogPolar : (Weird) (re,im) = (0,0) !");  *logAmp = 0.5*log(re*re+im*im);  /* Case of pure imaginary number */  if(re == 0.0) {    if(im > 0) *arg = M_PI/2;    else       *arg = -M_PI/2;  }  /* Other cases */  else {    *arg = atan2(im,re);    if(re < 0.0) {      *arg += M_PI;    }  }}  /* * Simple function that gets the (complex or real) values of the inner product  * of three 'neighboring' time-frequency atoms. * Arguments :  *  atom     : the atom which neighbors we look at *  dict     : the dictionary used to get/compute the values *  channel  : the channel of the dictionary we should use *  type     : either ComplexStft or RealStft *  neighbor : either TIME_NEIGHBOR or FREQ_NEIGHBOR * Output    : *  the real (and imaginary) parts of the three inner products *  the distance 'rate' between neighbors (in timeId or freqId units) * Return    : *  'YES' in most cases *  'NO'  iff one of the neighbors  *  -is strictly beyond the Nyquist frequency OR *  -is strictly below the Zero frequency     OR *  -has support not completely inside [0,signalSize-1] */ #define TIME_NEIGHBOR 0#define FREQ_NEIGHBOR 1static char GetNeighborsData(ATOM atom,DICT dict,unsigned char channel,char type,char neighbor,unsigned long *pRate,			     LWFLOAT *coeffRM,LWFLOAT *coeffRC,LWFLOAT *coeffRP,			     LWFLOAT *coeffIM,LWFLOAT *coeffIC,LWFLOAT *coeffIP){  char flagRecompute = NO;  SUBDICT subDict = NULL;  STFT    stft    = NULL;  SIGNAL  signal  = NULL;    /* Atom fields */  long timeId;  long freqId;  /* Support of the atom */  int timeIdMin,timeIdMax;  /* Utilities */  long tM,tC,tP,fM,fC,fP;  LWFLOAT *pArrayRM,*pArrayRC,*pArrayRP;  LWFLOAT *pArrayIM,*pArrayIC,*pArrayIP;  static ATOM atomM = NULL,atomC = NULL,atomP = NULL;    timeId = (int) atom->timeId;  freqId = (int) atom->freqId;  if((subDict = GetStftSubDict(dict,channel,type,atom->windowShape,atom->windowSize,NULL))==NULL)    Errorf("GetNeighborsData : stft is not available at windowSize=%d windowShape='%s'",atom->windowSize,WindowShape2Name(atom->windowShape));  stft = (STFT)(subDict->dataContainer);  /* Checking the range */  CheckAtom(atom);  if(timeId > stft->tRate*(stft->nFrames-1))    Errorf("GetNeighborsData (Weired) : bad timeId %g > %d",timeId,stft->tRate*(stft->nFrames-1));  if(freqId>GABOR_NYQUIST_FREQID)    Errorf("GetNeighborsData (Weired) : bad freqId %g > %d",freqId,GABOR_NYQUIST_FREQID);  /* Cases where we have to compute the inner products */  if(atom->chirpId != 0.0)    flagRecompute = YES;   /* the atom is chirped */  if(subDict->flagUpToDate == NO) {    flagRecompute = YES;   /* the content of the stft is out of date */  } else {    if(((LWFLOAT)freqId)!=atom->freqId || freqId%stft->fRate != 0)      flagRecompute = YES; /* the frequency is not on the grid of the stft */    if(((LWFLOAT)timeId)!=atom->timeId || timeId%stft->tRate != 0)      flagRecompute = YES; /* the time is not on the grid of the stft */  }  /* Setting the neighbors we want */  if(flagRecompute == NO) {    /* Case when we get the coeffs from the stft */    switch(neighbor) {    case FREQ_NEIGHBOR :      tM  = tC = tP = timeId;      fM  = freqId-stft->fRate;      fC  = freqId;      fP  = freqId+stft->fRate;      *pRate = stft->fRate;      /* Cases where the neighbors are 'out' */      if(fM<0 || fP>GABOR_NYQUIST_FREQID) return(NO);          break;    case TIME_NEIGHBOR :      tM  = timeId-stft->tRate;      tC  = timeId;      tP  = timeId+stft->tRate;      fM  = fC = fP = freqId;      *pRate = stft->tRate;      /* Cases where the neighbors are 'out' */      ComputeWindowSupport(atom->windowSize,atom->windowShape,atom->timeId,&timeIdMin,&timeIdMax);      if(timeIdMin-stft->tRate<0 || timeIdMax+stft->tRate>=atom->signalSize) return(NO);          break;    default :      Errorf("GetNeighborsData : Weired error (neighbor type=%d)",neighbor);      break;    }  } else {    /* Case when we compute the coeffs */    atomM = CopyAtom(atom,atomM);    atomC = CopyAtom(atom,atomC);    atomP = CopyAtom(atom,atomP);    /*      * This ensures compliance of atomM and atomP with CheckAtom in SCAtomInnerProduct     * if atomM->freqId==0 or atomP->freqId==GABOR_NYQUIST_FREQID     */    atomM->coeffI = atomP->coeffI = 0.0;     switch(neighbor) {    case FREQ_NEIGHBOR :      atomM->freqId -= stft->fRate;      atomP->freqId += stft->fRate;      *pRate = stft->fRate;      /* Cases where the neighbors are 'out' */      if(atomM->freqId<0 || atomP->freqId>GABOR_NYQUIST_FREQID)  return(NO);          break;    case TIME_NEIGHBOR :      atomM->timeId -= stft->tRate;      atomP->timeId += stft->tRate;      *pRate = stft->tRate;      /* Cases where the neighbors are 'out' */      ComputeWindowSupport(atom->windowSize,atom->windowShape,atom->timeId,&timeIdMin,&timeIdMax);      if(timeIdMin-stft->tRate<0 || timeIdMax+stft->tRate>=atom->signalSize) return(NO);          break;    default :       Errorf("GetNeighborsData : Weired error (neighbor type=%d)",neighbor);      break;    }  }      /* Actually get/compute the coeffs */  if(flagRecompute == NO) {    switch(type) {    case ComplexStft :      GetStftData(stft,tM,&pArrayRM,&pArrayIM);      GetStftData(stft,tC,&pArrayRC,&pArrayIC);      GetStftData(stft,tP,&pArrayRP,&pArrayIP);      *coeffRM = pArrayRM[fM/stft->fRate];          *coeffRC = pArrayRC[fC/stft->fRate];      *coeffRP = pArrayRP[fP/stft->fRate];          *coeffIM = pArrayIM[fM/stft->fRate];          *coeffIC = pArrayIC[fC/stft->fRate];      *coeffIP = pArrayIP[fP/stft->fRate];          break;    case RealStft :       GetStftData(stft,tM,&pArrayRM,NULL);      GetStftData(stft,tC,&pArrayRC,NULL);      GetStftData(stft,tP,&pArrayRP,NULL);      *coeffRM = pArrayRM[fM/stft->fRate];          *coeffRC = pArrayRC[fC/stft->fRate];      *coeffRP = pArrayRP[fP/stft->fRate];          break;    default :      Errorf("GetNeighborsData : Weired error (stft type)");      break;    }  }  else {    signal = GetChannel(dict,channel);    SCAtomInnerProduct(signal,atomM,stft->borderType,&(atomM->coeffR),&(atomM->coeffI));    SCAtomInnerProduct(signal,atomC,stft->borderType,&(atomC->coeffR),&(atomC->coeffI));    SCAtomInnerProduct(signal,atomP,stft->borderType,&(atomP->coeffR),&(atomP->coeffI));    switch(type) {    case ComplexStft :      *coeffRM = atomM->coeffR;      *coeffRC = atomC->coeffR;      *coeffRP = atomP->coeffR;      *coeffIM = atomM->coeffI;      *coeffIC = atomC->coeffI;      *coeffIP = atomP->coeffI;      break;    case RealStft :      CastAtomReal(atomM);      CastAtomReal(atomC);      CastAtomReal(atomP);      *coeffRM = atomM->coeff2;      *coeffRC = atomC->coeff2;      *coeffRP = atomP->coeff2;      break;    default :      Errorf("GetNeighborsData : Weired error (stft type)");      break;    }  }  return(YES);}/* * The main procedure to estimate the chirpId and windowSize of a chirplet * using parabolic interpolation of the second derivatives of the phase and log-amplitude  * of a spectrogram. Cf the article * "Fast Matching Pursuit with a multiscale dictionary of Gaussian chirps", * IEEE Trans. Signal Proc., Vol. 49, No. 5, May 2001 * Input  :  * Output : * Return : *   YES (in most cases) : the estimation was successful and compatible with the underlying model *   NO if the model was not compatible with the data (the content of the output is unspecified) */static char EstimateChirp(const ATOM atom,LWFLOAT aLogAmp,LWFLOAT aPhiWrapped,unsigned long rate,LWFLOAT *pChirpId,LWFLOAT *pWindowSize){  LWFLOAT scale,scale2,binSize;  LWFLOAT der2LogAmp,der2Phi;  int nMin,nMax;  LWFLOAT estimChirpId;  // TODO : Errorf or what ?  if(atom->windowShape != GaussWindowShape) {    Warningf("EstimateChirp : only valid for Gaussian windows, not '%s'",WindowShape2Name(atom->windowShape));  }  scale   = atom->windowSize;  scale2  = theGaussianSigma2*scale*scale;  binSize = (2*M_PI*rate)/GABOR_MAX_FREQID;  if(scale2 >= 2*M_PI/(binSize*binSize))      Errorf("EstimateChirp (Weired) : multiple unwrapping of the phase may be possible");  der2LogAmp     = aLogAmp/(binSize*binSize);  /* Testing if the 'ridge' model is valid : see Eq. (18) in the paper */  if(der2LogAmp >= 0 || der2LogAmp < -scale2) {    //Warningf("EstimateChirp : model is incompatible with logAmp");    return(NO);  }  /*    * 'Unwrapping' the phase : given the second derivative der2Phi of the phase of a spectrogram along frequency, we compute   * the value of 'der2Phi+2*n*pi/(binSize*binSize)' which is compatible with the chirp model : see Eq. (17) in paper.   * If no such value is compatible, then the model does not allow an estimate.   */  der2Phi = aPhiWrapped/(binSize*binSize);  if(fabs(der2Phi) > scale2/2) {    nMin = ceil ((-der2Phi-scale2/2)*binSize*binSize/(2*M_PI));    nMax = floor((-der2Phi+scale2/2)*binSize*binSize/(2*M_PI));    /* Testing if the 'ridge' model is valid : is there at least one compatible unwrapping ? */    if(nMin != nMax) {      //Warningf("EstimateChirp : model is incompatible with phase unwrapping [%d %d]",nMin,nMax);      return(NO);    }     der2Phi += 2*M_PI*nMin/(binSize*binSize);  }  /* The estimation */  estimChirpId       = -der2Phi/(der2LogAmp*der2LogAmp+der2Phi+der2Phi);  *pChirpId    = estimChirpId*GABOR_MAX_FREQID/(2*M_PI);#ifdef DEBUG_SCALE  estimInverseScale2 = -(1/scale2)-der2LogAmp/(der2LogAmp*der2LogAmp+der2Phi*der2Phi);  // DEBUG/INFO for future estimate ??  if(estimInverseScale2 <= 0.0)    Warningf("EstimateChirp : estimated scale2=1/(%g) is negative or infinite !",estimInverseScale2);  estimScale2        = 1/estimInverseScale2;  *pWindowSize = sqrt(estimScale2/theGaussianSigma2);  // DEBUG  if(estimInverseScale2 > 0.0)    Printf("s = %g -> %d ",*pWindowSize,1<<((int)(0.5+(log(*pWindowSize)/log(2.0)))));#endif  return(YES);}/* * Estimation of the fields of an atom using three neighbors and interpolation. * Output : one or more estimated parameters, depending on paramType. * Return : YES if the estimation was successful, NO in the other case (the content of the estimated parameters is then unspecified) */static char EstimateAtomParameter(ATOM atom,DICT dict,unsigned char channel,unsigned char paramType,LWFLOAT *pParamVal,LWFLOAT *pAuxParamVal){  unsigned long rate;  LWFLOAT coeff2M,coeff2C,coeff2P;  LWFLOAT realM,realC,realP,imagM,imagC,imagP;  LWFLOAT phaseM,phaseC,phaseP;  LWFLOAT logAmpM,logAmpC,logAmpP;  LWFLOAT aPhi,aLogAmp,b,c;  LWFLOAT kPhi;  LWFLOAT dTimeId,dFreqId,dChirpId,windowSize;  LWFLOAT freqId,chirpId;  /* Checking */  CheckAtom(atom);  switch(paramType) {    /***************************************/    /* Interpolation on the time parameter */    /***************************************/  case TimeParameter :    /* We get the value on three points to interpolate */    if(GetNeighborsData(atom,dict,channel,RealStft,TIME_NEIGHBOR,&rate,&coeff2M,&coeff2C,&coeff2P,NULL,NULL,NULL)==NO) {      //Warningf("TimeInterpolation : no neighbor available");      return(NO);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -