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); }
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; }
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; }
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); }
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; }