コード例 #1
0
ファイル: PlotDlg.cpp プロジェクト: jhp333/aux
void CPlotDlg::OnMenu(UINT nID)
{
	static char fullfname[MAX_PATH];
	static CAxis *axSpec(NULL);
	CAxis *localax(gcf->ax[0]); // Following the convention
	CRect rt;
	CSize sz;
	CFont editFont;
	CPosition pos;
	double range, miin(1.e15), maax(-1.e15);
	double width, newmin, newmax;
	int i, len, id1, id2, iSel(-1);
	char errstr[256];
	CSignals signal;
	bool multi;
	static void  *playPoint;
	switch (nID)
	{
	case IDM_FULLVIEW:
		localax->setRange('x',localax->m_ln[0]->xdata[0], localax->m_ln[0]->xdata[localax->m_ln[0]->len-1]);
		localax->setTick('x', 0, localax->m_ln[0]->xdata[localax->m_ln[0]->len-1]/10, 1, 0, "%6.3f");
		// 2/3/2011, commented out by jhpark, because y axis is not affected by zooming.
		//localax->setRange('y', -1, 1);
		OnMenu(IDM_SPECTRUM_INTERNAL);
		return;

	case IDM_ZOOM_IN:
		width = localax->xlim[1] - localax->xlim[0];
		if (width<0.005) return;
		localax->setRange('x', localax->xlim[0] + width/4., localax->xlim[1] - width/4.);
		width = localax->xtick.a2 - localax->xtick.a1;
		localax->xtick.a2 -= width/4.;
		localax->xtick.a1 += width/4.;
		OnMenu(IDM_SPECTRUM_INTERNAL);
		return;

	case IDM_ZOOM_OUT:
		if (localax->xlim[1]==localax->xlimFull[1] && localax->xlim[0]==localax->xlimFull[0]) return;
		for (i=0; i<localax->nLines; i++)
			miin = min(miin, getMin(localax->m_ln[i]->len, localax->m_ln[i]->xdata));
		for (i=0; i<localax->nLines; i++)
			maax = max(maax, getMax(localax->m_ln[i]->len, localax->m_ln[i]->xdata));
		width = localax->xlim[1] - localax->xlim[0];
		localax->setRange('x', max(miin,localax->xlim[0] - width/2.), min(maax,localax->xlim[1] + width/2.));
		width = localax->xtick.a2 - localax->xtick.a1;
		//Oh, I just realized that a1 and a2 do not need to be within the range==> no need to check, it will still draw the ticks only within the range.
		localax->xtick.a2 += width/2.;
		localax->xtick.a1 -= width/2.;
		if (localax->xtick.a1<0) localax->xtick.a1=0;
		OnMenu(IDM_SPECTRUM_INTERNAL);
		return;
	case IDM_SCROLL_LEFT:
		for (i=0; i<localax->nLines; i++)
			miin = min(miin, getMin(localax->m_ln[i]->len, localax->m_ln[i]->xdata));
		range = localax->xlim[1] - localax->xlim[0];
		newmin = max(miin, localax->xlim[0]-range);
		localax->setRange('x', newmin, newmin+range);
		rt = localax->axRect;
		rt.InflateRect(5,0,5,30);
		InvalidateRect(&rt);
		OnMenu(IDM_SPECTRUM_INTERNAL);
		return;
	case IDM_SCROLL_RIGHT:
		for (i=0; i<localax->nLines; i++)
			maax = max(maax, getMax(localax->m_ln[i]->len, localax->m_ln[i]->xdata));
		range = localax->xlim[1] - localax->xlim[0];
		newmax = min(maax, localax->xlim[1]+range);
		localax->setRange('x', newmax-range, newmax);
		rt = localax->axRect;
		rt.InflateRect(5,0,5,30);
		InvalidateRect(&rt);
		OnMenu(IDM_SPECTRUM_INTERNAL);
		return;
	case IDM_LEFT_STEP:
		for (i=0; i<localax->nLines; i++)
			miin = min(miin, getMin(localax->m_ln[i]->len, localax->m_ln[i]->xdata));
		range = localax->xlim[1] - localax->xlim[0];
		newmin = max(miin, localax->xlim[0]-range/4.);
		localax->setRange('x', newmin, newmin+range);
		rt = localax->axRect;
		rt.InflateRect(5,0,5,30);
		InvalidateRect(&rt);
		OnMenu(IDM_SPECTRUM_INTERNAL);
		return;
	case IDM_RIGHT_STEP:
		for (i=0; i<localax->nLines; i++)
			maax = max(maax, getMax(localax->m_ln[i]->len, localax->m_ln[i]->xdata));
		range = localax->xlim[1] - localax->xlim[0];
		newmax = min(maax, localax->xlim[1]+range/4.);
		localax->setRange('x', newmax-range, newmax);
		rt = localax->axRect;
		rt.InflateRect(5,0,5,30);
		InvalidateRect(&rt);
		OnMenu(IDM_SPECTRUM_INTERNAL);
		return;
	case IDM_PLAY:
		errstr[0]=0;
		if (!playing)
			if(!GetSignalInRange(signal,1))		MessageBox (errStr);
			else 
			{
				playPoint = signal.PlayArray(devID, WM__SOUND_EVENT, hDlg, &block, errstr);
				playing = true;
			}
		else
		{
			PauseResumePlay(playPoint, paused);
			playing = paused;
			if (paused) paused = false;
		}
		return;
	case IDM_PAUSE:
		errstr[0]=0;
		if (playing)
		{
			PauseResumePlay(playPoint, false);
			paused = true;
		}
		return;
	case IDM_SPECTRUM:
		// To draw a spectrum, first re-adjust the aspect ratio of the client window 
		// so that the width is at least 1.5 times the height.
		if (!specView)
		{
			GetWindowRect(&rt);
			sz = rt.Size();
			if (sz.cx<3*sz.cy/2)
			{
				rt.InflateRect(0, 0, 3*sz.cy/2, 0);
				MoveWindow(&rt, 0);
			}
			//Again, //Assuming that the first axis is the waveform viewer, the second one is for spectrum viewing
			lastPos = gcf->ax[0]->pos;
			gcf->ax[0]->setPos(.08, .1, .62, .8);
			axSpec = gcf->axes(.75, .3, .22, .4);
			axSpec->colorBack = RGB(230, 230, 190);
			OnMenu(IDM_SPECTRUM_INTERNAL);
		}
		else
		{
			deleteObj(axSpec);
			axSpec=NULL;
			gcf->ax[0]->setPos(lastPos);
		}
		specView = !specView;
		break;
	case IDM_SPECTRUM_INTERNAL:
		rfftw_plan plan;
		double *freq, *fft, *mag, *fft2, *mag2, fs, maxx, maxmag, ylim;
		multi = localax->nLines>1 ? true : false;
		if (gcf->nAxes==1) break;
		fs = (double)sig.GetFs();
		for (; gcf->ax[1]->nLines>0;)	
			deleteObj(gcf->ax[1]->m_ln[0]);
		GetIndicesInRange(localax, id1, id2);
		len = id2-id1+1;
		freq = new double[len];
		fft = new double[len];
		mag = new double[len/2];
		for (i=0; i<len; i++)
			freq[i]=(double)i/(double)len*fs;
		plan = rfftw_create_plan(len, FFTW_FORWARD, FFTW_ESTIMATE|FFTW_OUT_OF_PLACE);
		rfftw_one(plan, &localax->m_ln[0]->ydata[id1], fft);
		if (multi) 
		{
			fft2 = new double[len];
			mag2 = new double[len/2];
			rfftw_one(plan, &localax->m_ln[1]->ydata[id1], fft2);
		}
		rfftw_destroy_plan(plan);
		for (i=0; i<len/2; i++)		mag[i] = 20.*log10(fabs(fft[len-i]));
		if (multi) for (i=0; i<len/2; i++)	mag2[i] = 20.*log10(fabs(fft2[len-i]));
		maxmag = getMax(len/2,mag);
		maxx = 5.*(maxmag/5.+1);
		for (int j=0; j<len/2; j++)	mag[j] -= maxx;
		if (multi) 
		{
			maxmag = getMax(len/2,mag2);
			maxx = 5.*(maxmag/5.+1);
			for (int j=0; j<len/2; j++)	mag2[j] -= maxx;
		}
		ylim = 10.*(maxmag/10.+1)-maxx;
		PlotDouble(gcf->ax[1], len/2, freq, mag);
		SetRange(gcf->ax[1], 'x', 0, fs/2);
		SetTick(gcf->ax[1], 'x', 0, 1000, 0, 0, "%2.0lfk", 0.001);
		SetRange(gcf->ax[1], 'y', getMean(len/2,mag)-40, ylim);
		SetTick(gcf->ax[1], 'y', 0, 10);
		gcf->ax[1]->m_ln[0]->color = gcf->ax[0]->m_ln[0]->color;
		if (multi) 
		{
			PlotDouble(gcf->ax[1], len/2, freq, mag2);
			gcf->ax[1]->m_ln[1]->color = gcf->ax[0]->m_ln[1]->color;
			delete[] fft2;
			delete[] mag2;
		}
		delete[] freq;
		delete[] fft;
		delete[] mag;
		break;
	case IDM_WAVWRITE:
		char fname[MAX_PATH];
		CFileDlg fileDlg;
		fileDlg.InitFileDlg(hDlg, hInst, "");
		errstr[0]=0;
		if(!GetSignalInRange(signal,1))
		{	MessageBox (errStr);	return;	}
		if (fileDlg.FileSaveDlg(fullfname, fname, "Wav file (*.WAV)\0*.wav\0", "wav"))
			if (!signal.Wavwrite(fullfname, errstr))	
			{MessageBox (errstr);}
		else
		{
			CStdString str;
			if (GetLastError()!=0) { GetLastErrorStr(str); MessageBox (str.c_str(), "Filesave error");}
		}
		return;
	}
	InvalidateRect(NULL);
}
コード例 #2
0
void test_planner(int rank)
{
     /* 
      * create and destroy many plans, at random.  Check the
      * garbage-collecting allocator of twiddle factors 
      */
     int i, dim;
     int r, s;
     fftw_plan p[PLANNER_TEST_SIZE];
     fftwnd_plan pnd[PLANNER_TEST_SIZE];
     int *narr, maxdim;

     chk_mem_leak = 0;
     verbose--;

     please_wait();
     if (rank < 1)
	  rank = 1;

     narr = (int *) fftw_malloc(rank * sizeof(int));

     maxdim = (int) pow(8192.0, 1.0/rank);

     for (i = 0; i < PLANNER_TEST_SIZE; ++i) {
	  p[i] = (fftw_plan) 0;
	  pnd[i] = (fftwnd_plan) 0;
     }

     for (i = 0; i < PLANNER_TEST_SIZE * PLANNER_TEST_SIZE; ++i) {
	  r = rand();
	  if (r < 0)
	       r = -r;
	  r = r % PLANNER_TEST_SIZE;

	  for (dim = 0; dim < rank; ++dim) {
	       do {
		    s = rand();
		    if (s < 0)
			 s = -s;
		    s = s % maxdim + 1;
	       } while (s == 0);
	       narr[dim] = s;
	  }

	  if (rank == 1) {
	       if (p[r])
		    rfftw_destroy_plan(p[r]);

	       p[r] = rfftw_create_plan(narr[0], random_dir(), measure_flag |
					wisdom_flag);
	       if (paranoid && narr[0] < 200)
		    test_correctness(narr[0]);
	  }
	  if (pnd[r])
	       rfftwnd_destroy_plan(pnd[r]);

	  pnd[r] = rfftwnd_create_plan(rank, narr,
				       random_dir(), measure_flag |
				       wisdom_flag);

	  if (i % (PLANNER_TEST_SIZE * PLANNER_TEST_SIZE / 20) == 0) {
	       WHEN_VERBOSE(0, printf("test planner: so far so good\n"));
	       WHEN_VERBOSE(0, printf("test planner: iteration %d out of %d\n",
			      i, PLANNER_TEST_SIZE * PLANNER_TEST_SIZE));
	  }
     }

     for (i = 0; i < PLANNER_TEST_SIZE; ++i) {
	  if (p[i])
	       rfftw_destroy_plan(p[i]);
	  if (pnd[i])
	       rfftwnd_destroy_plan(pnd[i]);
     }

     fftw_free(narr);
     verbose++;
     chk_mem_leak = 1;
}
コード例 #3
0
ファイル: fft.c プロジェクト: PauloJava2016/Solfege
int
_fft_init( unsigned long points )
{
	long c;
#ifndef HAVE_FFTW

	unsigned int i = points, k = 1;
	float j;

	while( i > 2 ) {
		if( i & 0x0001 )
			return -1;
		i >>= 1;
		k++;
	}

	nn = points;
	lognn = k;

	if( iout != NULL )
		free( iout );
	if( rout != NULL )
		free( rout );
	if( sintable != NULL )
		free( sintable );
	if( costable != NULL )
		free( costable );
	if( bit_reverse != NULL )
		free( bit_reverse );

	bit_reverse = (int*) xmalloc( sizeof( int ) * nn );
	costable = (double*) xmalloc( sizeof( double ) * nn / 2 );
	sintable = (double*) xmalloc( sizeof( double ) * nn / 2 );

	rout = (double*) xmalloc ( sizeof( double ) * nn );
	iout = (double*) xmalloc ( sizeof( double ) * nn );

	for( i = 0; i < nn; i++ ) {
		bit_reverse[i] = _fft_reverse_bits( i );
	}
	
	for( i = 0; i < nn / 2; i++ ) {
		j = 2 * PI * i / nn;
		costable[i] = cos( j );
		sintable[i] = sin( j );
   	}

#else

	nn = points;

	if( rout )
		free( rout );
	if( rin )
		free( rin );
	if( have_plan )
		rfftw_destroy_plan( p );

	rin = (fftw_real*) xmalloc( sizeof( fftw_real ) * nn );
	rout = (fftw_real*) xmalloc( sizeof( fftw_real ) * nn );

	p = rfftw_create_plan( nn, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE );
	have_plan = 1;

#endif

	if( window )
		free( window );

	window = (double*) xmalloc( sizeof( double ) * nn );
	for ( c = 0; c < nn / 2; c++ )
		window[c] = window[nn - c - 1] = 0.54 - 0.46 * cos( 2 * PI * c / nn );

	return 0;
}
コード例 #4
0
void test_in_place(int n, int istride,
		   int howmany, fftw_direction dir,
		   fftw_plan validated_plan, int specific)
{
     fftw_complex *in2, *out2;
     fftw_real *in1, *out1, *out3;
     fftw_plan plan;
     int i, j;
     int ostride = istride;
     int flags = measure_flag | wisdom_flag | FFTW_IN_PLACE;

     if (coinflip())
	  flags |= FFTW_THREADSAFE;

     in1 = (fftw_real *) fftw_malloc(istride * n * sizeof(fftw_real) * howmany);
     in2 = (fftw_complex *) fftw_malloc(n * sizeof(fftw_complex));
     out1 = in1;
     out2 = (fftw_complex *) fftw_malloc(n * sizeof(fftw_complex));
     out3 = (fftw_real *) fftw_malloc(n * sizeof(fftw_real));

     if (!specific)
	  plan = rfftw_create_plan(n, dir, flags);
     else
	  plan = rfftw_create_plan_specific(n, dir, flags,
					    in1, istride, out1, ostride);
     CHECK(plan != NULL, "can't create plan");

     /* generate random inputs */
     fill_random(in1, n, istride);
     for (j = 1; j < howmany; ++j)
	  for (i = 0; i < n; ++i)
	       in1[(j * n + i) * istride] = in1[i * istride];

     /* copy random inputs to complex array for comparison with fftw: */
     if (dir == FFTW_REAL_TO_COMPLEX)
	  for (i = 0; i < n; ++i) {
	       c_re(in2[i]) = in1[i * istride];
	       c_im(in2[i]) = 0.0;
     } else {
	  int n2 = (n + 1) / 2;
	  c_re(in2[0]) = in1[0];
	  c_im(in2[0]) = 0.0;
	  for (i = 1; i < n2; ++i) {
	       c_re(in2[i]) = in1[i * istride];
	       c_im(in2[i]) = in1[(n - i) * istride];
	  }
	  if (n2 * 2 == n) {
	       c_re(in2[n2]) = in1[n2 * istride];
	       c_im(in2[n2]) = 0.0;
	       ++i;
	  }
	  for (; i < n; ++i) {
	       c_re(in2[i]) = c_re(in2[n - i]);
	       c_im(in2[i]) = -c_im(in2[n - i]);
	  }
     }

     /* 
      * fill in other positions of the array, to make sure that
      * rfftw doesn't overwrite them 
      */
     for (j = 1; j < istride; ++j)
	  for (i = 0; i < n * howmany; ++i)
	       in1[i * istride + j] = i * istride + j;

     WHEN_VERBOSE(2, rfftw_print_plan(plan));

     /* fft-ize */
     if (howmany != 1 || istride != 1 || coinflip())
	  rfftw(plan, howmany, in1, istride, n * istride, 0, 0, 0);
     else
	  rfftw_one(plan, in1, NULL);

     rfftw_destroy_plan(plan);

     /* check for overwriting */
     for (j = 1; j < ostride; ++j)
	  for (i = 0; i < n * howmany; ++i)
	       CHECK(out1[i * ostride + j] == i * ostride + j,
		     "output has been overwritten");

     fftw(validated_plan, 1, in2, 1, n, out2, 1, n);

     if (dir == FFTW_REAL_TO_COMPLEX) {
	  int n2 = (n + 1) / 2;
	  out3[0] = c_re(out2[0]);
	  for (i = 1; i < n2; ++i) {
	       out3[i] = c_re(out2[i]);
	       out3[n - i] = c_im(out2[i]);
	  }
	  if (n2 * 2 == n)
	       out3[n2] = c_re(out2[n2]);
     } else {
	  for (i = 0; i < n; ++i)
	       out3[i] = c_re(out2[i]);
     }

     for (j = 0; j < howmany; ++j)
	  CHECK(compute_error(out1 + j * n * ostride, ostride, out3, 1, n)
		< TOLERANCE,
		"test_in_place: wrong answer");
     WHEN_VERBOSE(2, printf("OK\n"));

     fftw_free(in1);
     fftw_free(in2);
     fftw_free(out2);
     fftw_free(out3);
}
コード例 #5
0
ファイル: main.c プロジェクト: jdm/autotune-stuff
int main (int argc, char** argv)
{
  extern int abs_flg; /* flag for absolute/relative cutoff  */
  extern double adj_pitch;
  extern double pitch_shift;
  extern int n_pitch;

  char *file_midi = NULL;
  char *file_wav = NULL;
  char *file_patch = NULL;

  int i;

  // default value
  double cut_ratio; // log10 of cutoff ratio for scale velocity
  cut_ratio = -5.0;
  double rel_cut_ratio; // log10 of cutoff ratio relative to average
  rel_cut_ratio = 1.0; // this value is ignored when abs_flg == 1
  long len = 2048;
  int flag_window = 3; // hanning window
  /* for 76 keys piano  */
  int notetop = 103; /* G8  */
  int notelow = 28; /* E2  */

  abs_flg = 1;

  long hop = 0;
  int show_help = 0;
  int show_version = 0;
  adj_pitch = 0.0;
  /* to select peaks in a note  */
  int peak_threshold = 128; /* this means no peak search  */

  int flag_phase = 1; // use the phase correction
  int psub_n = 0;
  double psub_f = 0.0;
  double oct_f = 0.0;
  for (i = 1; i < argc; i++)
    {
      if ((strcmp (argv[i], "-input" ) == 0)
	 || (strcmp (argv[i], "-i" ) == 0))
	{
	  if ( i+1 < argc )
	    {
	      file_wav = (char *)malloc (sizeof (char)
					 * (strlen (argv[++i]) + 1));
	      CHECK_MALLOC (file_wav, "main");
	      strcpy (file_wav, argv[i]);
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if ((strcmp (argv[i], "-output" ) == 0)
	      || (strcmp (argv[i], "-o" ) == 0))
	{
	  if ( i+1 < argc )
	    {
	      file_midi = (char *)malloc (sizeof (char)
					 * (strlen (argv[++i]) + 1));
	      CHECK_MALLOC (file_midi, "main");
	      strcpy (file_midi, argv[i]);
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if ((strcmp (argv[i], "--cutoff") == 0)
	       || (strcmp (argv[i], "-c") == 0))
	{
	  if ( i+1 < argc )
	    {
	      cut_ratio = atof (argv[++i]);
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if ((strcmp (argv[i], "--top") == 0)
	       || (strcmp (argv[i], "-t") == 0))
	{
	  if ( i+1 < argc )
	    {
	      notetop = atoi( argv[++i] );
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if ((strcmp (argv[i], "--bottom") == 0)
	       || (strcmp (argv[i], "-b") == 0))
	{
	  if ( i+1 < argc )
	    {
	      notelow = atoi (argv[++i]);
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if ((strcmp (argv[i], "--window") == 0)
	       || (strcmp (argv[i], "-w") == 0))
	{
	  if ( i+1 < argc )
	    {
	      flag_window = atoi (argv[++i]);
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if ( strcmp (argv[i], "-n") == 0)
	{
	  if ( i+1 < argc )
	    {
	      len = atoi (argv[++i]);
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if ((strcmp (argv[i], "--shift") == 0)
	       || (strcmp (argv[i], "-s") == 0))
	{
	  if ( i+1 < argc )
	    {
	      hop = atoi (argv[++i]);
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if ((strcmp (argv[i], "--patch") == 0)
	       || (strcmp (argv[i], "-p") == 0))
	{
	  if ( i+1 < argc )
	    {
	      file_patch = argv[++i];
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if ((strcmp (argv[i], "--relative") == 0)
	       || (strcmp (argv[i], "-r") == 0))
	{
	  if ( i+1 < argc )
	    {
	      rel_cut_ratio = atof (argv[++i]);
	      abs_flg = 0;
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if ((strcmp (argv[i], "--peak") == 0)
	       || (strcmp (argv[i], "-k") == 0))
	{
	  if ( i+1 < argc )
	    {
	      peak_threshold = atoi (argv[++i]);
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if ((strcmp (argv[i], "--adjust") == 0)
	       || (strcmp (argv[i], "-a") == 0))
	{
	  if ( i+1 < argc )
	    {
	      adj_pitch = atof (argv[++i]);
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if ((strcmp (argv[i], "--help") == 0)
	       || (strcmp (argv[i], "-h") == 0))
	{
	  show_help = 1;
	  break;
	}
      else if (strcmp (argv[i], "-nophase") == 0)
	{
	  flag_phase = 0;
	}
      else if (strcmp (argv[i], "-psub-n") == 0)
	{
	  if ( i+1 < argc )
	    {
	      psub_n = atoi (argv[++i]);
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if (strcmp (argv[i], "-psub-f") == 0)
	{
	  if ( i+1 < argc )
	    {
	      psub_f = atof (argv[++i]);
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if (strcmp (argv[i], "-oct") == 0)
	{
	  if ( i+1 < argc )
	    {
	      oct_f = atof (argv[++i]);
	    }
	  else
	    {
	      show_help = 1;
	      break;
	    }
	}
      else if (strcmp (argv[i], "-v") == 0 ||
	       strcmp (argv[i], "--version") == 0)
	{
	  show_version = 1;
	}
      else
	{
	  show_help = 1;
	}
    }
  if (show_help == 1)
    {
      print_usage (argv[0]);
      exit (1);
    }
  else if (show_version == 1)
    {
      print_version ();
      exit (1);
    }

  if (flag_window < 0 || flag_window > 6)
    {
      flag_window = 0;
    }
  if (hop == 0)
    {
      hop = len / 4;
    }
  if (psub_n == 0) psub_f = 0.0;
  if (psub_f == 0.0) psub_n = 0;


  struct WAON_notes *notes = WAON_notes_init();
  CHECK_MALLOC (notes, "main");
  char vel[128];     // velocity at the current step
  int on_event[128]; // event index of struct WAON_notes.
  for (i = 0; i < 128; i ++)
    {
      vel[i]      = 0;
      on_event[i] = -1;
    }

  // allocate buffers
  double *left  = (double *)malloc (sizeof (double) * len);
  double *right = (double *)malloc (sizeof (double) * len);
  CHECK_MALLOC (left,  "main");
  CHECK_MALLOC (right, "main");

  double *x = NULL; /* wave data for FFT  */
  double *y = NULL; /* spectrum data for FFT */ 
#ifdef FFTW2
  x = (double *)malloc (sizeof (double) * len);
  y = (double *)malloc (sizeof (double) * len);
#else // FFTW3
  x = (double *)fftw_malloc (sizeof (double) * len);
  y = (double *)fftw_malloc (sizeof (double) * len);
#endif // FFTW2
  CHECK_MALLOC (x, "main");
  CHECK_MALLOC (y, "main");

  /* power spectrum  */
  double *p = (double *)malloc (sizeof (double) * (len / 2 + 1));
  CHECK_MALLOC (p, "main");

  double *p0 = NULL;
  double *dphi = NULL;
  double *ph0 = NULL;
  double *ph1 = NULL;
  if (flag_phase != 0)
    {
      p0 = (double *)malloc (sizeof (double) * (len / 2 + 1));
      CHECK_MALLOC (p0, "main");

      dphi = (double *)malloc (sizeof (double) * (len / 2 + 1));
      CHECK_MALLOC (dphi, "main");

      ph0 = (double *)malloc (sizeof (double) * (len/2+1));
      ph1 = (double *)malloc (sizeof (double) * (len/2+1));
      CHECK_MALLOC (ph0, "main");
      CHECK_MALLOC (ph1, "main");
    }

  double *pmidi = (double *)malloc (sizeof (double) * 128);
  CHECK_MALLOC (pmidi, "main");


  // MIDI output
  if (file_midi == NULL)
    {
      file_midi = (char *)malloc (sizeof (char) * (strlen("output.mid") + 1));
      CHECK_MALLOC (file_midi, "main");
      strcpy (file_midi, "output.mid");
    }

  // open input wav file
  if (file_wav == NULL)
    {
      file_wav = (char *) malloc (sizeof (char) * 2);
      CHECK_MALLOC (file_wav, "main");
      file_wav [0] = '-';
    }
  SF_INFO sfinfo;
  SNDFILE *sf = sf_open (file_wav, SFM_READ, &sfinfo);
  if (sf == NULL)
    {
      fprintf (stderr, "Can't open input file %s : %s\n",
	       file_wav, strerror (errno));
      exit (1);
    }
  sndfile_print_info (&sfinfo);


  // check stereo or mono
  if (sfinfo.channels != 2 && sfinfo.channels != 1)
    {
      fprintf (stderr, "only mono and stereo inputs are supported.\n");
      exit (1);
    }


  // time-period for FFT (inverse of smallest frequency)
  double t0 = (double)len/(double)sfinfo.samplerate;

  // weight of window function for FFT
  double den = init_den (len, flag_window);

  /* set range to analyse (search notes) */
  /* -- after 't0' is calculated  */
  int i0 = (int)(mid2freq[notelow]*t0 - 0.5);
  int i1 = (int)(mid2freq[notetop]*t0 - 0.5)+1;
  if (i0 <= 0)
    {
      i0 = 1; // i0=0 means DC component (frequency = 0)
    }
  if (i1 >= (len/2))
    {
      i1 = len/2 - 1;
    }

  // init patch
  init_patch (file_patch, len, flag_window);
  /*                      ^^^ len could be given by option separately  */

  // initialization plan for FFTW
#ifdef FFTW2
  rfftw_plan plan;
  plan = rfftw_create_plan (len, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE);
#else // FFTW3
  fftw_plan plan;
  plan = fftw_plan_r2r_1d (len, x, y, FFTW_R2HC, FFTW_ESTIMATE);
#endif

  // for first step
  if (hop != len)
    {
      if (sndfile_read (sf, sfinfo,
			left + hop,
			right + hop,
			(len - hop))
	  != (len - hop))
	{
	  fprintf (stderr, "No Wav Data!\n");
	  exit(0);
	}
    }

  /** main loop (icnt) **/
  pitch_shift = 0.0;
  n_pitch = 0;
  int icnt; /* counter  */
  for (icnt=0; ; icnt++)
    {
      // shift
      for (i = 0; i < len - hop; i ++)
	{
	  if (sfinfo.channels == 2) // stereo
	    {
	      left  [i] = left  [i + hop];
	      right [i] = right [i + hop];
	    }
	  else // mono
	    {
	      left  [i] = left  [i + hop];
	    }
	}
      // read from wav
      if (sndfile_read (sf, sfinfo,
			left  + (len - hop),
			right + (len - hop),
			hop)
	  != hop)
	{
	  fprintf (stderr, "WaoN : end of file.\n");
	  break;
	}

      // set double table x[] for FFT
      for (i = 0; i < len; i ++)
	{
	  if (sfinfo.channels == 2) // stereo
	    {
	      x [i] = 0.5 * (left [i] + right [i]);
	    }
	  else // mono
	    {
	      x [i] = left [i];
	    }
	}

      /**
       * stage 1: calc power spectrum
       */
      windowing (len, x, flag_window, 1.0, x);

      /* FFTW library  */
#ifdef FFTW2
      rfftw_one (plan, x, y);
#else // FFTW3
      fftw_execute (plan); // x[] -> y[]
#endif

      if (flag_phase == 0)
	{
	  // no phase-vocoder correction
	  HC_to_amp2 (len, y, den, p);
	}
      else
	{
	  // with phase-vocoder correction
	  HC_to_polar2 (len, y, 0, den, p, ph1);

	  if (icnt == 0) // first step, so no ph0[] yet
	    {
	      for (i = 0; i < (len/2+1); ++i) // full span
		{
		  // no correction
		  dphi[i] = 0.0;

		  // backup the phase for the next step
		  p0  [i] = p   [i];
		  ph0 [i] = ph1 [i];
		}	  
	    }
	  else // icnt > 0
	    {
	      // freq correction by phase difference
	      for (i = 0; i < (len/2+1); ++i) // full span
		{
		  double twopi = 2.0 * M_PI;
		  //double dphi;
		  dphi[i] = ph1[i] - ph0[i]
		    - twopi * (double)i / (double)len * (double)hop;
		  for (; dphi[i] >= M_PI; dphi[i] -= twopi);
		  for (; dphi[i] < -M_PI; dphi[i] += twopi);

		  // frequency correction
		  // NOTE: freq is (i / len + dphi) * samplerate [Hz]
		  dphi[i] = dphi[i] / twopi / (double)hop;

		  // backup the phase for the next step
		  p0  [i] = p   [i];
		  ph0 [i] = ph1 [i];

		  // then, average the power for the analysis
		  p[i] = 0.5 *(sqrt (p[i]) + sqrt (p0[i]));
		  p[i] = p[i] * p[i];
		}
	    }
	}

      // drum-removal process
      if (psub_n != 0)
	{
	  power_subtract_ave (len, p, psub_n, psub_f);
	}

      // octave-removal process
      if (oct_f != 0.0)
	{
	  power_subtract_octave (len, p, oct_f);
	}

      /**
       * stage 2: pickup notes
       */
      /* new code
      if (flag_phase == 0)
	{
	  average_FFT_into_midi (len, (double)sfinfo.samplerate,
				 p, NULL,
				 pmidi);
	}
      else
	{
	  average_FFT_into_midi (len, (double)sfinfo.samplerate,
				 p, dphi,
				 pmidi);
	}
      pickup_notes (pmidi,
		    cut_ratio, rel_cut_ratio,
		    notelow, notetop,
		    vel);
      */

      /* old code */
      if (flag_phase == 0)
	{
	  // no phase-vocoder correction
	  note_intensity (p, NULL,
			  cut_ratio, rel_cut_ratio, i0, i1, t0, vel);
	}
      else
	{
	  // with phase-vocoder correction
	  // make corrected frequency (i / len + dphi) * samplerate [Hz]
	  for (i = 0; i < (len/2+1); ++i) // full span
	    {
	      dphi[i] = ((double)i / (double)len + dphi[i])
		* (double)sfinfo.samplerate;
	    }
	  note_intensity (p, dphi,
			  cut_ratio, rel_cut_ratio, i0, i1, t0, vel);
	}

      /**
       * stage 3: check previous time for note-on/off
       */
      WAON_notes_check (notes, icnt, vel, on_event,
			8, 0, peak_threshold);
    }


  // clean notes
  WAON_notes_regulate (notes);

  WAON_notes_remove_shortnotes (notes, 1, 64);
  WAON_notes_remove_shortnotes (notes, 2, 28);

  WAON_notes_remove_octaves (notes);


  /*
  pitch_shift /= (double) n_pitch;
  fprintf (stderr, "WaoN : difference of pitch = %f ( + %f )\n",
	   -(pitch_shift - 0.5),
	   adj_pitch);
  */

  /* div is the divisions for one beat (quater-note).
   * here we assume 120 BPM, that is, 1 beat is 0.5 sec.
   * note: (hop / ft->rate) = duration for 1 step (sec) */
  long div = (long)(0.5 * (double)sfinfo.samplerate / (double) hop);
  fprintf (stderr, "division = %ld\n", div);
  fprintf (stderr, "WaoN : # of events = %d\n", notes->n);

  WAON_notes_output_midi (notes, div, file_midi);


#ifdef FFTW2
  rfftw_destroy_plan (plan);
#else
  fftw_destroy_plan (plan);
#endif /* FFTW2 */


  WAON_notes_free (notes);
  free (left);
  free (right);
  free (x);
  free (y);
  free (p);
  if (p0 != NULL) free (p0);
  if (dphi != NULL) free (dphi);
  if (ph0 != NULL) free (ph0);
  if (ph1 != NULL) free (ph1);

  if (pmidi != NULL) free (pmidi);

  if (file_wav  != NULL) free (file_wav);
  if (file_midi != NULL) free (file_midi);

  sf_close (sf);

  return 0;
}