/* play 100 milisecond and return */ gint play_100msec (gpointer data) { extern struct pv_complex *pv; extern long play_cur; long len_100msec = (long)(0.1 /* sec */ * pv->sfinfo->samplerate /* Hz */); // draw indicator draw_play_indicator ((GtkWidget *)data); extern int WIN_wav_cur; extern int WIN_wav_scale; extern int WIN_wav_width; long frame0; long frame1; frame0 = (long) WIN_wav_cur; frame1 = frame0 + (long)(WIN_wav_scale * WIN_wav_width) - 1; if (frame1 >= pv->sfinfo->frames) frame1 = (long)pv->sfinfo->frames - 1; if (play_cur < frame0) play_cur = frame0; if (play_cur >= frame1) play_cur = frame1; long l; for (l = 0; l < len_100msec; l += pv->hop_syn) { long len_play = pv_complex_play_step (pv, play_cur); if (len_play < pv->hop_res) { flag_play = 0; // stop playing // rewind if (pv->hop_ana >= 0.0) play_cur = frame0; else play_cur = frame1; // if FAIL is returned, this timeout is removed return FALSE; } // increment play_cur play_cur += pv->hop_ana; // check the boundary if (play_cur < frame0 || play_cur + pv->hop_ana >= frame1) { // rewind if (pv->hop_ana >= 0.0) play_cur = frame0; else play_cur = frame1; } } return TRUE; }
/* play 100 milisecond and return * INPUT * pv : struct pv_complex * play_cur : current frame * frame0, frame1 : the loop range * OUTPUT */ int play_100msec_curses (struct pv_complex * pv, long * play_cur, long frame0, long frame1) { extern int flag_nofft; long len_100msec = (long)(0.1 /* sec */ * pv->sfinfo->samplerate /* Hz */); long l; /* counting output frames */ if (*play_cur < frame0) *play_cur = frame0; if (*play_cur >= frame1) *play_cur = frame1; for (l = 0; l < len_100msec; l += pv->hop_syn) { long len_play; if (flag_nofft == 0) len_play = pv_complex_play_step (pv, *play_cur); else len_play = pv_nofft_play_step (pv, *play_cur); if (len_play < pv->hop_res) { /* end of file */ /* rewind */ if (pv->hop_ana >= 0.0) *play_cur = frame0; else *play_cur = frame1; } /* increment play_cur */ *play_cur += pv->hop_ana; /* check the boundary */ if (*play_cur < frame0 || *play_cur + pv->hop_ana >= frame1) { /* rewind */ if (pv->hop_ana >= 0.0) *play_cur = frame0; else *play_cur = frame1; } } return 1; /* TRUE */ }
/* phase vocoder by complex arithmetics with fixed hops. * t_i - s_i = u_i - u_{i-1} = hop * where s_i and t_i are the times for two analysis FFT * and u_i is the time for the synthesis FFT at step i * Reference: M.Puckette (1995) * INPUT * flag_lock : 0 == no phase lock is applied * 1 == loose phase lock is applied * rate : time-streching rate * pitch_shift : in the unit of half-note */ void pv_complex (const char * file, const char * outfile, double rate, double pitch_shift, long len, long hop_syn, int flag_window, int flag_lock) { long hop_res = (long)((double)hop_syn * pow (2.0, - pitch_shift / 12.0)); long hop_ana = (long)((double)hop_res * rate); long cur; struct pv_complex * pv = pv_complex_init (len, hop_syn, flag_window); SNDFILE * sf = NULL; SF_INFO sfinfo; SNDFILE * sfout = NULL; SF_INFO sfout_info; ao_device * ao = NULL; pv->hop_res = hop_res; pv->hop_ana = hop_ana; /*pv->pitch_shift = pitch_shift; */ /* open file */ memset (&sfinfo, 0, sizeof (sfinfo)); sf = sf_open (file, SFM_READ, &sfinfo); if (sf == NULL) { fprintf (stderr, "fail to open %s\n", file); exit (1); } sndfile_print_info (&sfinfo); pv_complex_set_input (pv, sf, &sfinfo); if (outfile == NULL) { ao = ao_init_16_stereo (sfinfo.samplerate, 1 /* verbose */); pv_complex_set_output_ao (pv, ao); } else { sfout = sndfile_open_for_write (&sfout_info, outfile, sfinfo.samplerate, sfinfo.channels); if (sfout == NULL) { fprintf (stderr, "fail to open file %s\n", outfile); exit (1); } pv_complex_set_output_sf (pv, sfout, &sfout_info); } pv->flag_lock = flag_lock; for (cur = 0; cur < (long)sfinfo.frames; cur += pv->hop_ana) { long len_play = pv_complex_play_step (pv, cur); if (len_play < pv->hop_res) { break; } } if (outfile == NULL) { ao_close (ao); } else { /* frames left in l_out[] and r_out[] */ sndfile_write (sfout, sfout_info, pv->l_out, pv->r_out, len); sf_write_sync (sfout); sf_close (sfout); } pv_complex_free (pv); sf_close (sf) ; }