Пример #1
0
void dft(double *jr, double *ji, int n, int iflag)
{
  fftw_plan plan;
  int i;
  double ninv;
  FFTW_COMPLEX *cbuf;
  static int wisdom_inited=0;
  char *ram_cache_wisdom;
  int plan_flags;

  if(!wisdom_inited)  {
    wisdom_inited=1;
    wisdom_file=getenv("GRACE_FFTW_WISDOM_FILE");
    ram_cache_wisdom=getenv("GRACE_FFTW_RAM_WISDOM");

    if(ram_cache_wisdom) sscanf(ram_cache_wisdom, "%d", &using_wisdom);
    /* turn on wisdom if it is requested even without persistent storage */

    if(wisdom_file && wisdom_file[0] ) {
      /* if a file was specified in GRACE_FFTW_WISDOM_FILE, try to read it */
      FILE *wf;
      fftw_status fstat;
      wf=fopen(wisdom_file,"r");
      if(wf) {
	fstat=fftw_import_wisdom_from_file(wf);
	fclose(wf);
	initial_wisdom=fftw_export_wisdom_to_string();
      } else initial_wisdom=0;
      atexit(save_wisdom);
      using_wisdom=1; /* if a file is specified, always use wisdom */
    }
  }

  plan_flags=using_wisdom? (FFTW_USE_WISDOM | FFTW_MEASURE) : FFTW_ESTIMATE;

  plan=fftw_create_plan(n, iflag?FFTW_BACKWARD:FFTW_FORWARD,
		   plan_flags | FFTW_IN_PLACE);
  cbuf=xcalloc(n, sizeof(*cbuf));
  if(!cbuf) return;
  for(i=0; i<n; i++) {
    cbuf[i].re=jr[i]; cbuf[i].im=ji[i];
  }
  fftw(plan, 1, cbuf, 1, 1, 0, 1, 1);
  fftw_destroy_plan(plan);

  if(!iflag) {
    ninv=1.0/n;
    for(i=0; i<n; i++) {
    jr[i]=cbuf[i].re*ninv; ji[i]=cbuf[i].im*ninv;
    }
  } else {
    for(i=0; i<n; i++) {
      jr[i]=cbuf[i].re; ji[i]=cbuf[i].im;
    }
  }

  XCFREE(cbuf);
  
}
Пример #2
0
void plan_fftw(
  Search_settings *sett, 
	Command_line_opts *opts,
	FFTW_plans *plans, 
	FFTW_arrays *fftw_arr, 
	Aux_arrays *aux_arr) {

  char hostname[512], wfilename[512];
  FILE *wisdom;

  /* Imports a "wisdom file" containing information 
   * (previous tests) about how to optimally compute Fourier 
   * transforms on a given machine. If wisdom file is not present, 
   * it will be created after the test (measure) runs 
   * of the fft_plans are performed below 
   * (see http://www.fftw.org/fftw3_doc/Wisdom.html)
   */ 

  fftw_init_threads();

  gethostname(hostname, 512);
  sprintf (wfilename, "wisdom-%s.dat", hostname);
  if((wisdom = fopen (wfilename, "r")) != NULL) {
    fftw_import_wisdom_from_file(wisdom);
    fclose (wisdom);
  }

  sett->Ninterp = sett->interpftpad*sett->nfft; 

  // array length (xa, xb) is max{fftpad*nfft, Ninterp}
  fftw_arr->arr_len = (sett->fftpad*sett->nfft > sett->Ninterp 
                    ? sett->fftpad*sett->nfft : sett->Ninterp);

  //  fftw_arr->xa = fftw_malloc(2*fftw_arr->arr_len*sizeof(fftw_complex));
  //fftw_arr->xb = fftw_arr->xa + fftw_arr->arr_len;
  fftw_arr->xa = fftw_malloc(fftw_arr->arr_len*sizeof(fftw_complex));
  fftw_arr->xb = fftw_malloc(fftw_arr->arr_len*sizeof(fftw_complex));

  sett->nfftf = sett->fftpad*sett->nfft;

  // Change FFTW_MEASURE to FFTW_PATIENT for more optimized plan
  // (takes more time to generate the wisdom file)
  plans->plan = fftw_plan_dft_1d(sett->nfftf, fftw_arr->xa, fftw_arr->xa, FFTW_FORWARD, FFTW_MEASURE);

  fftw_plan_with_nthreads(omp_get_max_threads());

  plans->pl_int = fftw_plan_dft_1d(sett->nfft, fftw_arr->xa, fftw_arr->xa, FFTW_FORWARD, FFTW_MEASURE);
	                             
  plans->pl_inv = fftw_plan_dft_1d(sett->Ninterp, fftw_arr->xa, fftw_arr->xa, FFTW_BACKWARD, FFTW_MEASURE);
	                             
  // Generates a wisdom FFT file if there is none
  if((wisdom = fopen(wfilename, "r")) == NULL) {
    wisdom = fopen(wfilename, "w");
    fftw_export_wisdom_to_file(wisdom);
  }

  fclose (wisdom);

} // end of FFT plans 
Пример #3
0
int
nrrdFFTWWisdomRead(FILE *file) {
  static const char me[]="nrrdFFTWWisdomRead";

  if (!(file)) {
    biffAddf(NRRD, "%s: given file NULL", me);
    return 1;
  }
  if (!fftw_import_wisdom_from_file(file)) {
    biffAddf(NRRD, "%s: trouble importing wisdom", me);
    return 1;
  }
  return 0;
}
Пример #4
0
/*--------------------------------------------------------------------------*/
long _fftwI (char *wisdom_file) /* import */
{
  FILE *fp;
  int stat;
  fp = fopen(wisdom_file, "r");
  if((fp = fopen(wisdom_file, "r"))==NULL) {
    printf("Error reading wisdom file\"%s\"\n",wisdom_file);
    fflush(stdout);
    exit(0);
  }
  stat= fftw_import_wisdom_from_file(fp);
  fclose(fp);
  return stat;
}
Пример #5
0
// see if we have wisdom already
static char *
obtain_wisdom( int *planflag ,
	       const int DIR , 
	       const char *type )
{
  *planflag = NOPLAN ;
  char *str = malloc( 256 * sizeof( char ) ) ;
  sprintf( str , "%s" , type ) ;
  if( DIR < 0 ) return str ;
#ifndef CONDOR_MODE
  FILE *wizzard ;
  size_t mu ;
  char prec_str[ 16 ] ; 
  *planflag = NOPLAN ; 
  #ifdef SINGLE_PREC
  sprintf( prec_str , "FLOAT" ) ;
  #else
  sprintf( prec_str , "DOUBLE" ) ;
  #endif
  // openmp'd wisdom
  #ifdef OMP_FFTW
  sprintf( str , "%s/Local/Wisdom/%s_%sOMPnt%d_SU%d_" , 
	   HAVE_PREFIX , prec_str , type , nthreads , NC ) ;
  #else
  sprintf( str , "%s/Local/Wisdom/%s_%sSU%d_" , 
	   HAVE_PREFIX , prec_str , type , NC ) ;
  #endif
  for( mu = 0 ; mu < DIR - 1 ; mu++ ) {
    sprintf( str , "%s%zux" , str , Latt.dims[ mu ] ) ;
  }
  sprintf( str , "%s%zu.wisdom" , str , Latt.dims[ DIR - 1 ] ) ;
  if( ( wizzard = fopen( str , "r" ) ) == NULL ) {
    fprintf( stdout , "\n[FFTW] No wisdom to be obtained here ... planning" ) ; 
  } else {
    fprintf( stdout , "\n[FFTW] Successful wisdom attained" ) ; 
    *planflag = fftw_import_wisdom_from_file( wizzard ) ; 
    fclose( wizzard ) ; 
  }
  // condor mode ifdef
#else
  fprintf( stdout , "[FFTW] Creating plan on CONDOR host" ) ; 
#endif
  return str ;
}
Пример #6
0
int
main (int argc, char* argv[])
{
#if defined(HAVE_FFTW) && defined(HAVE_GETENV)
  const char* const pszHome = getenv("HOME");
  char* pszWisdom = NULL;

  if (pszHome) {
    const char szFileBase[] = ".fftw3-wisdom";
    int nHome = strlen(pszHome);
    int nBase = strlen(szFileBase);
    int len = nHome + nBase + 1;
    pszWisdom = new char [ len + 1 ];
    strcpy (pszWisdom, pszHome);
    pszWisdom[nHome] = '/';
    strcpy(pszWisdom+nHome+1,szFileBase);
    pszWisdom[nHome+nBase+2] = 0;

    FILE *wisdom = fopen(pszWisdom,"r");
    if (wisdom) {
      fftw_import_wisdom_from_file(wisdom);
      fclose(wisdom);
    }
  }
#endif

  int retval = ctsimtext_main(argc, argv);

#if defined(HAVE_FFTW) && defined(HAVE_GETENV)
  if (pszWisdom) {
    FILE* wisdom = fopen(pszWisdom,"w+");
    if (wisdom) {
      fftw_export_wisdom_to_file(wisdom);
      fclose(wisdom);
      delete [] pszWisdom;
    }
  }
#endif

  return retval;
}
Пример #7
0
void CBlasMath::loadWisdom()
{
    // Older versions of fftw3 dont have the this method
//    int err = fftw_import_wisdom_from_filename(wisdomFileName.toLocal8Bit().constData());
//    if(err != 1)
//    {
//           qWarning(QString("fftw_import_wisdom_from_filename returned " + QString::number(err) +
//                            " while trying to read wisdoms from " + wisdomFileName).toLocal8Bit().constData());
//    }
    QFile file(wisdomFileName);
    if(file.exists())
    {
        qDebug() << "Loading wisdoms ...";
        if(!file.open(QIODevice::ReadOnly))
        {
            qWarning() << ("Error opening file " + wisdomFileName);
            return;
        }
        FILE *f = fdopen(file.handle(), "r");
        if (!f)
        {
            qDebug() << ("Error opening file " + wisdomFileName);
            return;
        }
        int err = fftw_import_wisdom_from_file(f);
        if(err != 1)
        {
            qWarning(QString("fftw_import_wisdom_from_filename returned " + QString::number(err) +
                              " while trying to read wisdoms from " + wisdomFileName).toLocal8Bit().constData());
        }
        if (fclose(f))
        {
            qWarning("Error closing file");
        }
    }
    else
    {
        qDebug() << "No wisdom file found";
    }
}
Пример #8
0
void setup_sht() {
    int nmaps = sht_nmaps;
    FILE *fd;
    printf("  Initializing (incl. FFTW plans)\n");
    /* Import FFTW plan if it exists */
    fd = fopen("fftw.wisdom", "r");
    if (fd != NULL) {
        fftw_import_wisdom_from_file(fd);
        fclose(fd);
    }

    sht_plan = wavemoth_plan_to_healpix(Nside, lmax, lmax, nmaps, N_threads, sht_input,
                                        sht_output, WAVEMOTH_MMAJOR, sht_flags,
                                        sht_resourcefile);
    checkf(sht_plan, "plan not created, nthreads=%d", N_threads);

    /* Export FFTW wisdom generated during planning */
    fd = fopen("fftw.wisdom", "w");
    if (fd != NULL) {
        fftw_export_wisdom_to_file(fd);
        fclose(fd);
    }
}
Пример #9
0
/****************************************************************************//**
 * \brief Load the wisdom from file and memorize its name in
 *
 * \param[in] fname The name of the wisdom file. Although this name is
 *   saved, the handled argument can be savely freed/modified afterwards.
 *   It is save to pass get_fftw_wisdom_name() as input (self-assignment).
 * \param[in] load If true, the wisdom is reloaded from the file. Otherwise
 *   its name is just remembered.
 * \return 1 in case of success, 0 otherwise. In case of failure,
 *   probably load was true, but the file contains invalid data.
 *   Or maybe (less likely), allocating memory for the copy of fname failed.
 *
 * For example you can set the name, and load it later be calling
 * \code
 * set_fftw_wisdom_name(name, 0);
 * ...
 * set_fftw_wisdom_name(get_fftw_wisdom_name(), 1);
 * \endcode
 *
 * These wisdom-functions are not thread save!
 *******************************************************************************/
