1 /* real-time phase vocoder with curses interface and JACK
2  * Copyright (C) 2007 Kengo Ichiki <kichiki@users.sourceforge.net>
3  * $Id: jack-pv.c,v 1.1 2007/10/29 02:48:41 kichiki Exp $
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  */
19 #include <stdio.h>
20 #include <unistd.h> // sleep()
21 #include <stdlib.h>
22 #include <string.h>
23 #include <math.h> // pow()
24 
25 #include <ao/ao.h>
26 #include "ao-wrapper.h"
27 #include <sndfile.h>
28 #include "pv-conventional.h" // get_scale_factor_for_window ()
29 #include <curses.h>
30 
31 #include <jack/jack.h>
32 #include <jack/transport.h>
33 
34 #include "pv-complex.h" // struct pv_complex
35 #include "hc.h" // HC_complex_phase_vocoder()
36 #include "memory-check.h" // CHECK_MALLOC
37 
38 #include "jack-pv.h"
39 
40 // check
41 FILE *err_log = NULL;
42 
43 /*
44  * OUTPUT
45  *  returned value : 1 if x[i] = 0 for i = 0 to n-1
46  *                   0 otherwise
47  */
48 static int
check_zero(int n,const double * x)49 check_zero (int n, const double *x)
50 {
51   int i;
52 
53   for (i = 0; i < n; i ++)
54     {
55       if (x[i] != 0.0) return 1;
56     }
57   return 0;
58 }
59 
60 /* play one hop_in by the phase vocoder:
61  * phase vocoder by complex arithmetics with fixed hops.
62  *   t_i - s_i = u_i - u_{i-1} = hop
63  *   where s_i and t_i are the times for two analysis FFT
64  *   and u_i is the time for the synthesis FFT at step i
65  * Reference: M.Puckette (1995)
66  * INPUT
67  *  pv : struct pv_complex
68  *  cur : current frame to play.
69  *        you have to increment this by yourself.
70  *  pv->flag_lock : 0 == no phase lock
71  *                  1 == loose phase lock
72  * OUTPUT
73  *  left[pv->hop_res], right[pv->hop_res] :
74  *  returned value : hop_res (not hop_syn).
75  */
76 int
jack_pv_complex_play_step(struct pv_complex * pv,long cur,double * left,double * right)77 jack_pv_complex_play_step (struct pv_complex *pv,
78 			   long cur,
79 			   double *left, double *right)
80 {
81   static double *l_fs  = NULL;
82   static double *r_fs  = NULL;
83   static double *l_ft  = NULL;
84   static double *r_ft  = NULL;
85   static double *l_tmp = NULL;
86   static double *r_tmp = NULL;
87 
88   if (l_fs == NULL)
89     {
90       l_fs = (double *)malloc (pv->len * sizeof (double));
91       r_fs = (double *)malloc (pv->len * sizeof (double));
92       CHECK_MALLOC (l_fs, "pv_complex_play_step");
93       CHECK_MALLOC (r_fs, "pv_complex_play_step");
94 
95       l_ft = (double *)malloc (pv->len * sizeof (double));
96       r_ft = (double *)malloc (pv->len * sizeof (double));
97       CHECK_MALLOC (l_ft, "pv_complex_play_step");
98       CHECK_MALLOC (r_ft, "pv_complex_play_step");
99 
100       l_tmp = (double *)malloc (pv->len * sizeof (double));
101       r_tmp = (double *)malloc (pv->len * sizeof (double));
102       CHECK_MALLOC (l_tmp, "pv_complex_play_step");
103       CHECK_MALLOC (r_tmp, "pv_complex_play_step");
104     }
105 
106   long status;
107   // read the starting frame (cur)
108   status = read_and_FFT_stereo (pv, cur, l_fs, r_fs);
109   if (status != pv->len)
110     {
111       return 0; // no output
112     }
113 
114   // read the terminal frame (cur + hop_syn)
115   status = read_and_FFT_stereo (pv, cur + pv->hop_syn, l_ft, r_ft);
116   if (status != pv->len)
117     {
118       return 0; // no output
119     }
120 
121   int flag_left_cur;
122   int flag_right_cur;
123   if (check_zero (pv->len, l_fs) == 0 ||
124       check_zero (pv->len, l_ft) == 0)
125     {
126       flag_left_cur = 0; // inactive
127     }
128   else
129     {
130       flag_left_cur = 1; // active
131     }
132 
133   if (check_zero (pv->len, r_fs) == 0 ||
134       check_zero (pv->len, r_ft) == 0)
135     {
136       flag_right_cur = 0; // inactive
137     }
138   else
139     {
140       flag_right_cur = 1; // active
141     }
142 
143 
144   int i;
145 
146   // left channel
147   if (flag_left_cur == 1)
148     {
149       // check l_f_old[]
150       if (pv->flag_left == 0)
151 	{
152 	  if (pv->flag_lock == 0) // no phase lock
153 	    {
154 	      for (i = 0; i < pv->len; i ++)
155 		{
156 		  pv->l_f_old [i] = l_fs [i];
157 		}
158 	    }
159 	  else // loose phase lock
160 	    {
161 	      // apply loose phase lock
162 	      HC_puckette_lock (pv->len, l_fs, pv->l_f_old);
163 	    }
164 
165 	  pv->flag_left = 1;
166 	}
167 
168       // generate the frame (out_0 + (n+1) * hop_syn), that is, "u_i"
169       if (pv->flag_lock == 0) // no phase lock
170 	{
171 	  // Y[u_i] = X[t_i] (Y[u_{i-1}]/X[s_i]) / |Y[u_{i-1}]/X[s_i]|
172 	  HC_complex_phase_vocoder (pv->len, l_fs, l_ft, pv->l_f_old,
173 				    pv->l_f_old);
174 	  // already backed up for the next step in [lr]_f_old[]
175 	  apply_invFFT_mono (pv, pv->l_f_old, pv->window_scale, pv->l_out);
176 	}
177       else // loose phase lock
178 	{
179 	  // Y[u_i] = X[t_i] (Z[u_{i-1}]/X[s_i]) / |Z[u_{i-1}]/X[s_i]|
180 	  HC_complex_phase_vocoder (pv->len, l_fs, l_ft, pv->l_f_old,
181 				    l_tmp);
182 	  // apply loose phase lock and store for the next step
183 	  HC_puckette_lock (pv->len, l_tmp, pv->l_f_old);
184 
185 	  apply_invFFT_mono (pv, l_tmp, pv->window_scale, pv->l_out);
186 	}
187     }
188 
189 
190   // right channel
191   if (flag_right_cur == 1)
192     {
193       // check l_f_old[]
194       if (pv->flag_right == 0)
195 	{
196 	  if (pv->flag_lock == 0) // no phase lock
197 	    {
198 	      for (i = 0; i < pv->len; i ++)
199 		{
200 		  pv->r_f_old [i] = r_fs [i];
201 		}
202 	    }
203 	  else // loose phase lock
204 	    {
205 	      // apply loose phase lock
206 	      HC_puckette_lock (pv->len, r_fs, pv->r_f_old);
207 	    }
208 	  pv->flag_right = 1;
209 	}
210 
211       // generate the frame (out_0 + (n+1) * hop_syn), that is, "u_i"
212       if (pv->flag_lock == 0) // no phase lock
213 	{
214 	  // Y[u_i] = X[t_i] (Y[u_{i-1}]/X[s_i]) / |Y[u_{i-1}]/X[s_i]|
215 	  HC_complex_phase_vocoder (pv->len, r_fs, r_ft, pv->r_f_old,
216 				    pv->r_f_old);
217 	  // already backed up for the next step in [lr]_f_old[]
218 	  apply_invFFT_mono (pv, pv->r_f_old, pv->window_scale, pv->r_out);
219 	}
220       else // loose phase lock
221 	{
222 	  // Y[u_i] = X[t_i] (Z[u_{i-1}]/X[s_i]) / |Z[u_{i-1}]/X[s_i]|
223 	  HC_complex_phase_vocoder (pv->len, r_fs, r_ft, pv->r_f_old,
224 				    r_tmp);
225 	  // apply loose phase lock and store for the next step
226 	  HC_puckette_lock (pv->len, r_tmp, pv->r_f_old);
227 
228 	  apply_invFFT_mono (pv, r_tmp, pv->window_scale, pv->r_out);
229 	}
230     }
231 
232 
233   // output
234   //status = pv_complex_play_resample (pv);
235   if (pv->hop_syn != pv->hop_res)
236     {
237       pv_complex_resample (pv, left, right);
238     }
239   else
240     {
241       for (i = 0; i < pv->hop_res; i ++)
242 	{
243 	  left[i]  = pv->l_out[i];
244 	  right[i] = pv->r_out[i];
245 	}
246     }
247 
248 
249   /* shift [lr]_out by hop_syn */
250   for (i = 0; i < pv->len; i ++)
251     {
252       pv->l_out [i] = pv->l_out [i + pv->hop_syn];
253       pv->r_out [i] = pv->r_out [i + pv->hop_syn];
254     }
255   for (i = pv->len; i < pv->len + pv->hop_syn; i ++)
256     {
257       pv->l_out [i] = 0.0;
258       pv->r_out [i] = 0.0;
259     }
260 
261   return (pv->hop_res);
262 }
263 
264 /**
265  * The process callback for this JACK application is called in a
266  * special realtime thread once for each audio cycle.
267  *
268  * This client follows a simple rule: when the JACK transport is
269  * running, copy the input port to the output.  When it stops, exit.
270  */
271 int
my_jack_process(jack_nframes_t nframes,void * arg)272 my_jack_process (jack_nframes_t nframes, void *arg)
273 {
274   static long play_cur = 0;
275 
276   struct pv_jack *pv_jack = (struct pv_jack *)arg;
277 
278   static jack_default_audio_sample_t *in = NULL;
279   static jack_nframes_t in_len = 0;
280   if (in == NULL)
281     {
282       in = (jack_default_audio_sample_t *)malloc
283 	(sizeof (jack_default_audio_sample_t) * nframes);
284       in_len = nframes;
285     }
286   else if (in_len < nframes)
287     {
288       in = (jack_default_audio_sample_t *)realloc
289 	(in,
290 	 sizeof (jack_default_audio_sample_t) * nframes);
291       in_len = nframes;
292     }
293 
294   static double *left  = NULL;
295   static double *right = NULL;
296   static int hop_res0 = 0;
297   static int cur = 0;
298   if (left == NULL)
299     {
300       left  = (double *)malloc (sizeof (double) * pv_jack->pv->hop_res);
301       right = (double *)malloc (sizeof (double) * pv_jack->pv->hop_res);
302       CHECK_MALLOC (left,  "my_jack_process");
303       CHECK_MALLOC (right, "my_jack_process");
304       hop_res0 = pv_jack->pv->hop_res;
305       cur = hop_res0; // no data left
306     }
307   else if (hop_res0 < pv_jack->pv->hop_res)
308     {
309       left  = (double *)realloc (left,  sizeof (double) * pv_jack->pv->hop_res);
310       right = (double *)realloc (right, sizeof (double) * pv_jack->pv->hop_res);
311       CHECK_MALLOC (left,  "my_jack_process");
312       CHECK_MALLOC (right, "my_jack_process");
313       hop_res0 = pv_jack->pv->hop_res;
314       cur = hop_res0; // no data left
315     }
316 
317   // check
318   extern FILE *err_log;
319   fprintf (err_log, "cur = %d\n", cur);
320 
321   jack_transport_state_t ts = jack_transport_query (pv_jack->client, NULL);
322   if (ts == JackTransportRolling)
323     {
324       if (pv_jack->state == Init)
325 	{
326 	  pv_jack->state = Run;
327 	}
328 
329       jack_default_audio_sample_t *out
330 	= (jack_default_audio_sample_t *)
331 	jack_port_get_buffer (pv_jack->out, nframes);
332 
333       // the process for nframes
334       int i, j;
335       // paste the data left in left[] and right[] from cur to hop_res0
336       for (i = 0, j = cur;
337 	   (j < hop_res0) && (i < nframes);
338 	   i ++, j ++)
339 	{
340 	  in[i] = (jack_default_audio_sample_t)(0.5*(left[j] + right[j]));
341 	}
342       cur = j;
343       cur = cur % hop_res0;
344 
345       // if the data is not enough,
346       while (i < nframes)
347 	{
348 	  // process further data (next hop_res frames)
349 	  if (cur != 0)
350 	    {
351 	      fprintf (stderr, "cur update failed...\n");
352 	      fprintf (err_log, "cur update failed...\n");
353 	      fprintf (err_log, "cur = %d\n", cur);
354 	      fclose (err_log);
355 	      exit (1);
356 	    }
357 	  jack_pv_complex_play_step (pv_jack->pv, play_cur, left, right);
358 	  play_cur += pv_jack->pv->hop_ana;
359 
360 	  // then, paste the data in left[] and right[] from 0 to hop_res0
361 	  int j;
362 	  for (j = 0;
363 	       (j < hop_res0) && (i < nframes);
364 	       j ++, i ++)
365 	    {
366 	      in[i] = (jack_default_audio_sample_t)(0.5*(left[j] + right[j]));
367 	    }
368 	  cur = j;
369 	  cur = cur % hop_res0;
370 	}
371 
372       // now, the data in in[] is enough to pass jack server
373       memcpy (out, in,
374 	      sizeof (jack_default_audio_sample_t) * nframes);
375     }
376   else if (ts == JackTransportStopped)
377     {
378       if (pv_jack->state == Run)
379 	{
380 	  pv_jack->state = Exit;
381 	}
382     }
383 
384   return 0;
385 }
386 
387 /**
388  * JACK calls this shutdown_callback if the server ever shuts down or
389  * decides to disconnect the client.
390  */
391 void
jack_shutdown(void * arg)392 jack_shutdown (void *arg)
393 {
394   exit (1);
395 }
396 
397 /* start jack process for output (playback)
398  * INPUT
399  * OUTPUT
400  *  returned value : struct pv_jack *pv_jack.
401  */
402 struct pv_jack *
pv_jack_init(struct pv_complex * pv)403 pv_jack_init (struct pv_complex *pv)
404 {
405   struct pv_jack *pv_jack
406     = (struct pv_jack *)malloc (sizeof (struct pv_jack));
407   CHECK_MALLOC (pv_jack, "main");
408 
409   pv_jack->pv = pv;
410   pv_jack->state = Init;
411 
412 
413   char *client_name = (char *)malloc (sizeof (char) * 8);
414   strcpy (client_name, "jack-pv");
415 
416   const char *server_name = NULL;
417 
418   /* open a client connection to the JACK server */
419   jack_options_t options = JackNullOption;
420   jack_status_t jack_status;
421   pv_jack->client
422     = jack_client_open (client_name, options, &jack_status, server_name);
423   if (pv_jack->client == NULL)
424     {
425       fprintf (stderr, "jack_client_open() failed, "
426 	       "status = 0x%2.0x\n", jack_status);
427       if (jack_status & JackServerFailed)
428 	{
429 	  fprintf (stderr, "Unable to connect to JACK server\n");
430 	}
431       exit (1);
432     }
433   if (jack_status & JackServerStarted)
434     {
435       fprintf (stderr, "JACK server started\n");
436     }
437   if (jack_status & JackNameNotUnique)
438     {
439       free (client_name);
440       client_name = jack_get_client_name(pv_jack->client);
441       fprintf (stderr, "unique name `%s' assigned\n", client_name);
442     }
443 
444   /* tell the JACK server to call `process()' whenever
445      there is work to be done.
446   */
447   jack_set_process_callback (pv_jack->client, my_jack_process, pv_jack);
448 
449   /* tell the JACK server to call `jack_shutdown()' if
450      it ever shuts down, either entirely, or if it
451      just decides to stop calling us.
452   */
453   jack_on_shutdown (pv_jack->client, jack_shutdown, pv_jack);
454 
455 
456   /* display the current sample rate.
457    */
458   printf ("engine sample rate: %" PRIu32 "\n",
459 	  jack_get_sample_rate (pv_jack->client));
460 
461   /* create the output ports */
462   pv_jack->out = jack_port_register (pv_jack->client, "output",
463 				     JACK_DEFAULT_AUDIO_TYPE,
464 				     JackPortIsOutput, 0);
465 
466   if (pv_jack->out == NULL)
467     {
468       fprintf(stderr, "no more JACK ports available\n");
469       exit (1);
470     }
471 
472   /* Tell the JACK server that we are ready to roll.  Our
473    * process() callback will start running now. */
474   if (jack_activate (pv_jack->client))
475     {
476       fprintf (stderr, "cannot activate client");
477       exit (1);
478     }
479 
480   /* Connect the ports.  You can't do this before the client is
481    * activated, because we can't make connections to clients
482    * that aren't running.  Note the confusing (but necessary)
483    * orientation of the driver backend ports: playback ports are
484    * "input" to the backend, and capture ports are "output" from
485    * it.
486    */
487   const char **ports;
488   ports = jack_get_ports (pv_jack->client, NULL, NULL,
489 			  JackPortIsPhysical|JackPortIsInput);
490   if (ports == NULL)
491     {
492       fprintf(stderr, "no physical playback ports\n");
493       exit (1);
494     }
495   if (jack_connect (pv_jack->client, jack_port_name (pv_jack->out), ports[0]))
496     {
497       fprintf (stderr, "cannot connect output ports\n");
498     }
499   free (ports);
500 
501 
502   return (pv_jack);
503 }
504 
505 void
pv_jack_free(struct pv_jack * pv_jack)506 pv_jack_free (struct pv_jack *pv_jack)
507 {
508   if (pv_jack != NULL) free (pv_jack);
509 }
510 
511 
512 #define Y_file    (1)
513 #define Y_frames  (2)
514 #define Y_loop    (3)
515 
516 #define Y_rate    (5)
517 #define Y_pitch   (6)
518 #define Y_lock    (8)
519 #define Y_window  (10)
520 #define Y_len     (11)
521 #define Y_hop_syn (12)
522 #define Y_hop_ana (13)
523 #define Y_hop_res (14)
524 
525 #define Y_status  (16)
526 #define Y_comment (18)
527 
528 static void
curses_print_window(int flag_window)529 curses_print_window (int flag_window)
530 {
531   switch (flag_window)
532     {
533     case 0: // square (no window)
534       mvprintw (Y_window, 1, "window     : square  ");
535       break;
536     case 1: // parzen window
537       mvprintw (Y_window, 1, "window     : parzen  ");
538       break;
539     case 2: // welch window
540       mvprintw (Y_window, 1, "window     : welch   ");
541       break;
542     case 3: // hanning window
543       mvprintw (Y_window, 1, "window     : hanning ");
544       break;
545     case 4: // hamming window
546       mvprintw (Y_window, 1, "window     : hamming ");
547       break;
548     case 5: // blackman window
549       mvprintw (Y_window, 1, "window     : blackman");
550       break;
551     case 6: // steeper 30-dB/octave rolloff window
552       mvprintw (Y_window, 1, "window     : steeper ");
553       break;
554     }
555 }
556 
557 static void
curses_print_pitch(int pv_pitch)558 curses_print_pitch (int pv_pitch)
559 {
560   int oct;
561   int key;
562   if (pv_pitch < 0)
563     {
564       oct = (-pv_pitch-1) / 12; // -12 == -2 octaves
565       oct = -oct-1;
566       key = (-pv_pitch-1) % 12;
567       key = 11-key;
568     }
569   else
570     {
571       oct = pv_pitch / 12;
572       key = pv_pitch % 12;
573     }
574 
575   switch (key)
576     {
577     case 0: // 1 degree
578       mvprintw (Y_pitch,  1, "pitch      : C  %+2d (%+3d)", oct, pv_pitch);
579       break;
580     case 1: // 1.5
581       mvprintw (Y_pitch,  1, "pitch      : C# %+2d (%+3d)", oct, pv_pitch);
582       break;
583     case 2: // +2nd
584       mvprintw (Y_pitch,  1, "pitch      : D  %+2d (%+3d)", oct, pv_pitch);
585       break;
586     case 3: // 2.5
587       mvprintw (Y_pitch,  1, "pitch      : Eb %+2d (%+3d)", oct, pv_pitch);
588       break;
589     case 4: // +3
590       mvprintw (Y_pitch,  1, "pitch      : E  %+2d (%+3d)", oct, pv_pitch);
591       break;
592     case 5: // +4th
593       mvprintw (Y_pitch,  1, "pitch      : F  %+2d (%+3d)", oct, pv_pitch);
594       break;
595     case 6: // 4.5
596       mvprintw (Y_pitch,  1, "pitch      : F# %+2d (%+3d)", oct, pv_pitch);
597       break;
598     case 7: // +5th
599       mvprintw (Y_pitch,  1, "pitch      : G  %+2d (%+3d)", oct, pv_pitch);
600       break;
601     case 8: // 5.5
602       mvprintw (Y_pitch,  1, "pitch      : G# %+2d (%+3d)", oct, pv_pitch);
603       break;
604     case 9: // +6th
605       mvprintw (Y_pitch,  1, "pitch      : A  %+2d (%+3d)", oct, pv_pitch);
606       break;
607     case 10: // m7th
608       mvprintw (Y_pitch,  1, "pitch      : Bb %+2d (%+3d)", oct, pv_pitch);
609       break;
610     case 11: // M7
611       mvprintw (Y_pitch,  1, "pitch      : B  %+2d (%+3d)", oct, pv_pitch);
612       break;
613     default:
614       break;
615     }
616 }
617 
618 static void
curses_print_pv(const char * file,struct pv_complex * pv,int flag_play,long frame0,long frame1,double pv_pitch,double pv_rate)619 curses_print_pv (const char *file,
620 		 struct pv_complex *pv,
621 		 int flag_play,
622 		 long frame0, long frame1,
623 		 double pv_pitch,
624 		 double pv_rate)
625 {
626   mvprintw (0, 0, "========== pv ==========");
627   mvprintw (Y_file,   1, "file       : %s", file);
628   mvprintw (Y_frames, 1, "current    : %010ld / %010ld", 0, pv->sfinfo->frames);
629   mvprintw (Y_loop,   1, "loop       : %010ld - %010ld", frame0, frame1);
630   //mvprintw (Y_pitch,  1, "pitch      : %-5.0f", pv_pitch);
631   curses_print_pitch (pv_pitch);
632   mvprintw (Y_rate,   1, "rate       : %-5.1f", pv_rate);
633   mvprintw (Y_len,    1, "fft-len    : %06ld", pv->len);
634   mvprintw (Y_hop_syn,1, "hop(syn)   : %06ld", pv->hop_syn);
635   mvprintw (Y_hop_ana,1, "hop(ana)   : %06ld", pv->hop_ana);
636   mvprintw (Y_hop_res,1, "hop(res)   : %06ld", pv->hop_res);
637 
638   if (flag_play == 0) mvprintw(Y_status, 1, "status     : stop");
639   else                mvprintw(Y_status, 1, "status     : play");
640 
641   if (pv->flag_lock == 0) mvprintw(Y_lock, 1, "phase-lock : off");
642   else                    mvprintw(Y_lock, 1, "phase-lock : on ");
643   curses_print_window (pv->flag_window);
644 
645   // help message
646   mvprintw (Y_loop,    41, "< > by cur, [ { expand } ]");
647   mvprintw (Y_pitch,   41, "UP   / DOWN");
648   mvprintw (Y_rate,    41, "LEFT / RIGHT");
649   mvprintw (Y_hop_syn, 41, "H / h");
650   mvprintw (Y_status,  41, "SPACE");
651   mvprintw (Y_lock,    41, "L");
652   mvprintw (Y_window,  41, "W");
653 
654   mvprintw (Y_comment-1, 0, "----------------------------------------");
655 }
656 
657 /* change rate and pitch (note that hop_syn is fixed)
658  * INPUT
659  *  pv : struct pv_complex
660  *  rate  : rate of speed (1 == same speed, negative == backward)
661  *  pitch : pitch-shift (0 == no-shift, +1(-1) = half-note up(down))
662  * OUTPUT
663  *  pv->hop_res :
664  *  pv->hop_ana :
665  */
666 void
pv_complex_change_rate_pitch_(struct pv_complex * pv,int sr_in,int sr_out,double rate,double pitch)667 pv_complex_change_rate_pitch_ (struct pv_complex *pv,
668 			       int sr_in, int sr_out,
669 			       double rate,
670 			       double pitch)
671 {
672   double rate0 = (double)sr_out / (double)sr_in;
673   pv->hop_res = (long)(rate0 * (double)pv->hop_syn * pow (2.0, - pitch / 12.0));
674   pv->hop_ana = (long)((double)pv->hop_res * rate);
675 }
676 
677 /* phase vocoder by complex arithmetics with fixed hops.
678  */
pv_complex_curses_jack(const char * file,long len,long hop_syn)679 void pv_complex_curses_jack (const char *file,
680 			     long len, long hop_syn)
681 {
682   // ncurses initializing
683   initscr();             /* Start curses mode */
684   raw();                 /* Line buffering disabled */
685   keypad(stdscr, TRUE);  /* We get F1, F2 etc.. */
686   noecho();              /* Don't echo() while we do getch */
687   nodelay(stdscr, TRUE); /* Don't wait the key press */
688 
689 
690   int flag_window = 3;
691   struct pv_complex *pv
692     = pv_complex_init (len, hop_syn, flag_window);
693   CHECK_MALLOC (pv, "pv_complex_curses");
694 
695   // open input file
696   SNDFILE *sf = NULL;
697   SF_INFO sfinfo;
698   memset (&sfinfo, 0, sizeof (sfinfo));
699   sf = sf_open (file, SFM_READ, &sfinfo);
700   if (sf == NULL)
701     {
702       fprintf (stderr, "fail to open %s\n", file);
703       exit (1);
704     }
705   //sndfile_print_info (&sfinfo);
706 
707   pv_complex_set_input (pv, sf, &sfinfo);
708 
709   /*
710   ao_device *ao = NULL;
711   ao = ao_init_16_stereo (sfinfo.samplerate, 0);
712   pv_complex_set_output_ao (pv, ao);
713   */
714 
715   // jack initialization
716   struct pv_jack *pv_jack = pv_jack_init (pv);
717   int jack_sr = (int)jack_get_sample_rate (pv_jack->client);
718   extern FILE *err_log;
719   err_log = fopen ("jack-pv.log", "w");
720 
721 
722   // initial values
723   double pv_rate  = 1.0;
724   double pv_pitch = 0.0;
725   pv_complex_change_rate_pitch_ (pv, sfinfo.samplerate, jack_sr,
726 				 pv_rate, pv_pitch);
727   fprintf (stderr, "# samplerates: %d %d\n", sfinfo.samplerate, jack_sr);
728 
729   long frame0 = 0;
730   long frame1 = (long)pv->sfinfo->frames - 1;
731   pv->flag_lock = 0; // no phase-lock
732   int flag_play = 1;
733   long play_cur = 0;
734 
735   long len_1sec  = (long)(pv->sfinfo->samplerate /* Hz */);
736   long len_10sec = (long)(10 * pv->sfinfo->samplerate /* Hz */);
737 
738   mvprintw (Y_comment, 1, "Welcome WaoN-pv in curses mode.");
739   curses_print_pv (file, pv, flag_play, frame0, frame1,
740 		   pv_pitch, pv_rate);
741 
742   // main loop
743   //long status = 1; // TRUE
744   do
745     {
746       // scan keyboard
747       int ch = getch();
748       switch (ch)
749 	{
750 	case ERR: // no key event
751 	  break;
752 
753 	case ' ': // SPACE
754 	  flag_play++;
755 	  flag_play = flag_play % 2;
756 	  if (flag_play == 0) mvprintw(Y_status, 1, "status     : stop");
757 	  else                mvprintw(Y_status, 1, "status     : play");
758 	  break;
759 
760 	case '>':
761 	case '.':
762 	  frame1 = play_cur;
763 	  mvprintw (Y_loop,   1, "loop       : %010ld - %010ld",
764 		    frame0, frame1);
765 	  break;
766 
767 	case '<':
768 	case ',':
769 	  frame0 = play_cur;
770 	  mvprintw (Y_loop,   1, "loop       : %010ld - %010ld",
771 		    frame0, frame1);
772 	  break;
773 
774 	case ']':
775 	  frame1 += len_10sec;
776 	  if (frame1 >= pv->sfinfo->frames - 1) frame1 = pv->sfinfo->frames - 1;
777 	  mvprintw (Y_loop,   1, "loop       : %010ld - %010ld",
778 		    frame0, frame1);
779 	  break;
780 
781 	case '}':
782 	  frame1 += len_1sec;
783 	  if (frame1 >= pv->sfinfo->frames - 1) frame1 = pv->sfinfo->frames - 1;
784 	  mvprintw (Y_loop,   1, "loop       : %010ld - %010ld",
785 		    frame0, frame1);
786 	  break;
787 
788 	case '[':
789 	  frame0 -= len_10sec;
790 	  if (frame0 < 0) frame0 = 0;
791 	  mvprintw (Y_loop,   1, "loop       : %010ld - %010ld",
792 		    frame0, frame1);
793 	  break;
794 
795 	case '{':
796 	  frame0 -= len_1sec;
797 	  if (frame0 < 0) frame0 = 0;
798 	  mvprintw (Y_loop,   1, "loop       : %010ld - %010ld",
799 		    frame0, frame1);
800 	  break;
801 
802 	case 'L':
803 	case 'l':
804 	  pv->flag_lock++;
805 	  pv->flag_lock = pv->flag_lock % 2;
806 
807 	  if (pv->flag_lock == 0) mvprintw(Y_lock, 1, "phase-lock : off");
808 	  else                    mvprintw(Y_lock, 1, "phase-lock : on ");
809 	  break;
810 
811 	case 'W':
812 	case 'w':
813 	  pv->flag_window++;
814 	  pv->flag_window = pv->flag_window % 7; // 0 to 6
815 
816 	  // reset scale factor
817 	  pv->window_scale
818 	    = get_scale_factor_for_window (pv->len, pv->hop_syn,
819 					   pv->flag_window);
820 	  curses_print_window (pv->flag_window);
821 	  break;
822 
823 	case 'H':
824 	  pv->hop_syn *= 2;
825 	  if (pv->hop_syn > len) pv->hop_syn = len;
826 	  // hop_res, hop_ana depend on hop_syn
827 	  pv_complex_change_rate_pitch_ (pv, sfinfo.samplerate, jack_sr,
828 					 pv_rate, pv_pitch);
829 	  mvprintw (Y_hop_syn,1, "hop(syn)   : %06ld", pv->hop_syn);
830 	  mvprintw (Y_hop_ana,1, "hop(ana)   : %06ld", pv->hop_ana);
831 	  mvprintw (Y_hop_res,1, "hop(res)   : %06ld", pv->hop_res);
832 	  break;
833 
834 	case 'h':
835 	  pv->hop_syn /= 2;
836 	  if (pv->hop_syn < 1) pv->hop_syn = 1;
837 	  // hop_res, hop_ana depend on hop_syn
838 	  pv_complex_change_rate_pitch_ (pv, sfinfo.samplerate, jack_sr,
839 					 pv_rate, pv_pitch);
840 	  mvprintw (Y_hop_syn,1, "hop(syn)   : %06ld", pv->hop_syn);
841 	  mvprintw (Y_hop_ana,1, "hop(ana)   : %06ld", pv->hop_ana);
842 	  mvprintw (Y_hop_res,1, "hop(res)   : %06ld", pv->hop_res);
843 	  break;
844 
845 	case KEY_UP:
846 	  pv_pitch += 1.0;
847 	  pv_complex_change_rate_pitch_ (pv, sfinfo.samplerate, jack_sr,
848 					 pv_rate, pv_pitch);
849 	  curses_print_pitch (pv_pitch);
850 	  mvprintw (Y_hop_syn,1, "hop(syn)   : %06ld", pv->hop_syn);
851 	  mvprintw (Y_hop_ana,1, "hop(ana)   : %06ld", pv->hop_ana);
852 	  mvprintw (Y_hop_res,1, "hop(res)   : %06ld", pv->hop_res);
853 	  break;
854 
855 	case KEY_DOWN:
856 	  pv_pitch -= 1.0;
857 	  pv_complex_change_rate_pitch_ (pv, sfinfo.samplerate, jack_sr,
858 					 pv_rate, pv_pitch);
859 	  curses_print_pitch (pv_pitch);
860 	  mvprintw (Y_hop_syn,1, "hop(syn)   : %06ld", pv->hop_syn);
861 	  mvprintw (Y_hop_ana,1, "hop(ana)   : %06ld", pv->hop_ana);
862 	  mvprintw (Y_hop_res,1, "hop(res)   : %06ld", pv->hop_res);
863 	  break;
864 
865 	case KEY_LEFT:
866 	  pv_rate -= 0.1;
867 	  pv_complex_change_rate_pitch_ (pv, sfinfo.samplerate, jack_sr,
868 					 pv_rate, pv_pitch);
869 	  mvprintw (Y_rate,   1, "rate       : %-5.1f", pv_rate);
870 	  mvprintw (Y_hop_syn,1, "hop(syn)   : %06ld", pv->hop_syn);
871 	  mvprintw (Y_hop_ana,1, "hop(ana)   : %06ld", pv->hop_ana);
872 	  mvprintw (Y_hop_res,1, "hop(res)   : %06ld", pv->hop_res);
873 	  break;
874 
875 	case KEY_RIGHT:
876 	  pv_rate += 0.1;
877 	  pv_complex_change_rate_pitch_ (pv, sfinfo.samplerate, jack_sr,
878 					 pv_rate, pv_pitch);
879 	  mvprintw (Y_rate,   1, "rate       : %-5.1f", pv_rate);
880 	  mvprintw (Y_hop_syn,1, "hop(syn)   : %06ld", pv->hop_syn);
881 	  mvprintw (Y_hop_ana,1, "hop(ana)   : %06ld", pv->hop_ana);
882 	  mvprintw (Y_hop_res,1, "hop(res)   : %06ld", pv->hop_res);
883 	  break;
884 
885 	case KEY_HOME:
886 	case 'R':
887 	case 'r':
888 	  frame0 = 0;
889 	  frame1 = (long)pv->sfinfo->frames - 1;
890 	  pv_rate = 1.0;
891 	  pv_pitch = 0.0;
892 	  pv->hop_syn = hop_syn; // value in the argument
893 	  pv_complex_change_rate_pitch_ (pv, sfinfo.samplerate, jack_sr,
894 					 pv_rate, pv_pitch);
895 	  curses_print_pv (file, pv, flag_play, frame0, frame1,
896 			   pv_pitch, pv_rate);
897 	  mvprintw(Y_comment, 1, "reset everything");
898 	  break;
899 
900 	case 'Q':
901 	case 'q':
902 	  //status = 0;
903 	  pv_jack->state = Exit;
904 	  mvprintw(Y_comment, 1, "good-bye!");
905 	  break;
906 
907 	  /*
908 	defaut :
909 	  break;
910 	  */
911 	}
912       mvprintw (Y_frames, 1, "current    : %010ld", play_cur);
913       refresh();
914     }
915   //while (status == 1);
916   while (pv_jack->state != Exit);
917 
918   jack_client_close (pv_jack->client);
919   pv_jack_free (pv_jack);
920 
921   pv_complex_free (pv);
922   sf_close (sf) ;
923 
924 
925   /* End ncurses mode */
926   endwin();
927 }
928