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

📄 atom.c

📁 LastWave
💻 C
📖 第 1 页 / 共 3 页
字号:
      if (coeffR >= 0) {	*pCosPhase = 1.0;	*pSinPhase = 0.0;	*pPhase	 = 0.0;      } else {	*pCosPhase = -1.0;	*pSinPhase = 0.0;	*pPhase	 = 0.5;      }    }    return;  } else {    /* Cf. PhD thesis R. Gribonval */    /* Computing energy */    if(pEnergy) {      *pEnergy    = innerProd2-realGG*(coeffR*coeffR-coeffI*coeffI)+imagGG*2*coeffR*coeffI;      *pEnergy   *= 2;      *pEnergy   /= 1-(realGG*realGG+imagGG*imagGG);      // DEBUG       if(*pEnergy<0) Errorf("ComputeRealPhaseEnergy : (Weired) negative energy!");    }    /* Computing phase */    if(pPhase) {      real = (1-realGG)*coeffR + imagGG*coeffI;      imag = (1+realGG)*coeffI + imagGG*coeffR;          norm = sqrt(real*real+imag*imag);      *pCosPhase  = real/norm;      *pSinPhase  = imag/norm;      *pPhase = atan2(imag,real)/(2*M_PI);      if (*pPhase<0)	*pPhase = 1+*pPhase;      if(*pPhase >= 1.0)	*pPhase = *pPhase-1.0;    }  }}void CastAtomReal(ATOM atom){  LWFLOAT phase;  CheckAtom(atom);  SetAtomGG(atom);  ComputeRealPhaseEnergy(atom->coeffR,atom->coeffI,atom->realGG,atom->imagGG,			 &phase,&(atom->cosPhase),&(atom->sinPhase),&(atom->coeff2));  // DEBUG  if(isnan(atom->coeff2) || atom->coeff2 < 0.0) Errorf("CastAtomReal : atom coeff2=%g!",atom->coeff2);}/********************************************* *      The main function which builds atoms  ********************************************* * Build either (depending whether atomI!=NULL or not) * a/ a COMPLEX NORMALIZED atom (coeff2,coeffR,coeffI,cosPhase,sinPhase are not taken into account). * b/ a REAL atom (coeff2,cosPhase,sinPhase are used)  * The 'dx' and 'x0' fields of the output signals are properly set. * * If 'flagAtomSizeOnly'==YES, the output signal(s) have 'windowSize' samples corresponding to the 'support' of the atom, *   (the first sample is zero) * Else, the output signal(s) have 'signalSize' samples. * * The function built is the product of * -an amplitude 'sqrt(coeff2)', for REAL atoms (the amplitude is one for COMPLEX ones). * -a normalized window g_s(t-timeId), with shape and size determined by 'windowShape' and 'windowSize' * -a modulation : *  COMPLEX : exp(i*2*PI*(freqId*(t-timeId)/GABOR_MAX_FREQID+(chirpId/2)*(t-timeId)^2/GABOR_MAX_FREQID)) *  or *  REAL      cos(2*PI*(phi+freqId*(t-timeId)/GABOR_MAX_FREQID+(chirpId/2)*(t-timeId)^2/GABOR_MAX_FREQID)) * * WARNING: BORDERTYPE IS NOT  PROPERLY TREATED YET !!!!! ***************************************************************************/void BuildAtom(const ATOM atom,SIGNAL atomR,SIGNAL atomI,char borderType,char flagAtomSizeOnly){  /* Parameters of the atom (we make a copy to get shorter notations) */  LWFLOAT timeId;  LWFLOAT freqId;  LWFLOAT chirpId;  LWFLOAT coeff2,cosPhase,sinPhase,phase;  /* Tabulated data */  SIGNAL expikR 	= NULL;   SIGNAL expikI 	= NULL;  SIGNAL window 	= NULL;  static SIGNAL tempSignal = NULL;  unsigned long reconsSize;  // TODO : change to (unsigned) long when prototype of ComputeWindowSupport is changed ?  int   timeIdMin,timeIdMax;  unsigned long i;  long index;  double phaseArgument;    LWFLOAT ishift;    LWFLOAT factor;  LWFLOAT norm2;    /* Checking */  CheckAtom(atom);  if(atomR == NULL)               Errorf("BuildAtom : NULL atomR (Weird Error)");  if(!BorderTypeIsOK(borderType)) Errorf("BuildAtom : unknown borderType %d",borderType);    /* We copy the atom parameters to get shorter notation */  timeId  = atom->timeId;  freqId  = atom->freqId;  chirpId = atom->chirpId;  /* Complex atoms are normalized, real atoms use coeff2 and cosPhase/sinPhase */  if(atomI==NULL) {    coeff2    = atom->coeff2;    cosPhase  = atom->cosPhase;    sinPhase  = atom->sinPhase;    phase = atan2(atom->sinPhase,atom->cosPhase)/(2*M_PI);    if (phase<0)     phase = 1+phase;    if(phase >= 1.0) phase = phase-1.0;  } else {    coeff2    = 1.0;    cosPhase  = 1.0;    sinPhase  = 0.0;    phase     = 0.0;  }  /* Determine the size of the output signal(s) and allocate it/them */  if (flagAtomSizeOnly == YES)     reconsSize = atom->windowSize;  else                             reconsSize = atom->signalSize;  SizeSignal(atomR,reconsSize,YSIG);  ZeroSig(atomR);  if(atomI != NULL) {    SizeSignal(atomI,reconsSize,YSIG);    ZeroSig(atomI);  }    /* Compute the support of the atom [timeIdMin,timeIdMax]    * i.e. the set of indexes (in sample coordinates of the output signal) that have to be filled.   */  ComputeWindowSupport(atom->windowSize,atom->windowShape,timeId,&timeIdMin,&timeIdMax);  /* Add the first point of the atom, which value is zero */  // TODO : remove!  timeIdMin -=1;    /* Set the dx/x0 fields of the output signals */  if(flagAtomSizeOnly == YES) {    /* The output signals have a time offset with respect to the input signal */    atomR->x0 = atom->x0 + timeIdMin*atom->dx;    atomR->dx = atom->dx;    if(atomI != NULL){      atomI->x0   = atomR->x0;      atomI->dx   = atomR->dx;    }    /* TODO : EXPLAIN !!!! */    ishift  = timeIdMin-timeId;    /* The whole output signal has to be filled without any border effect */    timeIdMin	= 0;    timeIdMax	= reconsSize-1;  }  else {    /* The output signals have the same time offset as the input signal  */    atomR->x0 = atom->x0;    atomR->dx = atom->dx;    if(atomI != NULL){      atomI->x0 = atomR->x0;      atomI->dx = atom->dx;    }    /* TODO : EXPLAIN !!!! */    ishift 	= -timeId;    /* TODO : treat the border effects */    switch(borderType) {    case BorderPad0 :      timeIdMin	= MAX(0,timeIdMin);      timeIdMax	= MIN(reconsSize-1,timeIdMax);      break;    default :      Errorf("BuildAtom : border %s not treated yet",BorderType2Name(borderType));    }  }    /*   * Now, we start actually building the atom   */  /* First, the window of the atom */  GetTabWindow(atom->windowShape,atom->windowSize,&window);  for(i=timeIdMin; i <= timeIdMax; i++)  atomR->Y[i] = window->Y[i-timeIdMin];  if (atomI != NULL) {    for(i=timeIdMin;i<=timeIdMax;i++)    atomI->Y[i] = atomR->Y[i];  }  /* Then, multiply by the modulation, including the chirp */  /* We can use the tabulated exponentials only when   * - freqId is an integer [because freqId*(i+ishift) must be integer for all i]   * - phase is either 0 or 0.5 modulo 1   * - chirpId is an *even* integer        [because 0.5*chirpId*(i+ishift)^2 must be integer for all i]   */  if (freqId != (int) freqId || ((phase != 0) && (phase != 0.5)) || chirpId/2 == (int) (chirpId/2)) {    /* Modulating without tabulated data */    for(i=timeIdMin;i<=timeIdMax;i++) {      /* TODO : EXPLAIN the use of ishift */      phaseArgument = 2*M_PI*(phase+ (freqId*(i+ishift))/(GABOR_MAX_FREQID)			      +0.5*(chirpId*(i+ishift)*(i+ishift))/(GABOR_MAX_FREQID));      atomR->Y[i] *= cos(phaseArgument);      if(atomI != NULL)	atomI->Y[i] *= sin(phaseArgument);    }  } else {    /* Modulating with tabulated data */    GetTabExponentials(&expikR,&expikI);    /* Computations are modulo 'GABOR_MAX_FREQID', with positive integers */    ishift   = GABOR_MAX_FREQID + ((int) ishift)%(GABOR_MAX_FREQID);    for(i=timeIdMin;i<=timeIdMax;i++)  {	      /* TODO : EXPLAIN the use of ishift */      // Is there a problem here with phase?      //index = ((int) (phase*GABOR_MAX_FREQID      //+ freqId*(i+ishift)      //+ 0.5*chirpId*(i+ishift)*(i+ishift)))	%(GABOR_MAX_FREQID);      index  = ((int)freqId)*(i+(int)ishift);      index += ((int)(chirpId/2))*(i+(int)ishift)*(i+(int)ishift);      if(phase==0.5)	index += GABOR_MAX_FREQID/2;      index = index%GABOR_MAX_FREQID;      index = (index+GABOR_MAX_FREQID)%GABOR_MAX_FREQID;      if(!INRANGE(0,index,expikR->size-1)) Errorf("BuildAtom : (Weird) internal accessing expikR[%d]",index);      if(i>=atomR->size)      Errorf("BuildAtom : (Weird) internal atomR");      atomR->Y[i] *= expikR->Y[index];      if(atomI != NULL)	atomI->Y[i] *= expikI->Y[index];    }  }    /*   * If the atom we built is complex, we are done   */  if(atomI!=NULL) return;  else {    /* Compute the norm of the real atom */    norm2 = 0.0;    for(i=timeIdMin;i<=timeIdMax;i++) norm2 += atomR->Y[i]*atomR->Y[i];      /* Normalize the atom and set its amplitude */    factor = sqrt(coeff2/norm2);    for(i=timeIdMin;i<=timeIdMax;i++) atomR->Y[i] *= factor;  }}/* * The functions to Get the atom fields *//* * The window fields : windowShape,windowSize, */static char *windowShapeDoc = "{[= <windowShape>]} {Sets/Gets the windowShape of an atom. "WindowShapeHelpString"}";static char *windowSizeDoc = "{[= <windowSize>]} {Sets/Gets the windowSize of an atom, i.e. the number of samples of its window. So far only powers of 2 are allowed.}";void *GetWindowShapeAtomV(ATOM atom, void **arg){  /* Documentation */  if (atom == NULL) return(windowShapeDoc);  return(GetStrField(WindowShape2Name(atom->windowShape),arg));}void *GetWindowSizeAtomV(ATOM atom, void **arg){  /* Documentation */  if (atom == NULL) return(windowSizeDoc);  return(GetIntField(atom->windowSize,arg));}void *SetWindowShapeAtomV(ATOM atom, void **arg){  static char *windowShapeName = NULL;  char windowShape;  /* Documentation */  if (atom == NULL) return(windowShapeDoc);  // Allocation (once only) of the resulting string  if(windowShapeName == NULL) {    windowShapeName = CharAlloc(1);    windowShapeName[0] = '\0';  }  if(SetStrField(&windowShapeName,arg)==NULL) return(NULL);  windowShape = Name2WindowShape(windowShapeName);  // If the windowShape changed we have to recompute the 'GG' of the atom  // to keep coherent  if(atom->windowShape == windowShape) return(strType);  atom->windowShape = windowShape;  SetAtomGG(atom);  // DEBUG TODO : remove!  if(atom->realGG*atom->realGG+atom->imagGG*atom->imagGG>1) {    PrintInfoValue(atom);    Errorf("SetWindowShapeAtomV : (Weired) bad GG (%g %g)",atom->realGG,atom->imagGG);  }  return(strType);}void *SetWindowSizeAtomV(ATOM atom, void **arg){  int windowSize;  /* Documentation */  if (atom == NULL) return(windowShapeDoc);  // Init (for += syntax for example)  windowSize = atom->windowSize;  if(SetIntField(&windowSize,arg,FieldSPositive)==NULL) return(NULL);  /* Some checkings */  if(!INRANGE(STFT_MIN_WINDOWSIZE,windowSize,STFT_MAX_WINDOWSIZE) || windowSize > atom->signalSize) {    SetErrorf("Cannot set atom.windowSize=%d. Should be between %d and %d and at most atom.signalSize (%d)",	      windowSize,STFT_MIN_WINDOWSIZE,STFT_MAX_WINDOWSIZE,atom->signalSize);    return(NULL);  }  // If the windowSize changed we have to recompute the 'GG' of the atom  // to keep coherent  if(atom->windowSize == windowSize) return(numType);  atom->windowSize = windowSize;  SetAtomGG(atom);  // DEBUG TODO : remove!  if(atom->realGG*atom->realGG+atom->imagGG*atom->imagGG>1) {    PrintInfoValue(atom);    Errorf("SetWindowSizeAtomV : (Weired) bad GG (%g %g)",atom->realGG,atom->imagGG);  }  return(numType);}/* * The dt/df fields */static char *dtDoc = "{} {Gets the time spread of an atom in seconds.}";static char *dfDoc = "{} {Gets the frequency spread of an atom in Hertz.}";static char *supportDoc = "{} {Gets the time support {timeMin timeMax} of an atom in seconds}"; static char *supportIdDoc = "{} {Gets the time support {timeIdMin timeIdMax} of an atom in sample coordinates}"; void *GetDtDfAtomV(ATOM atom,void **arg){  char *field = ARG_G_GetField(arg);  LISTV lv;  int timeIdMin,timeIdMax;  /* Documentation */  if (atom == NULL) {    if(!strcmp(field,"dt")) return(dtDoc);    if(!strcmp(field,"df")) return(dfDoc);    if(!strcmp(field,"support")) return(supportDoc);    if(!strcmp(field,"supportId")) return(supportIdDoc);  }  if(!strcmp(field,"dt"))      return(GetFloatField(0.5*(TimeId2Time(atom,atom->windowSize)-TimeId2Time(atom,0)),arg));  if(!strcmp(field,"df"))    return(GetFloatField(0.5*FreqId2Freq(atom,((LWFLOAT)GABOR_MAX_FREQID)/(2*M_PI*theGaussianSigma2*(LWFLOAT)atom->windowSize)),arg));  if(!strcmp(field,"support") || !strcmp(field,"supportId")) {    lv = TNewListv();    ComputeWindowSupport(atom->windowSize,atom->windowShape,atom->timeId,			 &timeIdMin,&timeIdMax);    if(!strcmp(field,"supportId")) {      AppendInt2Listv(lv,timeIdMin);      AppendInt2Listv(lv,timeIdMax);    } else {      AppendFloat2Listv(lv,TimeId2Time(atom,timeIdMin));      AppendFloat2Listv(lv,TimeId2Time(atom,timeIdMax));    }    return(GetValueField(lv,arg));  }}/* * The time(Id) fields */static char *timeIdDoc = "{[= <timeId>]} {Sets/Gets the time center of an atom in sample coordinates, i.e. an index 0 <= timeId < atom.signalSize.}";static char *timeDoc = "{[= <time>]} {Sets/Gets the time center of an atom in real coordinates, i.e. the real time in seconds.}";void *GetTimeAtomV(ATOM atom,void **arg){  char *field = ARG_G_GetField(arg);   /* Documentation */  if (atom == NULL) {    if(!strcmp(field,"time")) return(timeDoc);    if(!strcmp(field,"timeId")) return(timeIdDoc);  }  if(!strcmp(field,"time"))      return(GetFloatField(TimeId2Time(atom,atom->timeId),arg));  if(!strcmp(field,"timeId"))    return(GetFloatField(atom->timeId,arg));}void *SetTimeAtomV(ATOM atom,void **arg){  char *field = ARG_G_GetField(arg);  char flagId = NO;  LWFLOAT time,timeId;  /* Documentation */  if (atom == NULL) {    if(!strcmp(field,"time")) return(timeDoc);    if(!strcmp(field,"timeId")) return(timeIdDoc);  }  if(!strcmp(field,"timeId"))    flagId = YES;  else if(!strcmp(field,"time")) flagId = NO;  else Errorf("SetTimeAtomV : Weird field %s",field);  if(flagId) {    // Init for += syntax    timeId = atom->timeId;    if(SetFloatField(&timeId,arg,FieldPositive)==NULL) return(NULL);  }  else {

⌨️ 快捷键说明

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