int tom::fftw::set_wisdom_name(const char *fname, int load) {

    int res = 0;
    char *wisdom_filename_local = NULL;


    if (fname) {
        wisdom_filename_local = (char *)malloc(sizeof(char)*strlen(fname)+1);
        if (!wisdom_filename_local) {
            return 0;
        }
        strcpy(wisdom_filename_local, fname);
    }
    tom::fftw::clear_wisdom_name();
    if ((wisdom_filename=wisdom_filename_local) && load) { /* This assignment is intended :) */
        FILE *f = fopen(fname, "rb");
        if (f) {
            res = fftw_import_wisdom_from_file(f);
            fclose(f);
        }
    }
    return res;
}
Пример #10
0
static void init_wisdom(void)
{
    static int wisdom_inited = FALSE;
    
    if (!wisdom_inited)  {
        char *ram_cache_wisdom;
        
        wisdom_inited = TRUE;
        wisdom_file      = getenv("GRACE_FFTW_WISDOM_FILE");
        ram_cache_wisdom = getenv("GRACE_FFTW_RAM_WISDOM");

        if (ram_cache_wisdom) {
            sscanf(ram_cache_wisdom, "%d", &using_wisdom);
        }

        /* turn on wisdom if it is requested even without persistent storage */
        if (wisdom_file && wisdom_file[0] ) {
            /* if a file was specified in GRACE_FFTW_WISDOM_FILE, try to read it */
            FILE *wf;
            fftw_status fstat;
            
            wf = gapp_openr(gapp, wisdom_file, SOURCE_DISK);
            if (wf) {
	        fstat = fftw_import_wisdom_from_file(wf);
	        gapp_close(wf);
	        initial_wisdom = fftw_export_wisdom_to_string();
            } else {
                initial_wisdom = NULL;
            }
            
            atexit(save_wisdom);
            
            /* if a file is specified, always use wisdom */
            using_wisdom = TRUE;
        }
    }
}
Пример #11
0
int dfft_init(double **data, 
	      int *local_mesh_dim, int *local_mesh_margin, 
	      int* global_mesh_dim, double *global_mesh_off,
	      int *ks_pnum)
{
  int i,j;
  /* helpers */
  int mult[3];

  int n_grid[4][3]; /* The four node grids. */
  int my_pos[4][3]; /* The position of this_node in the node grids. */
  int *n_id[4];     /* linear node identity lists for the node grids. */
  int *n_pos[4];    /* positions of nodes in the node grids. */
  /* FFTW WISDOM stuff. */
  char wisdom_file_name[255];
  FILE *wisdom_file;
  int wisdom_status;

  FFT_TRACE(fprintf(stderr,"%d: dipolar dfft_init():\n",this_node));


  dfft.max_comm_size=0; dfft.max_mesh_size=0;
  for(i=0;i<4;i++) {
    n_id[i]  = (int *) malloc(1*n_nodes*sizeof(int));
    n_pos[i] = (int *) malloc(3*n_nodes*sizeof(int));
  }

  /* === node grids === */
  /* real space node grid (n_grid[0]) */
  for(i=0;i<3;i++) {
    n_grid[0][i] = node_grid[i];
    my_pos[0][i] = node_pos[i];
  }
  for(i=0;i<n_nodes;i++) {
    map_node_array(i,&(n_pos[0][3*i+0]));
    n_id[0][get_linear_index( n_pos[0][3*i+0],n_pos[0][3*i+1],n_pos[0][3*i+2], n_grid[0])] = i;
  }
    
  /* FFT node grids (n_grid[1 - 3]) */
  calc_2d_grid(n_nodes,n_grid[1]);
  /* resort n_grid[1] dimensions if necessary */
  dfft.plan[1].row_dir = map_3don2d_grid(n_grid[0], n_grid[1], mult);
  dfft.plan[0].n_permute = 0;
  for(i=1;i<4;i++) dfft.plan[i].n_permute = (dfft.plan[1].row_dir+i)%3;
  for(i=0;i<3;i++) {
    n_grid[2][i] = n_grid[1][(i+1)%3];
    n_grid[3][i] = n_grid[1][(i+2)%3];
  }
  dfft.plan[2].row_dir = (dfft.plan[1].row_dir-1)%3;
  dfft.plan[3].row_dir = (dfft.plan[1].row_dir-2)%3;



  /* === communication groups === */
  /* copy local mesh off real space charge assignment grid */
  for(i=0;i<3;i++) dfft.plan[0].new_mesh[i] = local_mesh_dim[i];
  for(i=1; i<4;i++) {
    dfft.plan[i].g_size=fft_find_comm_groups(n_grid[i-1], n_grid[i], n_id[i-1], n_id[i], 
					dfft.plan[i].group, n_pos[i], my_pos[i]);
    if(dfft.plan[i].g_size==-1) {
      /* try permutation */
      j = n_grid[i][(dfft.plan[i].row_dir+1)%3];
      n_grid[i][(dfft.plan[i].row_dir+1)%3] = n_grid[i][(dfft.plan[i].row_dir+2)%3];
      n_grid[i][(dfft.plan[i].row_dir+2)%3] = j;
      dfft.plan[i].g_size=fft_find_comm_groups(n_grid[i-1], n_grid[i], n_id[i-1], n_id[i], 
					  dfft.plan[i].group, n_pos[i], my_pos[i]);
      if(dfft.plan[i].g_size==-1) {
	fprintf(stderr,"%d: dipolar INTERNAL ERROR: fft_find_comm_groups error\n", this_node);
	errexit();
      }
    }

    dfft.plan[i].send_block = (int *)realloc(dfft.plan[i].send_block, 6*dfft.plan[i].g_size*sizeof(int));
    dfft.plan[i].send_size  = (int *)realloc(dfft.plan[i].send_size, 1*dfft.plan[i].g_size*sizeof(int));
    dfft.plan[i].recv_block = (int *)realloc(dfft.plan[i].recv_block, 6*dfft.plan[i].g_size*sizeof(int));
    dfft.plan[i].recv_size  = (int *)realloc(dfft.plan[i].recv_size, 1*dfft.plan[i].g_size*sizeof(int));

    dfft.plan[i].new_size = fft_calc_local_mesh(my_pos[i], n_grid[i], global_mesh_dim,
					   global_mesh_off, dfft.plan[i].new_mesh, 
					   dfft.plan[i].start);  
    permute_ifield(dfft.plan[i].new_mesh,3,-(dfft.plan[i].n_permute));
    permute_ifield(dfft.plan[i].start,3,-(dfft.plan[i].n_permute));
    dfft.plan[i].n_ffts = dfft.plan[i].new_mesh[0]*dfft.plan[i].new_mesh[1];

    /* === send/recv block specifications === */
    for(j=0; j<dfft.plan[i].g_size; j++) {
      int k, node;
      /* send block: this_node to comm-group-node i (identity: node) */
      node = dfft.plan[i].group[j];
      dfft.plan[i].send_size[j] 
	= fft_calc_send_block(my_pos[i-1], n_grid[i-1], &(n_pos[i][3*node]), n_grid[i],
			      global_mesh_dim, global_mesh_off, &(dfft.plan[i].send_block[6*j]));
      permute_ifield(&(dfft.plan[i].send_block[6*j]),3,-(dfft.plan[i-1].n_permute));
      permute_ifield(&(dfft.plan[i].send_block[6*j+3]),3,-(dfft.plan[i-1].n_permute));
      if(dfft.plan[i].send_size[j] > dfft.max_comm_size) 
	dfft.max_comm_size = dfft.plan[i].send_size[j];
      /* First plan send blocks have to be adjusted, since the CA grid
	 may have an additional margin outside the actual domain of the
	 node */
      if(i==1) {
	for(k=0;k<3;k++) 
	  dfft.plan[1].send_block[6*j+k  ] += local_mesh_margin[2*k];
      }
      /* recv block: this_node from comm-group-node i (identity: node) */
      dfft.plan[i].recv_size[j] 
	= fft_calc_send_block(my_pos[i], n_grid[i], &(n_pos[i-1][3*node]), n_grid[i-1],
			      global_mesh_dim, global_mesh_off,&(dfft.plan[i].recv_block[6*j]));
      permute_ifield(&(dfft.plan[i].recv_block[6*j]),3,-(dfft.plan[i].n_permute));
      permute_ifield(&(dfft.plan[i].recv_block[6*j+3]),3,-(dfft.plan[i].n_permute));
      if(dfft.plan[i].recv_size[j] > dfft.max_comm_size) 
	dfft.max_comm_size = dfft.plan[i].recv_size[j];
    }

    for(j=0;j<3;j++) dfft.plan[i].old_mesh[j] = dfft.plan[i-1].new_mesh[j];
    if(i==1) 
      dfft.plan[i].element = 1; 
    else {
      dfft.plan[i].element = 2;
      for(j=0; j<dfft.plan[i].g_size; j++) {
	dfft.plan[i].send_size[j] *= 2;
	dfft.plan[i].recv_size[j] *= 2;
      }
    }
    /* DEBUG */
    for(j=0;j<n_nodes;j++) {
      /* MPI_Barrier(comm_cart); */
      if(j==this_node) FFT_TRACE(fft_print_fft_plan(dfft.plan[i]));
    }
  }

  /* Factor 2 for complex fields */
  dfft.max_comm_size *= 2;
  dfft.max_mesh_size = (local_mesh_dim[0]*local_mesh_dim[1]*local_mesh_dim[2]);
  for(i=1;i<4;i++) 
    if(2*dfft.plan[i].new_size > dfft.max_mesh_size) dfft.max_mesh_size = 2*dfft.plan[i].new_size;

  FFT_TRACE(fprintf(stderr,"%d: dfft.max_comm_size = %d, dfft.max_mesh_size = %d\n",
		    this_node,dfft.max_comm_size,dfft.max_mesh_size));

  /* === pack function === */
  for(i=1;i<4;i++) {
    dfft.plan[i].pack_function = fft_pack_block_permute2; 
    FFT_TRACE(fprintf(stderr,"%d: forw plan[%d] permute 2 \n",this_node,i));
  }
  (*ks_pnum)=6;
  if(dfft.plan[1].row_dir==2) {
    dfft.plan[1].pack_function = fft_pack_block;
    FFT_TRACE(fprintf(stderr,"%d: forw plan[%d] permute 0 \n",this_node,1));
    (*ks_pnum)=4;
  }
  else if(dfft.plan[1].row_dir==1) {
    dfft.plan[1].pack_function = fft_pack_block_permute1;
    FFT_TRACE(fprintf(stderr,"%d: forw plan[%d] permute 1 \n",this_node,1));
    (*ks_pnum)=5;
  }
  
  /* Factor 2 for complex numbers */
  dfft.send_buf = (double *)realloc(dfft.send_buf, dfft.max_comm_size*sizeof(double));
  dfft.recv_buf = (double *)realloc(dfft.recv_buf, dfft.max_comm_size*sizeof(double));
  (*data)  = (double *)realloc((*data), dfft.max_mesh_size*sizeof(double));
  dfft.data_buf = (double *)realloc(dfft.data_buf, dfft.max_mesh_size*sizeof(double));
  if(!(*data) || !dfft.data_buf || !dfft.recv_buf || !dfft.send_buf) {
    fprintf(stderr,"%d: Could not allocate FFT data arays\n",this_node);
    errexit();
  }

  fftw_complex *c_data     = (fftw_complex *) (*data);

  /* === FFT Routines (Using FFTW / RFFTW package)=== */
  for(i=1;i<4;i++) {
    dfft.plan[i].dir = FFTW_FORWARD;   
    /* FFT plan creation. 
       Attention: destroys contents of c_data/data and c_data_buf/data_buf. */
    wisdom_status   = FFTW_FAILURE;
    sprintf(wisdom_file_name,"dfftw3_1d_wisdom_forw_n%d.file",
	    dfft.plan[i].new_mesh[2]);
    if( (wisdom_file=fopen(wisdom_file_name,"r"))!=NULL ) {
      wisdom_status = fftw_import_wisdom_from_file(wisdom_file);
      fclose(wisdom_file);
    }
    if(dfft.init_tag==1) fftw_destroy_plan(dfft.plan[i].our_fftw_plan);
//printf("dfft.plan[%d].n_ffts=%d\n",i,dfft.plan[i].n_ffts);
    dfft.plan[i].our_fftw_plan =
      fftw_plan_many_dft(1,&dfft.plan[i].new_mesh[2],dfft.plan[i].n_ffts,
                         c_data,NULL,1,dfft.plan[i].new_mesh[2],
                         c_data,NULL,1,dfft.plan[i].new_mesh[2],
                         dfft.plan[i].dir,FFTW_PATIENT);
    if( wisdom_status == FFTW_FAILURE && 
	(wisdom_file=fopen(wisdom_file_name,"w"))!=NULL ) {
      fftw_export_wisdom_to_file(wisdom_file);
      fclose(wisdom_file);
    }
    dfft.plan[i].fft_function = fftw_execute;        
  }

  /* === The BACK Direction === */
  /* this is needed because slightly different functions are used */
  for(i=1;i<4;i++) {
    dfft.back[i].dir = FFTW_BACKWARD;
    wisdom_status   = FFTW_FAILURE;
    sprintf(wisdom_file_name,"dfftw3_1d_wisdom_back_n%d.file",
	    dfft.plan[i].new_mesh[2]);
    if( (wisdom_file=fopen(wisdom_file_name,"r"))!=NULL ) {
      wisdom_status = fftw_import_wisdom_from_file(wisdom_file);
      fclose(wisdom_file);
    }    
    if(dfft.init_tag==1) fftw_destroy_plan(dfft.back[i].our_fftw_plan);
    dfft.back[i].our_fftw_plan =
      fftw_plan_many_dft(1,&dfft.plan[i].new_mesh[2],dfft.plan[i].n_ffts,
                         c_data,NULL,1,dfft.plan[i].new_mesh[2],
                         c_data,NULL,1,dfft.plan[i].new_mesh[2],
                         dfft.back[i].dir,FFTW_PATIENT);
    if( wisdom_status == FFTW_FAILURE && 
	(wisdom_file=fopen(wisdom_file_name,"w"))!=NULL ) {
      fftw_export_wisdom_to_file(wisdom_file);
      fclose(wisdom_file);
    }
    dfft.back[i].fft_function = fftw_execute;
    dfft.back[i].pack_function = fft_pack_block_permute1;
    FFT_TRACE(fprintf(stderr,"%d: back plan[%d] permute 1 \n",this_node,i));
  }
  if(dfft.plan[1].row_dir==2) {
    dfft.back[1].pack_function = fft_pack_block;
    FFT_TRACE(fprintf(stderr,"%d: back plan[%d] permute 0 \n",this_node,1));
  }
  else if(dfft.plan[1].row_dir==1) {
    dfft.back[1].pack_function = fft_pack_block_permute2;
    FFT_TRACE(fprintf(stderr,"%d: back plan[%d] permute 2 \n",this_node,1));
  }
  dfft.init_tag=1;
  /* free(data); */
  for(i=0;i<4;i++) { free(n_id[i]); free(n_pos[i]); }
  return dfft.max_mesh_size; 
}
Пример #12
0
Файл: tracker.c Проект: bion/ats
/* ATS_SOUND *tracker (ANARGS *anargs, char *soundfile)
 * partial tracking function 
 * anargs: pointer to analysis parameters
 * soundfile: path to input file 
 * returns an ATS_SOUND with data issued from analysis
 */
