mhs.c

来自「Time-Frequency Toolbox,其中包含很常用的MATLAB程序」· C语言 代码 · 共 283 行

C
283
字号
/* EXISTS AN INTERFACE PROGRAM TO MATLAB : CTFRMHS.C                          *
 *============================================================================*
 * Name of the function : mhs.c (void)                                        *
 * Authors              : Emmanuel Roy - Manuel DAVY                          *
 * Date of creation     : 10 - 02 - 1999                                      *
 *----------------------------------------------------------------------------*
 * THE ALGORITHM                                                              *
 *                                                                            *
 * Given a signal to analyze in time and frequency, computes the Margenau-Hill*
 * Spectrogram Distribution (MHS) :                                           *
 *                                                                            *
 *                                                                            *
 *                       -1                                                   *
 *     MHS(t,f) = Real{ Kgh  F(t,f,g) F*(t,f,h) }                             *
 *                                                                            *
 *                  /                                                         *
 *    where  Kgh =  | h(u) g*(u) du                                           *
 *                 /                                                          *
 *                                                                            *
 *    F(t,f,h) and F(t,f,h) are the short-time Fourier transform of the signal*
 *    with h and g as analysis windows                                        *
 *                                                                            *
 * This function is real valued. Its computation requires a real or complex   *
 * signal, a vector containing time instants, the number of frequency bins, 2 *
 * frequency smoothing (analysis) windows.                                    *
 *                                                                            *
 *============================================================================*
 * INPUT VARIABLES                                                            *
 * Name                |              role                                    *
 * Signal              | The signal to analyze. No field modified             *
 *                     |                                                      *
 * WindowG             | Vector containing the points of the frequency window *
 * WindowG_Length      | Number of points of the g window (ODD number !)      *
 *                     |                                                      *
 * WindowH             | Vector containing the points of the frequency window *
 * WindowH_Length      | Number of points of the h window (ODD number !)      *
 *                     |                                                      *
 * tfr                 | Matrix containing the resulting TFR (real)           *
 * tfr.time_instants   | positions of the smoothing window                    *
 * tfr.N_time          | length of '.time_instants' = number of cols.         *
 *                     | in the tfr matrix                                    *
 * tfr.N_freq          | number of frequency bins = number of rows in the tfr *
 *                     | matrix                                               *
 * tfr.is_complex      | must be set to FALSE (a MHS tfr is real-valued)      *
 *                     |                                                      *
 *----------------------------------------------------------------------------*
 * OUTPUT VARIABLES                                                           *
 * Name                |                role                                  *
 * tfr.real_part       | the output tfr matrix  (real_part)                   *
 * tfr.freq_bins       | vector of frequency bins (freqs where the tfr matrix *
 *                     | is computed)                                         *
 *----------------------------------------------------------------------------*
 * INTERNAL VARIABLES                                                         *
 * Name                |                 role                                 *
 *                     |                                                      *
 * Nfft                | Next power of two to tfr.N_freq                      *
 * column, row         | variables of displacement in the matrices            *
 * time                | local time-instant variable to compute the tfr       *
 *                     |                                                      *
 * half_WindowG_Length | half-length of the frequency smoothing window g      *
 *                     |                                                      *
 * half_WindowH_Length | half-length of the frequency smoothing window h      *
 * normH               | normalization factor for the frequency window        *
 *                     |                                                      *
 * Lgh                 | variable to compute the lower length between         *
 *                     | half_WindowG_Length and half_WindowH_Length          *
 * Kgh                 | normalization factor                                 *
 *                     |                                                      *
 * tau                 | time-lag variable                                    *
 * taumin              | local time-lag variable bounds. Used to take into    *
 * taumax              | accound the beginning and the end of the             *
 *                     | signal, where the window is cut                      *
 *                     |                                                      *
 * windG_sig_real      | real and imaginary parts of the windowed signal      *
 * windG_sig_imag      | (analysis window g)                                  *
 *                     |                                                      *
 * windH_sig_real      | real and imaginary parts of the windowed signal      *
 * windH_sig_imag      | (analysis window h)                                  *
 *                     |                                                      *
 *============================================================================*
 * SUBROUTINES USED HERE                                                      *
 *----------------------------------------------------------------------------*
 * Name   | int idx(int i_row, int j_col, int nb_row)                         *
 * Action | computes the vector index for an element in a matrix given the row*
 *        | and column indices (i,j) and the total number of row              *
 * Place  | divers.c                                                          *
 *----------------------------------------------------------------------------*
 * Name   | int irem( double x, double y)                                     *
 * Action | computes the remainder after Euclidean division of double         *
 * Place  | divers.c                                                          *
 *----------------------------------------------------------------------------*
 * Name   | void fft(int n, int m, double *x, double *y)                      *
 * Action | Computes the fft                                                  *
 * Place  | divers.c                                                          *
 *----------------------------------------------------------------------------*
 * Name   | int po2(int x)                                                    *
 * Action | Computes the next power of two of x                               *
 * Place  | divers.c                                                          *
 *============================================================================*/

void
mhs (type_signal Signal,
      double *WindowG, int WindowG_Length,
      double *WindowH, int WindowH_Length,
      type_TFR tfr )

