mmce.c

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

C
332
字号
/* EXISTS AN INTERFACE PROGRAM TO MATLAB : CTFRMMCE.C                         *
 *============================================================================*
 * Name of the function : mmce.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 Minimu Mean  *
 * Cross-Entropy combination of spectrograms (MMCE) :                         *
 *                                                                            *
 *                         E                  __N                             *
 * MMCE(t,f) = ----------------------------   ||    |F(t,f;k)|^(2/N)          *
 *             ||  __N                    ||    k=1                           *
 *             ||  ||    |F(t,f;k)|^(2/N) ||                                  *
 *             ||    k=1                  ||1                                 *
 *                                                                            *
 * where || ||1 denotes the L1 norm, E the energy of the signal :             *
 *                                                                            *
 *         /               //                   ||         ||                 *
 *     E = | |x(t)|^2 dt = || MMCE(t,f) dt df = ||MMCE(t,f)||                 *
 *         /               //                   ||         ||1                *
 *                                                                            *
 * and F(t,f;k) the short-time Fourier transform of the signal, with the kieme*
 * analysis window h                                                          *
 *                                                                            *
 * This function is real valued. Its computation requires k frequency         *
 * smoothing windows, their displacement positions and the number of frequency*
 * bins to be computed with discrete variables.                               *
 *                                                                            *
 *============================================================================*
 * INPUT VARIABLES                                                            *
 * Name                |              role                                    *
 * Signal              | The signal to analyze. No field modified             *
 *                     |                                                      *
 * Window              | Matrix containing the points of the k frequency      *
 *                     | windows                                              *
 * Window_Length       | Number of points of the windows (ODD number !)       *
 * Window_col          | Number of analysis windows                           *
 *                     |                                                      *
 * 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 BJ 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_Window_Length  | half-length of the frequency smoothing window        *
 * Nb_Window           | number of analysis windows h                         *
 * normh               | normalization factor for the frequency windows       *
 *                     |                                                      *
 * 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                      *
 *                     |                                                      *
 * wind_sig_real       | real and imaginary parts of the windowed analysed    *
 * wind_sig_imag       | signal                                               *
 *                     |                                                      *
 * WIND_SIG_REAL       | matrix to store real and imaginary parts of the      *
 * WIND_SIG_IMAG       | signal windowed by the different analysis windows    *
 *                     |                                                      *
 *============================================================================*
 * 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
mmce (type_signal Signal,
      double *Window, int Window_Length, int Window_col,
      type_TFR tfr)

{
  int            Nfft, column, row, time;
  int            taumin, taumax, tau;
  int            half_Window_Length;
  double        *wind_sig_real, *wind_sig_imag; /* windowed signal */
  double        *WIND_SIG_REAL, *WIND_SIG_IMAG;
  double         normh, Nb_Window;
  int            i, j, hcol;
  double         WIN_ij, POW_Wind_sig, SUM_sig2, NORM_TFR, PROD_sig;
  char           STR[50];
 /*--------------------------------------------------------------------*/
 /*                      Test the input variables                      */
 /*--------------------------------------------------------------------*/


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

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

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

 /*--------------------------------------------------------------------*/
 /*                   checks that the window length is odd             */
 /*--------------------------------------------------------------------*/

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

    if (Window_col < 2)
    {
      printf ("mmce.c : The window must have at least 2 columns\n");
      exit(0);
    }

  half_Window_Length = (Window_Length - 1) / 2;

  /* Normalization of all Windows */
  for(j=0;j<Window_col;j++)
     {
      normh=0;
      for(i=0;i<Window_Length;i++)
         {
          WIN_ij = Window[idx(i,j,Window_Length)];
          normh = normh + ABS( WIN_ij*WIN_ij );
         }
      normh = sqrt(normh)+EPS;

      for(i=0;i<Window_Length;i++)
         {
          Window[idx(i,j,Window_Length)] = Window[idx(i,j,Window_Length)]/normh;
         }
     }

  Nb_Window = Window_col;
 /*--------------------------------------------------------------------*/
 /*           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           */
 /*--------------------------------------------------------------------*/
  wind_sig_real = (double *) ALLOC (tfr.N_freq, sizeof (double));
  wind_sig_imag = (double *) ALLOC (tfr.N_freq, sizeof (double));

  /* initialization of the intermediary vectors */
  for (row = 0; row < tfr.N_freq; row++)
	{
	  wind_sig_real[row] = 0.0;
	  wind_sig_imag[row] = 0.0;
   }


 WIND_SIG_REAL = (double *) ALLOC (tfr.N_freq*Window_col, sizeof (double));
 WIND_SIG_IMAG = (double *) ALLOC (tfr.N_freq*Window_col, sizeof (double));

  /* initialization of the intermediary vectors */
  for (row = 0; row < (tfr.N_freq*Window_col); row++)
	{
	  WIND_SIG_REAL[row] = 0.0;
	  WIND_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;


      /* the signal is multipied by the window between the instants
         time-taumin and time+taumax */
      /* when the window is wider than the number of desired frequencies (tfr.N_freq),
         the range is limited to tfr.N_freq */
      taumin = MIN (tfr.N_freq / 2, half_Window_Length);
      taumin = MIN (taumin, time);

      taumax = MIN ((tfr.N_freq / 2 - 1), half_Window_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 ) ;

       for ( hcol=0 ; hcol<Window_col ; hcol++ )
       {
        WIND_SIG_REAL[idx(row,hcol,tfr.N_freq)] = Signal.real_part[time + tau]
	                         * Window[idx((half_Window_Length + tau),hcol,Window_Length)];

        if (Signal.is_complex == TRUE)
        {
        WIND_SIG_IMAG[idx(row,hcol,tfr.N_freq)] = Signal.imag_part[time + tau]
                                   * Window[idx((half_Window_Length + tau),hcol,Window_Length)];
        }

        }
       }


       for ( hcol=0 ; hcol<Window_col ; hcol++ )
       {
        for (row = 0; row < tfr.N_freq; row++)
	      {
           wind_sig_real[row] = WIND_SIG_REAL[idx(row,hcol,tfr.N_freq)];
           wind_sig_imag[row] = WIND_SIG_IMAG[idx(row,hcol,tfr.N_freq)];
         }

          /* fft of the windowed signal */
         fft (tfr.N_freq, Nfft, wind_sig_real, wind_sig_imag);

         for (row = 0; row < tfr.N_freq; row++)
	      {
            WIND_SIG_REAL[idx(row,hcol,tfr.N_freq)] =
                                        ( wind_sig_real[row]*wind_sig_real[row]
                                        + wind_sig_imag[row]*wind_sig_imag[row]);
            WIND_SIG_IMAG[idx(row,hcol,tfr.N_freq)] = 0;
            /*wind_sig_real[row] = 0;
            wind_sig_imag[row] = 0;*/
         }

        }


        for (row = 0; row < tfr.N_freq; row++)
	     {
         PROD_sig = 1;
         for ( hcol=0 ; hcol<Window_col ; hcol++ )
         {
          PROD_sig = PROD_sig * WIND_SIG_REAL[idx(row,hcol,tfr.N_freq)];

          WIND_SIG_REAL[idx(row,hcol,tfr.N_freq)] = 0;
          WIND_SIG_IMAG[idx(row,hcol,tfr.N_freq)] = 0;
         }

         POW_Wind_sig = pow( PROD_sig,(1/Nb_Window));

         tfr.real_part[idx (row,column,tfr.N_freq)] = POW_Wind_sig;

         wind_sig_real[row] = 0.0;
	      wind_sig_imag[row] = 0.0;

        }



}
 /*--------------------------------------------------------------------*/
 /*                free the memory used in this program                */
 /*--------------------------------------------------------------------*/
  FREE (wind_sig_real);
  FREE (wind_sig_imag);
  FREE (WIND_SIG_REAL);
  FREE (WIND_SIG_IMAG);

 SUM_sig2 = 0;
 NORM_TFR = 0;
 for(column=0;column<tfr.N_time;column++)
    {
     time = ((int) tfr.time_instants[column]) - 1;
     if (Signal.is_complex == TRUE)
      {
      SUM_sig2 = SUM_sig2 + (Signal.real_part[time]*Signal.real_part[time]
                                 +Signal.imag_part[time]*Signal.imag_part[time]);
      }
      else
      {
      SUM_sig2 = SUM_sig2 + (Signal.real_part[time]*Signal.real_part[time]);
      }

     for(row=0; row<tfr.N_freq; row++)
       {
          NORM_TFR = NORM_TFR + tfr.real_part[idx (row,column,tfr.N_freq)];
       }
    }


  for(row=0; row<tfr.N_freq; row++)
     {
      for(column=0;column<tfr.N_time;column++)
         {
          tfr.real_part[idx (row,column,tfr.N_freq)] =  SUM_sig2/NORM_TFR
                         *tfr.real_part[idx (row,column,tfr.N_freq)];
          }
      }

}

⌨️ 快捷键说明

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