ATS_SOUND *tracker (ANARGS *anargs, char *soundfile, char *resfile)
{
  int fd, M_2, first_point, filptr, n_partials = 0;
  int frame_n, k, sflen, *win_samps, peaks_size, tracks_size = 0;
  int i, frame, i_tmp;
  float *window, norm, sfdur, f_tmp;
  /* declare structures and buffers */
  ATS_SOUND *sound = NULL;
  ATS_PEAK *peaks, *tracks = NULL, cpy_peak;
  ATS_FRAME *ana_frames = NULL, *unmatched_peaks = NULL;
  mus_sample_t **bufs;
  ATS_FFT fft;
#ifdef FFTW
  fftw_plan plan;
  FILE *fftw_wisdom_file;
#endif

  /* open input file
     we get srate and total_samps in file in anargs */
  if ((fd = mus_sound_open_input(soundfile))== -1) {
    fprintf(stderr, "%s: %s\n", soundfile, strerror(errno));
    return(NULL);
  }
  /* warn about multi-channel sound files */
  if (mus_sound_chans(soundfile) > 1) {
    fprintf(stderr, "Error: file has %d channels, must be mono!\n",
	    mus_sound_chans(soundfile));
    return(NULL);
  }

  fprintf(stderr, "tracking...\n");

  /* get sample rate and # of frames from file header */
  anargs->srate = mus_sound_srate(soundfile);
  sflen = mus_sound_frames(soundfile);
  sfdur = (float)sflen/anargs->srate;
  /* check analysis parameters */
  /* check start time */
  if( !(anargs->start >= 0.0 && anargs->start < sfdur) ){
    fprintf(stderr, "Warning: start %f out of bounds, corrected to 0.0\n", anargs->start);
    anargs->start = (float)0.0;
  }
  /* check duration */
  if(anargs->duration == ATSA_DUR) {
    anargs->duration = sfdur - anargs->start;
  }
  f_tmp = anargs->duration + anargs->start;
  if( !(anargs->duration > 0.0 && f_tmp <= sfdur) ){
    fprintf(stderr, "Warning: duration %f out of bounds, limited to file duration\n", anargs->duration);
    anargs->duration = sfdur - anargs->start;
  }
  /* print time bounds */
  fprintf(stderr, "start: %f duration: %f file dur: %f\n", anargs->start, anargs->duration , sfdur);
  /* check lowest frequency */
  if( !(anargs->lowest_freq > 0.0 && anargs->lowest_freq < anargs->highest_freq)){
    fprintf(stderr, "Warning: lowest freq. %f out of bounds, forced to default: %f\n", anargs->lowest_freq, ATSA_LFREQ);
    anargs->lowest_freq = ATSA_LFREQ;
  }
  /* check highest frequency */
  if( !(anargs->highest_freq > anargs->lowest_freq && anargs->highest_freq <= anargs->srate * 0.5 )){
    fprintf(stderr, "Warning: highest freq. %f out of bounds, forced to default: %f\n", anargs->highest_freq, ATSA_HFREQ);
    anargs->highest_freq = ATSA_HFREQ;
  }
  /* frequency deviation */
  if( !(anargs->freq_dev > 0.0 && anargs->freq_dev < 1.0) ){
    fprintf(stderr, "Warning: freq. dev. %f out of bounds, should be > 0.0 and <= 1.0,  forced to default: %f\n", anargs->freq_dev, ATSA_FREQDEV);
    anargs->freq_dev = ATSA_FREQDEV;
  }
  /* window cycles */
  if( !(anargs->win_cycles >= 1 && anargs->win_cycles <= 8) ){
    fprintf(stderr, "Warning: windows cycles %d out of bounds, should be between 1 and 8, forced to default: %d\n", anargs->win_cycles, ATSA_WCYCLES);
    anargs->win_cycles = ATSA_WCYCLES;
  }
  /* window type */
  if( !(anargs->win_type >= 0 && anargs->win_type <= 3) ){
    fprintf(stderr, "Warning: window type %d out of bounds, should be between 0 and 3, forced to default: %d\n", anargs->win_type, ATSA_WTYPE);
    anargs->win_type = ATSA_WTYPE;
  }
  /* hop size */
  if( !(anargs->hop_size > 0.0 && anargs->hop_size <= 1.0) ){
    fprintf(stderr, "Warning: hop size %f out of bounds, should be > 0.0 and <= 1.0, forced to default: %f\n", anargs->hop_size, ATSA_HSIZE);
    anargs->hop_size = ATSA_HSIZE;
  }
  /* lowest mag */
  if( !(anargs->lowest_mag <= 0.0) ){
    fprintf(stderr, "Warning: lowest magnitude %f out of bounds, should be >= 0.0 and <= 1.0, forced to default: %f\n", anargs->lowest_mag, ATSA_LMAG);
    anargs->lowest_mag = ATSA_LMAG;
  }
  /* set some values before checking next set of parameters */
  anargs->first_smp = (int)floor(anargs->start * (float)anargs->srate);
  anargs->total_samps = (int)floor(anargs->duration * (float)anargs->srate);
  /* fundamental cycles */
  anargs->cycle_smp = (int)floor((double)anargs->win_cycles * (double)anargs->srate / (double)anargs->lowest_freq);
  /* window size */
  anargs->win_size = (anargs->cycle_smp % 2 == 0) ? anargs->cycle_smp+1 : anargs->cycle_smp;
  /* calculate hop samples */
  anargs->hop_smp = floor( (float)anargs->win_size * anargs->hop_size );
  /* compute total number of frames */
  anargs->frames = compute_frames(anargs);
  /* check that we have enough frames for the analysis */
  if( !(anargs->frames >= ATSA_MFRAMES) ){
    fprintf(stderr, "Error: %d frames are not enough for analysis, nead at least %d\n", anargs->frames , ATSA_MFRAMES);
    return(NULL);
  }
  /* check other user parameters */
  /* track length */
  if( !(anargs->track_len >= 1 && anargs->track_len < anargs->frames) ){
    i_tmp = (ATSA_TRKLEN < anargs->frames) ? ATSA_TRKLEN : anargs->frames-1;
    fprintf(stderr, "Warning: track length %d out of bounds, forced to: %d\n", anargs->track_len , i_tmp);
    anargs->track_len = i_tmp;
  }    
  /* min. segment length */
  if( !(anargs->min_seg_len >= 1 && anargs->min_seg_len < anargs->frames) ){
    i_tmp = (ATSA_MSEGLEN < anargs->frames) ? ATSA_MSEGLEN : anargs->frames-1;
    fprintf(stderr, "Warning: min. segment length %d out of bounds, forced to: %d\n", anargs->min_seg_len, i_tmp);
    anargs->min_seg_len = i_tmp;
  }
  /* min. gap length */
  if( !(anargs->min_gap_len >= 0 && anargs->min_gap_len < anargs->frames) ){
    i_tmp = (ATSA_MGAPLEN < anargs->frames) ? ATSA_MGAPLEN : anargs->frames-1;
    fprintf(stderr, "Warning: min. gap length %d out of bounds, forced to: %d\n", anargs->min_gap_len, i_tmp);
    anargs->min_gap_len = i_tmp;
  }
  /* SMR threshold */
  if( !(anargs->SMR_thres >= 0.0 && anargs->SMR_thres < ATSA_MAX_DB_SPL) ){
    fprintf(stderr, "Warning: SMR threshold %f out of bounds, shoul be >= 0.0 and < %f dB SPL, forced to default: %f\n", anargs->SMR_thres, ATSA_MAX_DB_SPL, ATSA_SMRTHRES);
    anargs->SMR_thres = ATSA_SMRTHRES;
  }
  /* min. seg. SMR */
  if( !(anargs->min_seg_SMR >= anargs->SMR_thres && anargs->min_seg_SMR < ATSA_MAX_DB_SPL) ){
    fprintf(stderr, "Warning: min. seg. SMR  %f out of bounds, shoul be >= %f and < %f dB SPL, forced to default: %f\n", anargs->min_seg_SMR, anargs->SMR_thres, ATSA_MAX_DB_SPL, ATSA_MSEGSMR);
    anargs->min_seg_SMR = ATSA_MSEGSMR;
  }
  /* last peak contibution */
  if( !(anargs->last_peak_cont >= 0.0 && anargs->last_peak_cont <= 1.0) ){
    fprintf(stderr, "Warning: last peak contibution %f out of bounds, should be >= 0.0 and <= 1.0, forced to default: %f\n", anargs->last_peak_cont, ATSA_LPKCONT);
    anargs->last_peak_cont = ATSA_LPKCONT;
  }
  /* SMR cont. */
  if( !(anargs->SMR_cont >= 0.0 && anargs->SMR_cont <= 1.0) ){
    fprintf(stderr, "Warning: SMR contibution %f out of bounds, should be >= 0.0 and <= 1.0, forced to default: %f\n", anargs->SMR_cont, ATSA_SMRCONT);
    anargs->SMR_cont = ATSA_SMRCONT;
  }
  /* continue computing parameters */
  /* fft size */
  anargs->fft_size = ppp2(2*anargs->win_size);

  /* allocate memory for sound, we read the whole sound in memory */
  bufs = (mus_sample_t **)malloc(sizeof(mus_sample_t*));
  bufs[0] = (mus_sample_t *)malloc(sflen * sizeof(mus_sample_t));
  /*  bufs = malloc(sizeof(mus_sample_t*));
      bufs[0] = malloc(sflen * sizeof(mus_sample_t)); */
  /* make our window */
  window = make_window(anargs->win_type, anargs->win_size);
  /* get window norm */
  norm = window_norm(window, anargs->win_size);
  /* fft mag for computing frequencies */
  anargs->fft_mag = (double)anargs->srate / (double)anargs->fft_size;
  /* lowest fft bin for analysis */
  anargs->lowest_bin = floor( anargs->lowest_freq / anargs->fft_mag );
  /* highest fft bin for analisis */
  anargs->highest_bin = floor( anargs->highest_freq / anargs->fft_mag );
  /* allocate an array analysis frames in memory */
  ana_frames = (ATS_FRAME *)malloc(anargs->frames * sizeof(ATS_FRAME));
  /* alocate memory to store mid-point window sample numbers */
  win_samps = (int *)malloc(anargs->frames * sizeof(int));
  /* center point of window */
  M_2 = floor((anargs->win_size - 1) / 2); 
  /* first point in fft buffer to write */
  first_point = anargs->fft_size - M_2;  
  /* half a window from first sample */
  filptr = anargs->first_smp - M_2;   
  /* read sound into memory */
  mus_sound_read(fd, 0, sflen-1, 1, bufs);     

  /* make our fft-struct */
  fft.size = anargs->fft_size;
  fft.rate = anargs->srate;
#ifdef FFTW
  fft.data = fftw_malloc(sizeof(fftw_complex) * fft.size);
  if(fftw_import_system_wisdom()) fprintf(stderr, "system wisdom loaded!\n");
  else fprintf(stderr, "cannot locate system wisdom!\n");
  if((fftw_wisdom_file = fopen("ats-wisdom", "r")) != NULL) {
    fftw_import_wisdom_from_file(fftw_wisdom_file);
    fprintf(stderr, "ats-wisdom loaded!\n");
    fclose(fftw_wisdom_file);
  } else fprintf(stderr, "cannot locate ats-wisdom!\n");
  plan = fftw_plan_dft_1d(fft.size, fft.data, fft.data, FFTW_FORWARD, FFTW_PATIENT);
#else
  fft.fdr = (double *)malloc(anargs->fft_size * sizeof(double));
  fft.fdi = (double *)malloc(anargs->fft_size * sizeof(double));
#endif

  /* main loop */
  for (frame_n=0; frame_n<anargs->frames; frame_n++) {
    /* clear fft arrays */
#ifdef FFTW
    for(k=0; k<fft.size; k++) fft.data[k][0] = fft.data[k][1] = 0.0f;
#else
    for(k=0; k<fft.size; k++) fft.fdr[k] = fft.fdi[k] = 0.0f;
#endif
    /* multiply by window */
    for (k=0; k<anargs->win_size; k++) {
      if ((filptr >= 0) && (filptr < sflen)) 
#ifdef FFTW
        fft.data[(k+first_point)%fft.size][0] = window[k] * MUS_SAMPLE_TO_FLOAT(bufs[0][filptr]);
#else
        fft.fdr[(k+first_point)%anargs->fft_size] = window[k] * MUS_SAMPLE_TO_FLOAT(bufs[0][filptr]);
#endif
      filptr++;
    }
    /* we keep sample numbers of window midpoints in win_samps array */
    win_samps[frame_n] = filptr - M_2 - 1;
    /* move file pointer back */
    filptr = filptr - anargs->win_size + anargs->hop_smp;
    /* take the fft */
#ifdef FFTW
    fftw_execute(plan);
#else
    fft_slow(fft.fdr, fft.fdi, fft.size, 1);
#endif
    /* peak detection */
    peaks_size = 0;
    peaks = peak_detection(&fft, anargs->lowest_bin, anargs->highest_bin, anargs->lowest_mag, norm, &peaks_size); 
    /* peak tracking */
    if (peaks != NULL) {
      /* evaluate peaks SMR (masking curves) */
      evaluate_smr(peaks, peaks_size);
      if (frame_n) {
	/* initialize or update tracks */
	if ((tracks = update_tracks(tracks, &tracks_size, anargs->track_len, frame_n, ana_frames, anargs->last_peak_cont)) != NULL) {
	  /* do peak matching */
          unmatched_peaks = peak_tracking(tracks, &tracks_size, peaks, &peaks_size,  anargs->freq_dev, 2.0 * anargs->SMR_cont, &n_partials);
	  /* kill unmatched peaks from previous frame */
          if(unmatched_peaks[0].peaks != NULL) {
	    for(k=0; k<unmatched_peaks[0].n_peaks; k++) {
	      cpy_peak = unmatched_peaks[0].peaks[k];
	      cpy_peak.amp = cpy_peak.smr = 0.0;
	      peaks = push_peak(&cpy_peak, peaks, &peaks_size);
             }
             free(unmatched_peaks[0].peaks);
           }
           /* give birth to peaks from new frame */
           if(unmatched_peaks[1].peaks != NULL) {
             for(k=0; k<unmatched_peaks[1].n_peaks; k++) {
               tracks = push_peak(&unmatched_peaks[1].peaks[k], tracks, &tracks_size);
               unmatched_peaks[1].peaks[k].amp = unmatched_peaks[1].peaks[k].smr = 0.0;
               ana_frames[frame_n-1].peaks = push_peak(&unmatched_peaks[1].peaks[k], ana_frames[frame_n-1].peaks, &ana_frames[frame_n-1].n_peaks);
             }
             free(unmatched_peaks[1].peaks);
           }
         } else {
           /* give number to all peaks */
           qsort(peaks, peaks_size, sizeof(ATS_PEAK), peak_frq_inc);
           for(k=0; k<peaks_size; k++) peaks[k].track = n_partials++;
         }
      } else {
        /* give number to all peaks */
        qsort(peaks, peaks_size, sizeof(ATS_PEAK), peak_frq_inc);
        for(k=0; k<peaks_size; k++) peaks[k].track = n_partials++;
      }
      /* attach peaks to ana_frames */
      ana_frames[frame_n].peaks = peaks;
      ana_frames[frame_n].n_peaks = n_partials;
      ana_frames[frame_n].time = (double)(win_samps[frame_n] - anargs->first_smp) / (double)anargs->srate;
      /* free memory */
      free(unmatched_peaks);
    } else {
      /* if no peaks found, initialize empty frame */
      ana_frames[frame_n].peaks = NULL;
      ana_frames[frame_n].n_peaks = 0;
      ana_frames[frame_n].time = (double)(win_samps[frame_n] - anargs->first_smp) / (double)anargs->srate;
    }
  }
  /* free up some memory */
  free(window);
  free(tracks);
#ifdef FFTW
  fftw_destroy_plan(plan);
  fftw_free(fft.data);
#else
  free(fft.fdr);
  free(fft.fdi);
#endif
  /* init sound */
  fprintf(stderr, "Initializing ATS data...");
  sound = (ATS_SOUND *)malloc(sizeof(ATS_SOUND));
  init_sound(sound, anargs->srate, (int)(anargs->hop_size * anargs->win_size), 
             anargs->win_size, anargs->frames, anargs->duration, n_partials,
             ((anargs->type == 3 || anargs->type == 4) ? 1 : 0));
  /* store values from frames into the arrays */
  for(k=0; k<n_partials; k++) {
    for(frame=0; frame<sound->frames; frame++) {
      sound->time[k][frame] = ana_frames[frame].time;
      for(i=0; i<ana_frames[frame].n_peaks; i++) 
        if(ana_frames[frame].peaks[i].track == k) {
	  sound->amp[k][frame] = ana_frames[frame].peaks[i].amp;
          sound->frq[k][frame] = ana_frames[frame].peaks[i].frq;
          sound->pha[k][frame] = ana_frames[frame].peaks[i].pha;
          sound->smr[k][frame] = ana_frames[frame].peaks[i].smr;
        }
    }
  }
  fprintf(stderr, "done!\n");
  /* free up ana_frames memory */
  /* first, free all peaks in each slot of ana_frames... */
  for (k=0; k<anargs->frames; k++) free(ana_frames[k].peaks);  
  /* ...then free ana_frames */
  free(ana_frames);                                            
  /* optimize sound */
  optimize_sound(anargs, sound);
  /* compute  residual */
  if( anargs->type == 3 || anargs->type == 4 ) {
    fprintf(stderr, "Computing residual...");
    compute_residual(bufs, sflen, resfile, sound, win_samps, anargs->srate);
    fprintf(stderr, "done!\n");
  }
  /* free the rest of the memory */
  free(win_samps);
  free(bufs[0]);
  free(bufs);
  /* analyze residual */
  if( anargs->type == 3 || anargs->type == 4 ) {
    fprintf(stderr, "Analyzing residual...");
    residual_analysis(ATSA_RES_FILE, sound);
    fprintf(stderr, "done!\n");
  }
#ifdef FFTW
  fftw_wisdom_file = fopen("ats-wisdom", "w");
  fftw_export_wisdom_to_file(fftw_wisdom_file);
  fclose(fftw_wisdom_file);
#endif
  fprintf(stderr, "tracking completed.\n");
  return(sound);
}
Пример #13
0
/**
 * Main function
 *
 * Reads command line specifying input and output files, and optionally wisdom file,
 * measure level, and flag preventing import of system wide wisdom, and then creates
 * plans for each problem specified in the input file.  Accumulated wisdom is written
 * to the output file, and a human readable description of the plans successfully
 * created is written to stdout.  Any warnings or errors are written to stderr.
 */
