📄 atom.c
字号:
// Init for += syntax time = TimeId2Time(atom,atom->timeId); if(SetFloatField(&time,arg,0)==NULL) return(NULL); timeId = Time2TimeId(atom,time); } /* Some checkings */ if(!INRANGE(0,timeId,atom->signalSize-1)) { if(flagId) SetErrorf("Cannot set atom.timeId=%g because atom.signalSize-1=%d",timeId,atom->signalSize-1); else SetErrorf("Cannot set atom.time=%g (should be in [0,%g])",time,TimeId2Time(atom,atom->signalSize-1)); return(NULL); } atom->timeId = timeId; return(numType);} /* * The freq(Id) fields */static char *freqIdDoc = "{[= <freqId>]} {Sets/Gets the frequency center of an atom in sample coordinates, i.e. an index 0 <= freqId <= atom.freqIdNyquist.}";static char *freqDoc = "{[= <freq>]} {Sets/Gets the frequency center of an atom in real coordinates, i.e. the real frequency in Hertz.}";void *GetFreqAtomV(ATOM atom,void **arg){ char *field = ARG_G_GetField(arg); /* Documentation */ if (atom == NULL) { if(!strcmp(field,"freq")) return(freqDoc); if(!strcmp(field,"freqId")) return(freqIdDoc); } if(!strcmp(field,"freq")) return(GetFloatField(FreqId2Freq(atom,atom->freqId),arg)); if(!strcmp(field,"freqId")) return(GetFloatField(atom->freqId,arg));}void *SetFreqAtomV(ATOM atom,void **arg){ char *field = ARG_G_GetField(arg); char flagId = NO; LWFLOAT freq,freqId; /* Documentation */ if (atom == NULL) { if(!strcmp(field,"freq")) return(freqDoc); if(!strcmp(field,"freqId")) return(freqIdDoc); } if(!strcmp(field,"freqId")) flagId = YES; else if(!strcmp(field,"freq")) flagId = NO; else Errorf("SetFreqAtomV : Weird field %s",field); if(flagId) { // Init for += syntax freqId = atom->freqId; if(SetFloatField(&freqId,arg,FieldPositive)==NULL) return(NULL); } else { // Init for += syntax freq = FreqId2Freq(atom,atom->freqId); if(SetFloatField(&freq,arg,FieldPositive)==NULL) return(NULL); freqId = Freq2FreqId(atom,freq); } /* Some checkings */ if(freqId > GABOR_NYQUIST_FREQID) { if(flagId) SetErrorf("Cannot set atom.freqId=%g because atom.freqIdNyquist=%d",freqId,GABOR_NYQUIST_FREQID); else SetErrorf("Cannot set atom.freq=%g (should be in [0,%g]",freq,FreqNyquist(atom)); return(NULL); } if(atom->coeffI != 0.0 && (freqId == 0 || freqId == GABOR_NYQUIST_FREQID)) { if(flagId) SetErrorf("Cannot set atom.freqId=0 or %d (Nyquist) because atom.coeffI=%g (try setting atom.coeffI=0 first)",GABOR_NYQUIST_FREQID,atom->coeffI); else SetErrorf("Cannot set atom.freq=0 or %g (Nyquist) because atom.coeffI=%g (try setting atom.coeffI=0 first)",atom->coeffI,FreqNyquist(atom)); return(NULL); } // If the freqId changed we have to recompute the 'GG' of the atom // to keep coherent if(atom->freqId == freqId) return(numType); atom->freqId = freqId; SetAtomGG(atom); // DEBUG TODO : remove! if(atom->realGG*atom->realGG+atom->imagGG*atom->imagGG>1) { PrintInfoValue(atom); Errorf("SetFreqAtomV : (Weired) bad GG (%g %g)",atom->realGG,atom->imagGG); } return(numType);} /* * The chirp(Id) fields */static char *chirpIdDoc = "{[= <chirpId>]} {Sets/Gets the chirp rate of an atom in sample coordinates, i.e. an index chirpId with |chirpId| <= atom.freqIdNyquist/2.}";static char *chirpDoc = "{[= <chirp>]} {Sets/Gets the chirp rate of an atom in real coordinates, i.e. the real frequency slope in Hertz per second.}";void *GetChirpAtomV(ATOM atom,void **arg){ char *field = ARG_G_GetField(arg); /* Documentation */ if (atom == NULL) { if(!strcmp(field,"chirp")) return(chirpDoc); if(!strcmp(field,"chirpId")) return(chirpIdDoc); } if(!strcmp(field,"chirp")) return(GetFloatField(ChirpId2Chirp(atom,atom->chirpId),arg)); if(!strcmp(field,"chirpId")) return(GetFloatField(atom->chirpId,arg));}void *SetChirpAtomV(ATOM atom,void **arg){ char *field = ARG_G_GetField(arg); char flagId = NO; LWFLOAT chirp,chirpId; /* Documentation */ if (atom == NULL){ if(!strcmp(field,"chirp")) return(chirpDoc); if(!strcmp(field,"chirpId")) return(chirpIdDoc); } if(!strcmp(field,"chirpId")) flagId = YES; else if(!strcmp(field,"chirp")) flagId = NO; else Errorf("SetChirpAtomV : Weird field %s",field); if(flagId) { // Init for += syntax chirpId = atom->chirpId; if(SetFloatField(&chirpId,arg,0)==NULL) return(NULL); } else { // Init for += syntax chirp = ChirpId2Chirp(atom,atom->chirpId); if(SetFloatField(&chirp,arg,0)==NULL) return(NULL); chirpId = Chirp2ChirpId(atom,chirp); } /* Some checkings */ if(!INRANGE(-GABOR_MAX_CHIRPID,chirpId,GABOR_MAX_CHIRPID)) { if(flagId) SetErrorf("Cannot set atom.chirpId=%g (its absolute value should be at most %g)",chirpId,GABOR_MAX_CHIRPID); else SetErrorf("Cannot set atom.chirp=%g (its absolute value should be at most %g)",chirp,ChirpId2Chirp(atom,GABOR_MAX_CHIRPID)); return(NULL); } // If the chirpId changed we have to recompute the 'GG' of the atom // to keep coherent if(atom->chirpId == chirpId) return(numType); atom->chirpId = chirpId; SetAtomGG(atom); // DEBUG TODO : remove! if(atom->realGG*atom->realGG+atom->imagGG*atom->imagGG>1) { PrintInfoValue(atom); Errorf("SetChirpAtomV : (Weired) bad GG (%g %g)",atom->realGG,atom->imagGG); } return(numType);} #ifdef ATOM_ADVANCED/* * The inner-product <g,_g> between a (normalized) complex atom * and its complex conjugate. */static char *ggDoc = "{} {Gets a listv {real imag} that corresponds to the (complex) inner-product <g,_g> between a (normalized) complex atom 'g' and its complex conjugate '_g'. The value of <g,_g> depends on the windowShape, windowSize, frequency and chirp parameters. It is used to compute the energy ||P_{g,_g}s||^2 of the projection of a (real valued) signal 's' on the subspace spanned by 'g' and '_g' from the complex inner product <s,g>. WARNING : this is a read-only field. If you type 'atom.gg[0]=1' it will be accepted but what will be performed is similar to 'l=atom.gg; l[0]=1'.}";void *GetGGAtomV(ATOM atom, void **arg){ LISTV lv; /* Documentation */ if (atom == NULL) return(ggDoc); lv = TNewListv(); AppendFloat2Listv(lv,atom->realGG); AppendFloat2Listv(lv,atom->imagGG); return(GetValueField(lv,arg));}#endif //ATOM_ADVANCED/* * The coeff fields : coeff2,phase */static char *coeff2Doc = "{[= <coeff2>]} {Sets/Gets the atom squared coefficient.}";static char *phaseDoc = "{[= <phase>]} {Sets/Gets the atom phase (which is defined modulo 1).}";static char *coeffDoc = "{} {Gets the atom complex coefficient.}";static LWFLOAT _ComputePhase(LWFLOAT cosPhase,LWFLOAT sinPhase){ LWFLOAT phase; phase = atan2(sinPhase,cosPhase)/(2*M_PI); if (phase<0) phase = 1+phase; if(phase >= 1.0) phase = phase-1.0; return(phase);}void *GetCoeffAtomV(ATOM atom, void **arg){ char *field = ARG_G_GetField(arg); LWFLOAT phase; LISTV lv; /* Documentation */ if (atom == NULL) { if(!strcmp(field,"coeff2")) return(coeff2Doc); if(!strcmp(field,"phase")) return(phaseDoc); if(!strcmp(field,"coeff")) return(coeffDoc); } CheckAtomReal(atom); if(!strcmp(field,"coeff2")) return(GetFloatField(atom->coeff2,arg)); if(!strcmp(field,"phase")) { phase = _ComputePhase(atom->cosPhase,atom->sinPhase); return(GetFloatField(phase,arg)); } if(!strcmp(field,"coeff")) { lv = TNewListv(); AppendFloat2Listv(lv,atom->coeffR); AppendFloat2Listv(lv,atom->coeffI); return(GetValueField((VALUE)lv,arg)); }}void *SetCoeffAtomV(ATOM atom, void **arg){ char *field = ARG_G_GetField(arg); LWFLOAT phase; /* Documentation */ if (atom == NULL) { if(!strcmp(field,"coeff2")) return(coeff2Doc); if(!strcmp(field,"phase")) return(phaseDoc); } if(!strcmp(field,"coeff2")) return(SetFloatField(&(atom->coeff2),arg,FieldSPositive)); if(!strcmp(field,"phase")) { // Init for += syntax phase = _ComputePhase(atom->cosPhase,atom->sinPhase); if(SetFloatField(&phase,arg,0)==NULL) return(NULL); if((atom->freqId == 0 || atom->freqId == GABOR_NYQUIST_FREQID) && 2*phase != (int) 2*phase) { SetErrorf("Cannot set <phase>=%g : should be 0 or 0.5 (modulo 1) when atom.freq==0 or Nyquist. Try changing atom.freq(Id) first.",phase); return(NULL); } atom->cosPhase = cos(2*M_PI*(phase-(int)phase)); atom->sinPhase = sin(2*M_PI*(phase-(int)phase)); // DEBUG Printf("%g %g %g\n",phase,atom->cosPhase,atom->sinPhase); return(numType); }}/* * A virtual field to build the atom in */static char *buildcDoc = "{[*opt,...] [:]} {Gets a pair {real imag} of signals where the normalized complex atom has been built.}";static char *buildrDoc = "{[*opt,...] [:]} {Gets a signal where the real atom has been built.}";static void *GetExtractBuildAtomV(ATOM atom,void **arg){ char *field = ARG_G_GetField(arg); SIGNAL signalR = NULL; SIGNAL signalI = NULL; char borderType = Name2BorderType("pad0");// TODO an EXTRACT OPTION char flagAtomSizeOnly = NO; // TODO AN EXTRACT OPTION LISTV lv; if(atom==NULL) { if(!strcmp(field,"buildc")) return(buildcDoc); if(!strcmp(field,"buildr")) return(buildrDoc); } // Temporary allocation of the output signal(s) signalR = TNewSignal(); if(!strcmp(field,"buildc")) signalI = TNewSignal(); // Building the atom BuildAtom(atom,signalR,signalI,borderType,flagAtomSizeOnly); // Setting the output if(!strcmp(field,"buildc")) { lv = TNewListv(); AppendValue2Listv(lv,(VALUE)signalR); AppendValue2Listv(lv,(VALUE)signalI); return(GetValueField(lv,arg)); } else { return(GetValueField(signalR,arg)); }}static char *buildExtractDoc = "{*sizeonly,*bperiodic,...} {*sizeonly : the signal(s) where the atom will be built will have exactly the size of the atom. Otherwise the atom.signalSize will be used.}";static char *buildExtractOptions[] = {"*bperiodic","*bmirror","*bmirror1","*bconst","*b0","*sizeonly",NULL};static void *GetExtractOptionsAtomV(ATOM atom, void **arg){ char *field; field = ARG_G_GetField(arg); // There is no extraction on the atom itself if(field == NULL) return(NULL); /* doc */ if (atom == NULL) { if (!strcmp(field,"buildr")) return(buildExtractDoc); if (!strcmp(field,"buildc")) return(buildExtractDoc); // There is no extraction on atom itself nor on other fields return(NULL); } if (!strcmp(field,"buildr")) return(buildExtractOptions); if (!strcmp(field,"buildc")) return(buildExtractOptions); return(NULL);}/* * Function to get the ExtractInfo for fields 'coeff' and 'build' (and 'gg' ?) */static void *GetExtractInfoAtomV(ATOM atom, void **arg){ static ExtractInfo extractInfo; char *field = ARG_EI_GetField(arg); unsigned long *options = ARG_EI_GetPOptions(arg); // No extraction is available on atom itself if(field==NULL) return(NULL); if(!strcmp(field,"buildr") || !strcmp(field,"buildc")) { SetErrorf("ExtractInfo for build not finalized");return(NULL); extractInfo.nSignals = 1; extractInfo.xmin = 0; extractInfo.xmax = 1; extractInfo.dx = 1; extractInfo.xsignal = NULL; extractInfo.flags = EIErrorBound; return(&extractInfo); } return(NULL);}/* * The field list */struct field fieldsAtom[] = { "dx",GetDxTFContentV,SetDxTFContentV,NULL,NULL, "x0",GetX0TFContentV,SetX0TFContentV,NULL,NULL, "signalSize",GetSignalSizeTFContentV,NULL,NULL,NULL, "freqIdNyquist",GetFreqIdNyquistTFContentV,NULL,NULL,NULL, "windowShape",GetWindowShapeAtomV,SetWindowShapeAtomV,NULL,NULL, "windowSize",GetWindowSizeAtomV,SetWindowSizeAtomV,NULL,NULL, "timeId",GetTimeAtomV,SetTimeAtomV,NULL,NULL, "time",GetTimeAtomV,SetTimeAtomV,NULL,NULL, "freqId",GetFreqAtomV,SetFreqAtomV,NULL,NULL, "freq",GetFreqAtomV,SetFreqAtomV,NULL,NULL, "chirp",GetChirpAtomV,SetChirpAtomV,NULL,NULL, "chirpId",GetChirpAtomV,SetChirpAtomV,NULL,NULL, "coeff2",GetCoeffAtomV,SetCoeffAtomV,NULL,NULL, "phase",GetCoeffAtomV,SetCoeffAtomV,NULL,NULL, "coeff",GetCoeffAtomV,NULL,NULL,NULL, "buildr",GetExtractBuildAtomV,NULL,GetExtractOptionsAtomV,GetExtractInfoAtomV, "buildc",GetExtractBuildAtomV,NULL,GetExtractOptionsAtomV,GetExtractInfoAtomV, // "build",GetExtractBuildAtomV,NULL,NULL,NULL, "dt",GetDtDfAtomV,NULL,NULL,NULL, "df",GetDtDfAtomV,NULL,NULL,NULL, "support",GetDtDfAtomV,NULL,NULL,NULL, "supportId",GetDtDfAtomV,NULL,NULL,NULL,#ifdef ATOM_ADVANCED "gg",GetGGAtomV,NULL,NULL,NULL,#endif // ATOM_ADVANCED NULL, NULL, NULL, NULL, NULL};/* * The type structure for ATOM */TypeStruct tsAtom = { "{{{&atom} {This type is the basic type for time-frequency atoms that are used in Short Time Fourier Transform and Matching Pursuit decompositions.}}}", /* Documentation */ &atomType, /* The basic (unique) type name */ NULL, /* The GetType function */ DeleteAtom, /* The Delete function */ NewAtom, /* The New function */ CopyAtom, /* The copy function */ ClearAtom, /* The clear function */ ToStrAtom, /* String conversion */ ShortPrintAtom, /* The Print function : print the object when 'print' is called */ PrintInfoAtom, /* The PrintInfo function : called by 'info' */ NULL, /* The NumExtract function : used to deal with syntax like 10a */ fieldsAtom, /* The list of fields */}; /* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -