stft.c

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

C
216
字号
/* EXISTS AN INTERFACE PROGRAM TO MATLAB : STFTMEX.C		             *
 *====================================================================*
 * Name of the function : stft.c (void)                  	          *
 * Author               : Manuel DAVY - IRCyN                         *
 * Date of creation     : 10 - 02 - 1999                              *
 *--------------------------------------------------------------------*
 * THE ALGORITHM             				                               *
 *								                                              *
 * Given a signal to analyze in time and frequency, computes the      *
 * Short Time Fourier Transform (STFT) :			                      *
 *								                                              *
 *		            /            -j 2 pi f s			                   *
 *    STFT(t,f) = | x(s)h(t-s)e      	    ds			                *
 *		            /						                                  *
 *								                                              *
 * This function is complex valued. Its computation requires a window,*
 * its 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            |   Vector containing the points of the window   *
 * Window_Length     |   Number of points of the window (ODD number !)*
 *                   |          				                            *
 * tfr               |  Matrix containing the resulting TFR (complex) *
 * 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 TRUE (a stft is complex !)     *
 *--------------------------------------------------------------------*
 * OUTPUT VARIABLES    						                               *
 * Name              |                role                	          *
 * tfr.real_part     |  the output tfr matrix  (real_part)            *
 * tfr.imag_part     |  the output tfr matrix  (imag part)            *
 * norm_vector       |  Value of the normalization factor applied at  *
 *                   |  the points of computation of the stft i.e.    *
 *                   |  tfr.time_instants 			                   *
 *--------------------------------------------------------------------*
 * INTERNAL VARIABLES 						                               *
 * Name              |                 role                 	       *
 *                   |        				                            *
 *  Nfft             | Next power of two to tfr.N_freq                *
 *                   |               				                      *
 * column, line      |   variables of displacement in the matrices    *
 * tau               |   local time variable (the 's' in the equation *
 *                   |   above  				                            *
 * time              |   Current instant of computation of the spectro*
 * taumin            |   local time variable bounds. Used to take into*
 * taumax            |   accound the beginning and the end of the     *
 *                   |   signal, where the window is cut	             *
 * normh             |   current normalization value : depends on     *
 *                   |   wether the window is cut or not (near the    *
 *                   |   edges) 				                            *
 * wind_sig_real     |   Real and imaginary parts of the windowed     *
 * wind_sig_imag     |   signal at the current position of the window *
 * inter*            |   several intermediary variables		          *
 *====================================================================*
 * SUBROUTINES USED HERE				      	                         *
 *--------------------------------------------------------------------*
 * Name   | int idx(int line, int row, int nb_row)                    *
 * Action | computes the vector index for an element in a matrix given*
 *        | the line and column indices and the number of lines       *
 * 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
stft (type_signal Signal,
      double *Window, int Window_Length,
      type_TFR tfr, double *norm_vector)

{
  int            Mfft, Nfft, column, row, time;
  int            taumin, taumax, tau;
  int            half_Window_Length;
  double        *wind_sig_real, *wind_sig_imag;		/* windowed signal */
  double         inter_real, inter_imag, normh;
  double         inter;

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


   if (tfr.is_complex == FALSE)
    {
      printf ("stft.c : The tfr matrix must be complex valued\n");
      exit(0);
    }

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

  if (tfr.N_time <= 0)
    {
      printf ("stft.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 ("stft.c : The window Length must be an ODD number\n");
      exit(0);
    }

  half_Window_Length = (Window_Length - 1) / 2;
  inter = 0.0;
  for (row = 0; row <Window_Length; row++)
	 {
	  inter = inter + sqr (Window[row]);
	 }
  normh = sqrt (inter);
 /*--------------------------------------------------------------------*/
 /*           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));

 /*--------------------------------------------------------------------*/
 /*      computation of the fft for the current windowed signal        */
 /*--------------------------------------------------------------------*/
  for (column = 0; column < tfr.N_time; column++)
    {

      /* 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;
	}

      /* time instants of interest to compute the stft */
      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));

      /* Computation of a normalization factor, 
         equal to the quadratic norm of the window */


      norm_vector[column] = 1.0 / normh;
      /* The signal is windowed around the current time */
      for (tau = -taumin; tau <= taumax; tau++)
	{
	  row = irem( (tfr.N_freq+tau), tfr.N_freq ) ;
	  wind_sig_real[row] = Signal.real_part[time + tau]
	                     * Window[half_Window_Length + tau]
                             / normh;
	  if (Signal.is_complex == TRUE)
	    {
	      wind_sig_imag[row] = Signal.imag_part[time + tau]
                                 * Window[half_Window_Length + tau] 
                                 / normh;
	    }
	}

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


      /* the first half of the fft is put in the stft matrix  */
      for (row = 0; row < tfr.N_freq; row++)
	{
	  tfr.real_part[idx (row, column, tfr.N_freq)] = wind_sig_real[row];
	  tfr.imag_part[idx (row, column, tfr.N_freq)] = wind_sig_imag[row];

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

}

⌨️ 快捷键说明

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