int main(int argc, char **argv)
{
  static int measurelvl=3;
  static int nosys=0;
  UINT4 transform_size;
  char input_line[LINE_MAX];
  char type;
  char direc;
  FILE *infp=NULL, *outfp=NULL, *wisfp=NULL;
  int optindex, optreturn, retval;

  static struct LALoption long_options[] =
    {
      /* Options setting flags */
      {"no-system-wisdom",no_argument,&nosys,1},
      /* Options specifying input/output  */
      {"input",required_argument,NULL,'i'},
      {"output",required_argument,NULL,'o'},
      {"wisdom",required_argument,NULL,'w'},
      {"measurelvl",required_argument,NULL,'l'},
      {"help",no_argument,NULL,'h'},
      {0,0,0,0}
    };

  while ( (optreturn = LALgetopt_long(argc,argv,"ni:o:w:l:h",long_options,&optindex)) != -1)
    {
      switch(optreturn)
	{
	case 0:
	  break;  /* Everything done in setting flag */
	case 'n':
	  nosys=1;
	  break;
	case 'i':
	  infp = LALFopen(LALoptarg,"r+");
	  if (!infp)
	    {
	      fprintf(stderr,"Error: Could not open input file %s\n",LALoptarg);
	      if (outfp) LALFclose(outfp);
	      exit(EXIT_FAILURE);
	    }
	  break;
	case 'o':
	  outfp = LALFopen(LALoptarg,"w+");
	  if (!outfp)
	    {
	      fprintf(stderr,"Error: Could not open output file %s\n",LALoptarg);
	      if (infp) LALFclose(infp);
	      exit(EXIT_FAILURE);
	    }
	  break;
	case 'w':
	  wisfp = LALFopen(LALoptarg,"r+");
	  if (!wisfp)
	    {
	      fprintf(stderr,"Error: Could not open input wisdom file %s for reading\n",LALoptarg);
	      if (infp)  LALFclose(infp);
	      if (outfp) LALFclose(outfp);
	      exit(EXIT_FAILURE);
	    }
	  else
	    {
	      retval = fftw_import_wisdom_from_file(wisfp);
	      if (!retval)
		{
		  /* Retval is zero if UNsuccessful */
		  fprintf(stderr,"Error: Could not read wisdom from input wisdom file %s\n",LALoptarg);
		  if (infp)  LALFclose(infp);
		  if (outfp) LALFclose(outfp);
		  LALFclose(wisfp);
		  exit(EXIT_FAILURE);
		}
	      LALFclose(wisfp);
	    }
	  fprintf(stderr,"Read in existing wisdom from file %s\n",LALoptarg);
	  break;
	case 'l':
	  if ( sscanf(LALoptarg,"%d",&measurelvl) != 1)
	    {
	      fprintf(stderr,"Error: invalid measure level %s.\n",LALoptarg);
	      if (infp)  LALFclose(infp);
	      if (outfp) LALFclose(outfp);
	      exit(EXIT_FAILURE);
	    }
	  if ( (measurelvl<0) || (measurelvl>3) )
	    {
	      fprintf(stderr,"Error: invalid measure level %d.\n",measurelvl);
	      if (infp)  LALFclose(infp);
	      if (outfp) LALFclose(outfp);
	    }
	  break;
	case 'h': /* Fall through */
	case '?':
	  print_help();
	  break;
	default:
	  exit(EXIT_FAILURE);
	} /* switch(optreturn) */
    } /* while(optreturn != -1) */

  /* Check to make sure mandatory options were given */

  if (!infp)
    {
      fprintf(stderr,"Error: You must specify an input file with -i <FILE> or --input=<FILE>\n");
      if (outfp) LALFclose(outfp);
      exit(EXIT_FAILURE);
    }

  if (!outfp)
    {
      fprintf(stderr,"Error: You must specify an output file with -o <FILE> or --output=<FILE>\n");
      if (infp) LALFclose(infp);
      exit(EXIT_FAILURE);
    }

  /* Only after processing all options do we know if we should read in system wisdom file */

  if (!nosys)
    {
      retval = fftw_import_system_wisdom();
      if (!retval)
	{
	  /* Retval is zero if UNsuccessful */
	  fprintf(stderr,"Warning: Could not import system wisdom file /etc/fftw/wisdom\n");
	}
    }
  else
    {
      fprintf(stderr,"Skipped import of system wisdom file /etc/fftw/wisdom\n");
    }


  /* Process the input file */

  while ( (fgets(input_line,LINE_MAX,infp) != NULL) )
    {
      if (sscanf(input_line,"%c%c%" LAL_UINT4_FORMAT, &type, &direc, &transform_size) == 3)
	{
	  /* Yes, it's ugly, but we don't have to worry about locales: */
	  if ( !( (type=='r') || (type=='R') || (type=='c') || (type=='C') ) )
	    {
	      fprintf(stderr,"Error: Invalid type specifier %c; must be 'r' (real) or 'c' (complex). ",type);
	      fprintf(stderr,"Problem %c%c%" LAL_UINT4_FORMAT " will be skipped!\n", type, direc, transform_size);
	    }
	  else if ( !( (direc=='f') || (direc=='b') || (direc=='r') || (direc=='F') || (direc=='B') || (direc=='R') ) )
	    {
	      fprintf(stderr,"Error: Invalid direction specifier %c; must be 'f' (forward) or 'b'/'r' (backward/reverse). ",
		      direc);
	      fprintf(stderr,"Problem %c%c%" LAL_UINT4_FORMAT " will be skipped!\n",type,direc,transform_size);
	    }
	  else
	    {
	      retval = plan_problem(type,direc,transform_size,measurelvl);
	      if (retval)
		{
		  fprintf(stderr,"Unable to create plan %c%c%" LAL_UINT4_FORMAT "; skipping!\n",
			  type,direc,transform_size);
		}
	      else
		{
		  fprintf(stdout,"Created double-precision %s %s plan, size %" LAL_UINT4_FORMAT
			  " with measure level %d and FFTW_UNALIGNED\n",
			  ( (type=='r') || (type=='R') ) ? "REAL4" : "COMPLEX8",
			  ( (direc=='f') || (direc=='F') ) ? "forward" : "reverse",
			  transform_size, measurelvl);
		}
	    }
	}
      else
	{
	  fprintf(stderr,"Error: Invalid problem specifier. Problem: %s will be skipped\n",input_line);
	}
    }

  fftw_export_wisdom_to_file(outfp);
  LALFclose(infp);
  LALFclose(outfp);

  exit(EXIT_SUCCESS);
}
Пример #14
0
/*
void fft_2k_test(  fftw_complex *out )
{
    memset(fftw_in, 0, sizeof(fftw_complex)*M2KS);
    int m = (M2KS/2)+32;//1704;
    fftw_in[m].re =  0.7;

    fftw_one( m_fftw_2k_plan, fftw_in, out );
    return;
}
*/
void init_dvb_t_fft( void )
{
    //
    // Plans
    //
#ifdef USE_AVFFT
    m_avfft_2k_context  = av_fft_init (11, 1);
    m_avfft_4k_context  = av_fft_init (12, 1);
    m_avfft_8k_context  = av_fft_init (13, 1);
    m_avfft_16k_context = av_fft_init (14, 1);
    m_fft_in  = (fft_complex*)av_malloc(sizeof(fft_complex)*M16KS);
    m_fft_out = (fft_complex*)av_malloc(sizeof(fft_complex)*M16KS);
#else

    FILE *fp;
    if((fp=fopen(dvb_config_get_path("fftw_wisdom"),"r"))!=NULL)
    {
        fftw_import_wisdom_from_file(fp);
        m_fftw_2k_plan  = fftw_create_plan(M2KS,  FFTW_BACKWARD, FFTW_USE_WISDOM);
        m_fftw_4k_plan  = fftw_create_plan(M4KS,  FFTW_BACKWARD, FFTW_USE_WISDOM);
        m_fftw_8k_plan  = fftw_create_plan(M8KS,  FFTW_BACKWARD, FFTW_USE_WISDOM);
        m_fftw_16k_plan = fftw_create_plan(M16KS, FFTW_BACKWARD, FFTW_USE_WISDOM);
        fftw_import_wisdom_from_file(fp);
    }
    else
    {
        if((fp=fopen(dvb_config_get_path("fftw_wisdom"),"w"))!=NULL)
        {
            m_fftw_2k_plan  = fftw_create_plan(M2KS,  FFTW_BACKWARD, FFTW_MEASURE | FFTW_USE_WISDOM);
            m_fftw_4k_plan  = fftw_create_plan(M4KS,  FFTW_BACKWARD, FFTW_MEASURE | FFTW_USE_WISDOM);
            m_fftw_8k_plan  = fftw_create_plan(M8KS,  FFTW_BACKWARD, FFTW_MEASURE | FFTW_USE_WISDOM);
            m_fftw_16k_plan = fftw_create_plan(M16KS, FFTW_BACKWARD, FFTW_MEASURE | FFTW_USE_WISDOM);
            if(fp!=NULL) fftw_export_wisdom_to_file(fp);
        }
    }
    m_fft_in  = (fft_complex*)fftw_malloc(sizeof(fft_complex)*M16KS);
    m_fft_out = (fft_complex*)fftw_malloc(sizeof(fft_complex)*M16KS);
#endif
    if( m_format.tm == TM_2K)
    {
        m_N = M2KS;
        switch( m_format.chan )
        {
        case CH_8M:
        case CH_7M:
        case CH_6M:
            m_IR = 1;
            break;
        case CH_4M:
        case CH_3M:
        case CH_2M:
        case CH_1M:
            m_IR = 2;
            break;
        case CH_500K:
            m_IR = 4;
            break;
        }
    }
    if( m_format.tm == TM_8K)
    {
        m_N = M8KS;
        switch( m_format.chan )
        {
        case CH_8M:
        case CH_7M:
        case CH_6M:
            m_IR = 1;
            break;
        case CH_4M:
        case CH_3M:
        case CH_2M:
        case CH_1M:
            m_IR = 2;
            break;
        }
    }
    create_correction_table( m_N, m_IR );
}
Пример #15
0
int main(int argc, char *argv[])
{
  float *data1, *data2;
  fcomplex *ptr1, *ptr2;
  long n, npts, tmp = 0, ct, plimit, prn = 0;
  long i, isign = -1;
  double err = 0.0;
#if defined USERAWFFTW
  FILE *wisdomfile;
  fftw_plan plan_forward, plan_inverse;
  static char wisdomfilenm[120];
#endif
  struct tms runtimes;
  double ttim, stim, utim, tott;
  
  if (argc <= 1 || argc > 4) {
    printf("\nUsage:  testffts [sign (1/-1)] [print (0/1)] [frac err tol]\n\n");
    exit(0);
  } else if (argc == 2) {
    isign = atoi(argv[1]);
    prn = 0;
    err = 0.02;
  } else if (argc == 3) {
    isign = atoi(argv[1]);
    prn = atoi(argv[2]);
    err = 0.02;
  }
  if (argc == 4) {
    isign = atoi(argv[1]);
    prn = atoi(argv[2]);
    err = atof(argv[3]);
  }

  /* import the wisdom for FFTW */
#if defined USERAWFFTW
  sprintf(wisdomfilenm, "%s/fftw_wisdom.txt", DATABASE);
  wisdomfile = fopen(wisdomfilenm, "r");
  if (wisdomfile == NULL) {
    printf("Error opening '%s'.  Run makewisdom again.\n", \
	   wisdomfilenm);
    printf("Exiting.\n");
    exit(1);
  }
  if (FFTW_FAILURE == fftw_import_wisdom_from_file(wisdomfile)) {
    printf("Error importing FFTW wisdom.\n");
    printf("Exiting.\n");
    exit(1);
  }
  fclose(wisdomfile);
#endif

  for (i = 0; i <= 8; i++) {
    
    /* npts = 1 << (i + 14);        # of points in FFT */
    /*      npts = 1 << 16;	 # of points in FFT */
    /*      npts = 4096;  	 # of points in FFT */
    /*      npts = 524288;   	 # of points in FFT */
    
    npts = 300000 * (i + 1);

    n = npts << 1;	       	/* # of float vals */
    
    data1 = gen_fvect(n);
    data2 = gen_fvect(n);
    ptr1 = (fcomplex *)data1;
    ptr2 = (fcomplex *)data2;
    
    /*      make the data = {1,1,1,1,-1,-1,-1,-1} (all real) */
    /*
      for (ct = 0; ct < npts/2; ct++) {
      tmp = 2 * ct;
      data1[tmp] = 1.0;
      data1[tmp + 1] = 0.0;
      data1[tmp + npts] = -1.0;
      data1[tmp + npts + 1] = 0.0;
      data2[tmp] = 1.0;
      data2[tmp + 1] = 0.0;
      data2[tmp + npts] = -1.0;
      data2[tmp + npts + 1] = 0.0;
      }
    */
    
    /*      make the data a sin wave of fourier freq 12.12345... */
    /*
      for (ct = 0; ct < npts; ct++) {
      tmp = 2 * ct;
      data1[tmp] = sin(2.0*3.14159265358979*ct*12.12345/npts)+1.0;
      data2[tmp] = data1[tmp];
      data1[tmp+1] = 0.0;
      data2[tmp+1] = data1[tmp+1];
      }
    */
    
    /*      make the data a sin wave of fourier freq 12.12345... with noise */
    
    for (ct = 0; ct < npts; ct++) {
      tmp = 2 * ct;
      data1[tmp] = 10.0 * sin(TWOPI * ct * 12.12345 / npts) + 100.0;
      data1[tmp] = gennor(data1[tmp], 10.0);
      data2[tmp] = data1[tmp];
      data1[tmp + 1] = gennor(100.0, 10.0);
      data2[tmp + 1] = data1[tmp + 1];
    }
    
    printf("\nCalculating...\n");
    
    /*  The challenger... */
    
    tott = times(&runtimes) / (double) CLK_TCK;
    utim = runtimes.tms_utime / (double) CLK_TCK;
    stim = runtimes.tms_stime / (double) CLK_TCK;

    tablesixstepfft(ptr1, npts, isign);
    /* tablesixstepfft(plan1, plan2, ptr1, npts, isign); */
    /*  sixstepfft(ptr1, npts, isign);       */
    /*  four1(ptr1 - 1, npts, isign);        */
    /*  tablefft(ptr1, npts, isign);         */
    /*  tablesplitfft(ptr1, npts, isign);    */
    /*  realfft(ptr1, n, isign);             */
    /*  fftw(plan, 1, in, 1, 0, out, 1, 0);  */
    
    tott = times(&runtimes) / (double) CLK_TCK - tott;
    printf("Timing summary (Ransom)  npts = %ld:\n", npts);
    utim = runtimes.tms_utime / (double) CLK_TCK - utim;
    stim = runtimes.tms_stime / (double) CLK_TCK - stim;
    ttim = utim + stim;
    printf("CPU usage: %.3f sec total (%.3f sec user, %.3f sec system)\n", \
	   ttim, utim, stim);
    printf("Total time elapsed:  %.3f sec.\n\n", tott);
    
    /*  The "Standard" FFT... */
    
    /* The following is for the fftw FFT */

    /* Create new plans */
#if defined USERAWFFTW
    plan_forward = fftw_create_plan(npts, -1, FFTW_MEASURE | \
                                           FFTW_USE_WISDOM | \
                                           FFTW_IN_PLACE);
    plan_inverse = fftw_create_plan(npts, +1, FFTW_MEASURE | \
                                           FFTW_USE_WISDOM | \
                                           FFTW_IN_PLACE);
#endif

    tott = times(&runtimes) / (double) CLK_TCK;
    utim = runtimes.tms_utime / (double) CLK_TCK;
    stim = runtimes.tms_stime / (double) CLK_TCK;

    /*  four1(ptr2 - 1, npts, isign);        */
    /*  tablefft(ptr2, npts, isign);         */
    /*  tablesplitfft(ptr1, npts, isign);    */
    /*  tablesixstepfft(ptr2, npts, isign);  */
    /*  realft(ptr2 - 1, n, isign);          */
    fftwcall(ptr2, npts, -1);

#if defined USERAWFFTW
    if (isign == -1) {
      fftw(plan_forward, 1, (FFTW_COMPLEX *) ptr2, 1, 1, NULL, 1, 1);
    } else {
      fftw(plan_inverse, 1, (FFTW_COMPLEX *) ptr2, 1, 1, NULL, 1, 1);
    }
#endif

    tott = times(&runtimes) / (double) CLK_TCK - tott;
    printf("Timing summary (FFTW)  npts = %ld:\n", npts);
    utim = runtimes.tms_utime / (double) CLK_TCK - utim;
    stim = runtimes.tms_stime / (double) CLK_TCK - stim;
    ttim = utim + stim;
    printf("CPU usage: %.3f sec total (%.3f sec user, %.3f sec system)\n", \
	   ttim, utim, stim);
    printf("Total time elapsed:  %.3f sec.\n\n", tott);
    
    /* The following is for the fftw FFT */

#if defined USERAWFFTW
    fftw_destroy_plan(plan_forward);
    fftw_destroy_plan(plan_inverse);
#endif
        
    /* Check if correct with fractional errors... */
    
    for (ct = 0; ct < n; ct++) {
      if (data2[ct] != 0.0) {
	if (fabs((1.0 - (data1[ct] / data2[ct]))) > err) {
	  if ((ct % 2) == 1) {
	    printf("Values at freq %ld do not match to %4.2f%% fractional error:\n", (ct - 1) / 2, err * 100);
	    printf("  rl1 = %f  im1 = %f   rl2 = %f  im2 = %f\n",
		   data1[ct - 1], data1[ct], data2[ct - 1], data2[ct]);
	  } else {
	    printf("Values at freq %ld do not match to %4.2f%% fractional error:\n", ct / 2, err * 100);
	    printf("  rl1 = %f  im1 = %f   rl2 = %f  im2 = %f\n", data1[ct],
		   data1[ct + 1], data2[ct], data2[ct + 1]);
	  }
	}
      }
    }
    
    if (npts >= 64)
      plimit = 64;
    else
      plimit = npts;
    
    /* Print the output... */
    
    if (prn) {
      printf("\n   #1:  Challenger FFT...                      ");
      printf("#2:  Standard...\n");
      for (ct = 0; ct < plimit; ct++) {
	printf(" %3ld  rl = %12.3f   ", ct, data1[2 * ct]);
	printf("im = %12.3f    rl = %12.3f   im = %12.3f\n", \
	       data1[2 * ct + 1], data2[2 * ct], data2[2 * ct + 1]);
      }
    }

    free(data1);
    free(data2);
  }
  
  return 0;
  
}
Пример #16
0
//***************************************************************************
int main(int argc, char *argv[])
{
  extern char *optarg;
  extern int optind;
  int i,j,k;
  unsigned char *symbols, *decdata;
  signed char message[]={-9,13,-35,123,57,-39,64,0,0,0,0};
  char *callsign,*grid,*grid6, *call_loc_pow, *cdbm;
  char *ptr_to_infile,*ptr_to_infile_suffix;
  char uttime[5],date[7];
  char xuttime[6],xdate[11];
  int c,delta,nfft2=65536,verbose=0,quickmode=0,writenoise=0,usehashtable=1;
  int shift1, lagmin, lagmax, lagstep, worth_a_try, not_decoded, nadd, ndbm;
  int32_t n1, n2, n3;
  unsigned int nbits;
  unsigned int npoints, metric, maxcycles, cycles, maxnp;
  float df=375.0/256.0/2;
  float freq0[200],snr0[200],drift0[200],sync0[200];
  int shift0[200];
  float dt=1.0/375.0;
  double dialfreq_cmdline=0.0, dialfreq;
  float dialfreq_error=0.0;
  float fmin=-110, fmax=110;
  float f1, fstep, sync1, drift1, tblank=0, fblank=0;
  double *idat, *qdat;
  clock_t t0,t00;
  double tfano=0.0,treadwav=0.0,tcandidates=0.0,tsync0=0.0;
  double tsync1=0.0,tsync2=0.0,ttotal=0.0;

// Parameters used for performance-tuning:
  maxcycles=10000;                         //Fano timeout limit
  double minsync1=0.10;                    //First sync limit
  double minsync2=0.12;                    //Second sync limit
  int iifac=3;                             //Step size in final DT peakup
  int symfac=45;                           //Soft-symbol normalizing factor
  int maxdrift=4;                          //Maximum (+/-) drift
  double minrms=52.0 * (symfac/64.0);      //Final test for palusible decoding
  delta=60;                                //Fano threshold step

  t00=clock();
  fftw_complex *fftin, *fftout;
#include "./mettab.c"

// Check for an optional FFTW wisdom file
  FILE *fp_fftw_wisdom_file;
  if ((fp_fftw_wisdom_file = fopen("fftw_wisdom_wsprd", "r"))) {
    fftw_import_wisdom_from_file(fp_fftw_wisdom_file);
    fclose(fp_fftw_wisdom_file);
  }

  idat=malloc(sizeof(double)*nfft2);
  qdat=malloc(sizeof(double)*nfft2);

  while ( (c = getopt(argc, argv, "b:e:f:Hnqt:wv")) !=-1 ) {
    switch (c) {
    case 'b':
      fblank = strtof(optarg,NULL);
      break;
    case 'e':
      dialfreq_error = strtof(optarg,NULL);   // units of Hz
      // dialfreq_error = dial reading - actual, correct frequency
      break;
    case 'f':
      dialfreq_cmdline = strtod(optarg,NULL); // units of MHz
      break;
    case 'H':
      usehashtable = 0;
      break;
    case 'n':
      writenoise = 1;
      break;
    case 'q':
      quickmode = 1;
      break;
    case 't':
      tblank = strtof(optarg,NULL);
      break;
    case 'v':
      verbose = 1;
      break;
    case 'w':
      fmin=-150.0;
      fmax=150.0;
      break;
    case '?':
      usage();
      return 1;
    }
  }

  if( optind+1 > argc) {
    usage();
    return 1;
  } else {
    ptr_to_infile=argv[optind];
  }

  FILE *fall_wspr, *fwsprd, *fhash, *ftimer, *fweb;
  FILE *fdiag;
  fall_wspr=fopen("ALL_WSPR.TXT","a");
  fwsprd=fopen("wsprd.out","w");
  fdiag=fopen("wsprd_diag","a");
  fweb=fopen("wspr-now.txt","a");

  if((ftimer=fopen("wsprd_timer","r"))) {
    //Accumulate timing data
    nr=fscanf(ftimer,"%lf %lf %lf %lf %lf %lf %lf",
	   &treadwav,&tcandidates,&tsync0,&tsync1,&tsync2,&tfano,&ttotal);
    fclose(ftimer);
  }
  ftimer=fopen("wsprd_timer","w");

  if( strstr(ptr_to_infile,".wav") ) {
    ptr_to_infile_suffix=strstr(ptr_to_infile,".wav");

    t0 = clock();
    npoints=readwavfile(ptr_to_infile, idat, qdat);
    treadwav += (double)(clock()-t0)/CLOCKS_PER_SEC;

    if( npoints == 1 ) {
      return 1;
    }
    dialfreq=dialfreq_cmdline - (dialfreq_error*1.0e-06);
  } else if ( strstr(ptr_to_infile,".c2") !=0 )  {
    ptr_to_infile_suffix=strstr(ptr_to_infile,".c2");
    npoints=readc2file(ptr_to_infile, idat, qdat, &dialfreq);
    if( npoints == 1 ) {
      return 1;
    }
    dialfreq -= (dialfreq_error*1.0e-06);
  } else {
    printf("Error: Failed to open %s\n",ptr_to_infile);
    printf("WSPR file must have suffix .wav or .c2\n");
    return 1;
  }

// Parse date and time from given filename
  strncpy(date,ptr_to_infile_suffix-11,6);
  strncpy(uttime,ptr_to_infile_suffix-4,4);
  date[6]='\0';
  uttime[4]='\0';
//added riyas
  sprintf(xdate, "20%.2s-%.2s-%.2s", date, date+2, date+4);
  xdate[10]='\0';
  sprintf(xuttime, "%.2s:%.2s", uttime, uttime+2);
  xuttime[5]='\0';

// Do windowed ffts over 2 symbols, stepped by half symbols
  int nffts=4*floor(npoints/512)-1;
  fftin=(fftw_complex*) fftw_malloc(sizeof(fftw_complex)*512);
  fftout=(fftw_complex*) fftw_malloc(sizeof(fftw_complex)*512);
  PLAN3 = fftw_plan_dft_1d(512, fftin, fftout, FFTW_FORWARD, PATIENCE);
    
  float ps[512][nffts];
  float w[512];
  for(i=0; i<512; i++) {
    w[i]=sin(0.006135923*i);
  }

  memset(ps,0.0, sizeof(float)*512*nffts);
  for (i=0; i<nffts; i++) {
    for(j=0; j<512; j++ ) {
      k=i*128+j;
      fftin[j][0]=idat[k] * w[j];
      fftin[j][1]=qdat[k] * w[j];
    }
    fftw_execute(PLAN3);
    for (j=0; j<512; j++ ) {
      k=j+256;
      if( k>511 )
	k=k-512;
      ps[j][i]=fftout[k][0]*fftout[k][0]+fftout[k][1]*fftout[k][1];
    }
  }

  fftw_free(fftin);
  fftw_free(fftout);

// Compute average spectrum
  float psavg[512];
  memset(psavg,0.0, sizeof(float)*512);
  for (i=0; i<nffts; i++) {
    for (j=0; j<512; j++) {
      psavg[j]=psavg[j]+ps[j][i];
    }
  }

// Smooth with 7-point window and limit spectrum to +/-150 Hz
  int window[7]={1,1,1,1,1,1,1};
  float smspec[411];
  for (i=0; i<411; i++) {
    smspec[i]=0.0;
    for(j=-3; j<=3; j++) {
      k=256-205+i+j;
      smspec[i]=smspec[i]+window[j+3]*psavg[k];
    }
  }

// Sort spectrum values, then pick off noise level as a percentile
  float tmpsort[411];
  for (j=0; j<411; j++) {
    tmpsort[j]=smspec[j];
  }
  qsort(tmpsort, 411, sizeof(float), floatcomp);

// Noise level of spectrum is estimated as 123/411= 30'th percentile
  float noise_level = tmpsort[122];

// Renormalize spectrum so that (large) peaks represent an estimate of snr
  float min_snr_neg33db = pow(10.0,(-33+26.5)/10.0);
  for (j=0; j<411; j++) {
    smspec[j]=smspec[j]/noise_level - 1.0;
    if( smspec[j] < min_snr_neg33db) smspec[j]=0.1;
    continue;
  }

// Find all local maxima in smoothed spectrum.
  for (i=0; i<200; i++) {
    freq0[i]=0.0;
    snr0[i]=0.0;
    drift0[i]=0.0;
    shift0[i]=0;
    sync0[i]=0.0;
  }

  int npk=0;
  for(j=1; j<410; j++) {
    if((smspec[j]>smspec[j-1]) && (smspec[j]>smspec[j+1]) && (npk<200)) {
      freq0[npk]=(j-205)*df;
      snr0[npk]=10*log10(smspec[j])-26.5;
      npk++;
    }
  }

// Compute corrected fmin, fmax, accounting for dial frequency error
  fmin += dialfreq_error;    // dialfreq_error is in units of Hz
  fmax += dialfreq_error;

// Don't waste time on signals outside of the range [fmin,fmax].
  i=0;
  for( j=0; j<npk; j++) {
    if( freq0[j] >= fmin && freq0[j] <= fmax ) {
      freq0[i]=freq0[j];
      snr0[i]=snr0[j];
      i++;
    }
  }
  npk=i;

  t0=clock();
/* Make coarse estimates of shift (DT), freq, and drift

  * Look for time offsets up to +/- 8 symbols (about +/- 5.4 s) relative 
    to nominal start time, which is 2 seconds into the file

  * Calculates shift relative to the beginning of the file

  * Negative shifts mean that signal started before start of file

  * The program prints DT = shift-2 s

  * Shifts that cause sync vector to fall off of either end of the data 
    vector are accommodated by "partial decoding", such that missing 
    symbols produce a soft-decision symbol value of 128 

  * The frequency drift model is linear, deviation of +/- drift/2 over the
    span of 162 symbols, with deviation equal to 0 at the center of the 
    signal vector. 
*/

  int idrift,ifr,if0,ifd,k0;
  int kindex;
  float smax,ss,pow,p0,p1,p2,p3;
  for(j=0; j<npk; j++) {                              //For each candidate...
    smax=-1e30;
    if0=freq0[j]/df+256;
    for (ifr=if0-1; ifr<=if0+1; ifr++) {                      //Freq search
      for( k0=-10; k0<22; k0++) {                             //Time search
	for (idrift=-maxdrift; idrift<=maxdrift; idrift++) {  //Drift search
	  ss=0.0;
	  pow=0.0;
	  for (k=0; k<162; k++) {                             //Sum over symbols
	    ifd=ifr+((float)k-81.0)/81.0*( (float)idrift )/(2.0*df);
	    kindex=k0+2*k;
	    if( kindex < nffts ) {
	      p0=ps[ifd-3][kindex];
	      p1=ps[ifd-1][kindex];
	      p2=ps[ifd+1][kindex];
	      p3=ps[ifd+3][kindex];

	      p0=sqrt(p0);
	      p1=sqrt(p1);
	      p2=sqrt(p2);
	      p3=sqrt(p3);

	      ss=ss+(2*pr3[k]-1)*((p1+p3)-(p0+p2));
	      pow=pow+p0+p1+p2+p3;
	      sync1=ss/pow;
	    }
	  }
	  if( sync1 > smax ) {                  //Save coarse parameters
	    smax=sync1;
	    shift0[j]=128*(k0+1);
	    drift0[j]=idrift;
	    freq0[j]=(ifr-256)*df;
	    sync0[j]=sync1;
	  }
	}
      }
    }
  }
  tcandidates += (double)(clock()-t0)/CLOCKS_PER_SEC;

  nbits=81;
  symbols=malloc(sizeof(char)*nbits*2);
  memset(symbols,0,sizeof(char)*nbits*2);
  decdata=malloc((nbits+7)/8);
  grid=malloc(sizeof(char)*5);
  grid6=malloc(sizeof(char)*7);
  callsign=malloc(sizeof(char)*13);
  call_loc_pow=malloc(sizeof(char)*23);
  cdbm=malloc(sizeof(char)*3);
  float allfreqs[npk];
  memset(allfreqs,0,sizeof(float)*npk);
  char allcalls[npk][13];
  memset(allcalls,0,sizeof(char)*npk*13);
  memset(grid,0,sizeof(char)*5);
  memset(grid6,0,sizeof(char)*7);
  memset(callsign,0,sizeof(char)*13);
  memset(call_loc_pow,0,sizeof(char)*23);
  memset(cdbm,0,sizeof(char)*3);
  char hashtab[32768][13];
  memset(hashtab,0,sizeof(char)*32768*13);
  uint32_t nhash( const void *, size_t, uint32_t);
  int nh;
    
  if( usehashtable ) {
    char line[80], hcall[12];
    if( (fhash=fopen("hashtable.txt","r+")) ) {
      while (fgets(line, sizeof(line), fhash) != NULL) {
	sscanf(line,"%d %s",&nh,hcall);
	strcpy(*hashtab+nh*13,hcall);
      }
    } else {
      fhash=fopen("hashtable.txt","w+");
    }
    fclose(fhash);
  }
    
  int uniques=0, noprint=0;
/*    
 Refine the estimates of freq, shift using sync as a metric.
 Sync is calculated such that it is a float taking values in the range
 [0.0,1.0].
        
 Function sync_and_demodulate has three modes of operation
 mode is the last argument:

      0 = no frequency or drift search. find best time lag.
      1 = no time lag or drift search. find best frequency.
      2 = no frequency or time lag search. Calculate soft-decision 
          symbols using passed frequency and shift.

NB: best possibility for OpenMP may be here: several worker threads
could each work on one candidate at a time.
*/

  for (j=0; j<npk; j++) {
    f1=freq0[j];
    drift1=drift0[j];
    shift1=shift0[j];
    sync1=sync0[j];

// Fine search for best sync lag (mode 0)
    fstep=0.0;
    lagmin=shift1-144;
    lagmax=shift1+144;
    lagstep=8;
    if(quickmode) lagstep=16;
    t0 = clock();
    sync_and_demodulate(idat, qdat, npoints, symbols, &f1, fstep, &shift1, 
		    lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 0);
    tsync0 += (double)(clock()-t0)/CLOCKS_PER_SEC;

// Fine search for frequency peak (mode 1)
    fstep=0.1;
    t0 = clock();
    sync_and_demodulate(idat, qdat, npoints, symbols, &f1, fstep, &shift1, 
		     lagmin, lagmax, lagstep, &drift1, symfac, &sync1, 1);
    tsync1 += (double)(clock()-t0)/CLOCKS_PER_SEC;

    if( sync1 > minsync1 ) {
      worth_a_try = 1;
    } else {
      worth_a_try = 0;
    }

    int idt=0, ii=0, jiggered_shift;
    uint32_t ihash;
    double y,sq,rms;
    not_decoded=1;

    while ( worth_a_try && not_decoded && idt<=(128/iifac)) {
      ii=(idt+1)/2;
      if( idt%2 == 1 ) ii=-ii;
      ii=iifac*ii;
      jiggered_shift=shift1+ii;

// Use mode 2 to get soft-decision symbols
      t0 = clock();
      sync_and_demodulate(idat, qdat, npoints, symbols, &f1, fstep, 
	 &jiggered_shift, lagmin, lagmax, lagstep, &drift1, symfac, 
			  &sync1, 2);
      tsync2 += (double)(clock()-t0)/CLOCKS_PER_SEC;

      sq=0.0;
      for(i=0; i<162; i++) {
	y=(double)symbols[i] - 128.0;
	sq += y*y;
      }
      rms=sqrt(sq/162.0);

      if((sync1 > minsync2) && (rms > minrms)) {
	deinterleave(symbols);
	t0 = clock();
	  not_decoded = fano(&metric,&cycles,&maxnp,decdata,symbols,nbits,
			     mettab,delta,maxcycles);
	tfano += (double)(clock()-t0)/CLOCKS_PER_SEC;

	/* ### Used for timing tests:
	if(not_decoded) fprintf(fdiag,
	    "%6s %4s %4.1f %3.0f %4.1f %10.7f  %-18s %2d %5u %4d %6.1f %2d\n",
	    date,uttime,sync1*10,snr0[j], shift1*dt-2.0, dialfreq+(1500+f1)/1e6,
	    "@                 ", (int)drift1, cycles/81, ii, rms, maxnp);
	*/
      }
      idt++;
      if( quickmode ) break;  
    }

    if( worth_a_try && !not_decoded ) {
      for(i=0; i<11; i++) {
	if( decdata[i]>127 ) {
	  message[i]=decdata[i]-256;
	} else {
	  message[i]=decdata[i];
	}
      }

      unpack50(message,&n1,&n2);
      unpackcall(n1,callsign);
      unpackgrid(n2, grid);
      int ntype = (n2&127) - 64;

/*
 Based on the value of ntype, decide whether this is a Type 1, 2, or 
 3 message.

 * Type 1: 6 digit call, grid, power - ntype is positive and is a member 
         of the set {0,3,7,10,13,17,20...60}

 * Type 2: extended callsign, power - ntype is positive but not
         a member of the set of allowed powers

 * Type 3: hash, 6 digit grid, power - ntype is negative.
*/

      if( (ntype >= 0) && (ntype <= 62) ) {
	int nu=ntype%10;
	if( nu == 0 || nu == 3 || nu == 7 ) {
	  ndbm=ntype;
	  memset(call_loc_pow,0,sizeof(char)*23);
	  sprintf(cdbm,"%2d",ndbm);
	  strncat(call_loc_pow,callsign,strlen(callsign));
	  strncat(call_loc_pow," ",1);
	  strncat(call_loc_pow,grid,4);
	  strncat(call_loc_pow," ",1);
	  strncat(call_loc_pow,cdbm,2);
	  strncat(call_loc_pow,"\0",1);
                    
	  ihash=nhash(callsign,strlen(callsign),(uint32_t)146);
	  strcpy(*hashtab+ihash*13,callsign);

	  noprint=0;
	} else {
	  nadd=nu;
	  if( nu > 3 ) nadd=nu-3;
	  if( nu > 7 ) nadd=nu-7;
	  n3=n2/128+32768*(nadd-1);
	  unpackpfx(n3,callsign);
	  ndbm=ntype-nadd;

	  memset(call_loc_pow,0,sizeof(char)*23);
	  sprintf(cdbm,"%2d",ndbm);
	  strncat(call_loc_pow,callsign,strlen(callsign));
	  strncat(call_loc_pow," ",1);
	  strncat(call_loc_pow,cdbm,2);
	  strncat(call_loc_pow,"\0",1);
                    
	  ihash=nhash(callsign,strlen(callsign),(uint32_t)146);
	  strcpy(*hashtab+ihash*13,callsign);

	  noprint=0;
	}
      } else if ( ntype < 0 ) {
	ndbm=-(ntype+1);
	memset(grid6,0,sizeof(char)*7);
	strncat(grid6,callsign+5,1);
	strncat(grid6,callsign,5);
	ihash=(n2-ntype-64)/128;
	if( strncmp(hashtab[ihash],"\0",1) != 0 ) {
	  sprintf(callsign,"<%s>",hashtab[ihash]);
	} else {
	  sprintf(callsign,"%5s","<...>");
	}

	memset(call_loc_pow,0,sizeof(char)*23);
	sprintf(cdbm,"%2d",ndbm);
	strncat(call_loc_pow,callsign,strlen(callsign));
	strncat(call_loc_pow," ",1);
	strncat(call_loc_pow,grid6,strlen(grid6));
	strncat(call_loc_pow," ",1);
	strncat(call_loc_pow,cdbm,2);
	strncat(call_loc_pow,"\0",1);
                
	noprint=0;
                
// I don't know what to do with these... They show up as "A000AA" grids.
	if( ntype == -64 ) noprint=1;
	
      }
            
// Remove dupes (same callsign and freq within 1 Hz)
      int dupe=0;
      for (i=0; i<npk; i++) {
	if(!strcmp(callsign,allcalls[i]) && 
	   (fabs(f1-allfreqs[i]) <1.0)) dupe=1;
      }
      if( (verbose || !dupe) && !noprint) {
	uniques++;
	strcpy(allcalls[uniques],callsign);
	allfreqs[uniques]=f1;
// Add an extra space at the end of each line so that wspr-x doesn't 
// truncate the power (TNX to DL8FCL!)
    char mygrid[]="NK03";
	char mycall[]="SIARS";
    //printf("%4s=================%d\n",grid,distance(grid, mygrid));
	
    
	printf("%4s %3.0f %4.1f %10.6f %2d  %-s \n",
	       uttime, snr0[j],(shift1*dt-2.0), dialfreq+(1500+f1)/1e6,
	       (int)drift1, call_loc_pow);

	fprintf(fall_wspr,
		"%6s %4s %3.0f %3.0f %4.1f %10.7f  %-22s %2d %5u %4d\n",
		date,uttime,sync1*10,snr0[j],
		shift1*dt-2.0, dialfreq+(1500+f1)/1e6,
		call_loc_pow, (int)drift1, cycles/81, ii);
		
	fprintf(fwsprd,
		"%6s %4s %3.0f %3.0f %4.1f %10.7f  %-22s %2d %5u %4d\n",
		date,uttime,sync1*10,snr0[j],
		shift1*dt-2.0, dialfreq+(1500+f1)/1e6,
		call_loc_pow, (int)drift1, cycles/81, ii);		

	fprintf(fweb,"&nbsp;%10s %5s&nbsp;&nbsp;%s&nbsp;&nbsp;%10.7f&nbsp;&nbsp;%3.0f&nbsp;&nbsp;%2d&nbsp;&nbsp;%4s&nbsp;&nbsp;%2d&nbsp;&nbsp;%2d&nbsp;&nbsp;%5s&nbsp;&nbsp;%4s&nbsp;&nbsp;%d&nbsp;&nbsp;%d&nbsp;\n",
		xdate,xuttime,callsign,dialfreq+(1500+f1)/1e6,snr0[j],(int)drift1,grid,ndbm,ndbm,mycall,mygrid,distance(grid, mygrid),distance(grid, mygrid));

/* For timing tests

	fprintf(fdiag,
	  "%6s %4s %4.1f %3.0f %4.1f %10.7f  %-18s %2d %5u %4d %6.1f\n",
	  date,uttime,sync1*10,snr0[j],
	  shift1*dt-2.0, dialfreq+(1500+f1)/1e6,
	  call_loc_pow, (int)drift1, cycles/81, ii, rms);
*/
      }
    }
  }
  printf("<DecodeFinished>\n");

  if ((fp_fftw_wisdom_file = fopen("fftw_wisdom_wsprd", "w"))) {
    fftw_export_wisdom_to_file(fp_fftw_wisdom_file);
    fclose(fp_fftw_wisdom_file);
  }

  ttotal += (double)(clock()-t00)/CLOCKS_PER_SEC;

  fprintf(ftimer,"%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n\n",
	  treadwav,tcandidates,tsync0,tsync1,tsync2,tfano,ttotal);

  fprintf(ftimer,"Code segment        Seconds   Frac\n");
  fprintf(ftimer,"-----------------------------------\n");
  fprintf(ftimer,"readwavfile        %7.2f %7.2f\n",treadwav,treadwav/ttotal);
  fprintf(ftimer,"Coarse DT f0 f1    %7.2f %7.2f\n",tcandidates,
	                                            tcandidates/ttotal);
  fprintf(ftimer,"sync_and_demod(0)  %7.2f %7.2f\n",tsync0,tsync0/ttotal);
  fprintf(ftimer,"sync_and_demod(1)  %7.2f %7.2f\n",tsync1,tsync1/ttotal);
  fprintf(ftimer,"sync_and_demod(2)  %7.2f %7.2f\n",tsync2,tsync2/ttotal);
  fprintf(ftimer,"Fano decoder       %7.2f %7.2f\n",tfano,tfano/ttotal);
  fprintf(ftimer,"-----------------------------------\n");
  fprintf(ftimer,"Total              %7.2f %7.2f\n",ttotal,1.0);

  fclose(fall_wspr);
  fclose(fwsprd);
  fclose(fdiag);
  fclose(ftimer);
  fftw_destroy_plan(PLAN1);
  fftw_destroy_plan(PLAN2);
  fftw_destroy_plan(PLAN3);

  if( usehashtable ) {
    fhash=fopen("hashtable.txt","w");
    for (i=0; i<32768; i++) {
      if( strncmp(hashtab[i],"\0",1) != 0 ) {
	fprintf(fhash,"%5d %s\n",i,*hashtab+i*13);
      }
    }
    fclose(fhash);
  }
  if(fblank+tblank+writenoise == 999) return -1;  //Silence compiler warning
  return 0;
}