{
  int            Nfft, column, row, time;
  int            taumin, taumax, tau;
  int            half_WindowG_Length, half_WindowH_Length;
  double        *windG_sig_real, *windG_sig_imag; /* windowed signal */
  double        *windH_sig_real, *windH_sig_imag; /* windowed signal */
  double         normH;
  int            Lgh, points;
  double         Kgh;

 /*--------------------------------------------------------------------*/
 /*                      Test the input variables                      */
 /*--------------------------------------------------------------------*/


   if (tfr.is_complex == TRUE)
    {
      printf ("mhs.c : The tfr matrix must be real valued\n");
      exit(0);
    }

  if (tfr.N_freq <= 0)
    {
      printf ("mhs.c : The field tfr.N_freq is not correctly set\n");
      exit(0);
    }

  if (tfr.N_time <= 0)
    {
      printf ("mhs.c : The field tfr.N_time is not correctly set\n");
      exit(0);
    }

 /*--------------------------------------------------------------------*/
 /*                   checks that the window length is odd             */
 /*--------------------------------------------------------------------*/
 if (ISODD(WindowG_Length) == 0)
    {
      printf ("mhs.c : The window G Length must be an ODD number\n");
      exit(0);
    }


  if (ISODD(WindowH_Length) == 0)
    {
      printf ("mhs.c : The window H Length must be an ODD number\n");
      exit(0);
    }

  half_WindowG_Length = (WindowG_Length - 1) / 2;
  half_WindowH_Length = (WindowH_Length - 1) / 2;

  normH=WindowH[half_WindowH_Length];

  for(row = 0; row < WindowH_Length; row++)
    {
      WindowH[row] = WindowH[row]/normH;
    }

  
  Lgh = MIN( half_WindowG_Length , half_WindowH_Length );
  Kgh = 0.0;
  for( points=-Lgh ; points<=Lgh ; points++)
     {
      Kgh = Kgh + WindowH[half_WindowH_Length+points]
                 *WindowG[half_WindowG_Length+points];
      }

  for(row = 0; row < WindowH_Length; row++)
    {
      WindowH[row] = WindowH[row]/Kgh;
    }
  
 /*--------------------------------------------------------------------*/
 /*           creation of the vector of frequency bins  (output)       */
 /*--------------------------------------------------------------------*/
  Nfft = po2 (tfr.N_freq);

  for (row = 0; row < tfr.N_freq; row++)
    {
      tfr.freq_bins[row] = (double) row / tfr.N_freq;
    }
 /*--------------------------------------------------------------------*/
 /*                memory allocation for the windowed signal           */
 /*--------------------------------------------------------------------*/
  windG_sig_real = (double *) ALLOC (tfr.N_freq, sizeof (double));
  windG_sig_imag = (double *) ALLOC (tfr.N_freq, sizeof (double));

  windH_sig_real = (double *) ALLOC (tfr.N_freq, sizeof (double));
  windH_sig_imag = (double *) ALLOC (tfr.N_freq, sizeof (double));

  for (row = 0; row < tfr.N_freq; row++)
	   {
	    windG_sig_real[row] = 0.0;
	    windG_sig_imag[row] = 0.0;
       windH_sig_real[row] = 0.0;
	    windH_sig_imag[row] = 0.0;
       }
 /*--------------------------------------------------------------------*/
 /*      computation of the fft for the current windowed signal        */
 /*--------------------------------------------------------------------*/
  for (column = 0; column < tfr.N_time; column++)
    {

      /* time instants of interest to compute the tfr */
      time = ((int) tfr.time_instants[column]) - 1;

      taumin = MIN (tfr.N_freq / 2, half_WindowG_Length);
      taumin = MIN (taumin, time);

      taumax = MIN ((tfr.N_freq / 2 - 1), half_WindowG_Length);
      taumax = MIN (taumax, (Signal.length - time - 1));

      /* The signal is windowed around the current time */
      for (tau = -taumin; tau <= taumax; tau++)
	     {
	      row = irem( (tfr.N_freq+tau), tfr.N_freq ) ;
	      windG_sig_real[row] = Signal.real_part[time + tau]
	                         * WindowG[half_WindowG_Length + tau];
	      if (Signal.is_complex == TRUE)
	       {
	        windG_sig_imag[row] = Signal.imag_part[time + tau]
                                   * WindowG[half_WindowG_Length + tau];
	       }
        }

      /* fft of the windowed signal */
      fft (tfr.N_freq, Nfft, windG_sig_real, windG_sig_imag);


      taumin = MIN (tfr.N_freq / 2, half_WindowH_Length);
      taumin = MIN (taumin, time);

      taumax = MIN ((tfr.N_freq / 2 - 1), half_WindowH_Length);
      taumax = MIN (taumax, (Signal.length - time - 1));

      /* The signal is windowed around the current time */
      for (tau = -taumin; tau <= taumax; tau++)
	     {
	      row = irem( (tfr.N_freq+tau), tfr.N_freq ) ;
	      windH_sig_real[row] = Signal.real_part[time + tau]
	                         * WindowH[half_WindowH_Length + tau];
	      if (Signal.is_complex == TRUE)
	       {
	        windH_sig_imag[row] = Signal.imag_part[time + tau]
                                   * WindowH[half_WindowH_Length + tau];
	       }
        }

      /* fft of the windowed signal */
      fft (tfr.N_freq, Nfft, windH_sig_real, windH_sig_imag);



      /* the first half of the fft is put in the tfr matrix  */
      for (row = 0; row < tfr.N_freq; row++)
	{
	  tfr.real_part[idx (row,column,tfr.N_freq)] = 
	             windG_sig_real[row]*windH_sig_real[row]
                   + windG_sig_imag[row]*windH_sig_imag[row];

     windG_sig_real[row] = 0.0;
	    windG_sig_imag[row] = 0.0;
       windH_sig_real[row] = 0.0;
	    windH_sig_imag[row] = 0.0;
        }
    }
 /*--------------------------------------------------------------------*/
 /*                free the memory used in this program                */
 /*--------------------------------------------------------------------*/
  FREE (windG_sig_real);
  FREE (windG_sig_imag);
  FREE (windH_sig_real);
  FREE (windH_sig_imag);

}

⌨️ 快捷键说明

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