1 #ifdef _WITH_AUBIO_3_
2 
3 //      sourceaudio.c
4 //
5 //      Copyright 2012 Richard Shann <rshann@debian2>
6 //
7 //      This program is free software; you can redistribute it and/or modify
8 //      it under the terms of the GNU General Public License as published by
9 //      the Free Software Foundation; either version 2 of the License, or
10 //      (at your option) any later version.
11 //
12 //      This program is distributed in the hope that it will be useful,
13 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //      GNU General Public License for more details.
16 //
17 //      You should have received a copy of the GNU General Public License
18 //      along with this program; if not, write to the Free Software
19 //      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 //      MA 02110-1301, USA.
21 
22 
23 #include <stdio.h>
24 #include <sndfile.h>
25 #include <fcntl.h>
26 #include <aubio/aubio.h>
27 #include "core/utils.h"
28 #include "audio/midi.h"
29 #include "export/exportmidi.h"
30 #include "source/sourceaudio.h"
31 #include "command/keyresponses.h"
32 #include "audio/audiointerface.h"
33 #if GTK_MAJOR_VERSION==3
34 #include <gdk/gdkkeysyms-compat.h>      //FIXME Look for something more gtk3 like
35 #endif
36 
37 static gint leadin = 0;         //number of frames of silence before playing audio
38 static gboolean playing = FALSE;
39 
40 
41 
42 
43 //Creates a list of times which the aubio onset detector thinks are note onset times for the audio Denemo->si->recording
44 //Result is placed in Denemo->si->note_onsets
45 void
generate_note_onsets(void)46 generate_note_onsets (void)
47 {
48   DenemoRecording *audio = Denemo.project->movement->recording;
49   gint channels = audio->channels;
50 
51   aubio_onsetdetection_type type_onset = aubio_onset_kl;
52   aubio_onsetdetection_type type_onset2 = aubio_onset_complex;
53   smpl_t threshold = 0.3;
54   smpl_t silence = -90.;
55   uint_t buffer_size = 1024;
56   uint_t overlap_size = 512;
57 
58   uint_t samplerate = 44100;
59 
60   aubio_pvoc_t *pv;
61   fvec_t *ibuf;
62   fvec_t *obuf;
63   cvec_t *fftgrain;
64 
65   aubio_onsetdetection_t *o;
66   aubio_onsetdetection_t *o2;
67   fvec_t *onset;
68   fvec_t *onset2;
69   int isonset = 0;
70   aubio_pickpeak_t *parms;
71 
72 
73 
74   unsigned int pos = 0;         /*frames%dspblocksize */
75   unsigned int i;               /*channels */
76   unsigned int j;               /*frames */
77 
78   busy_cursor (Denemo.notebook);
79   gtk_window_set_modal (progressbar (_("Analysing Audio"), NULL), TRUE);
80 
81   ibuf = new_fvec (overlap_size, channels);
82   obuf = new_fvec (overlap_size, channels);
83   fftgrain = new_cvec (buffer_size, channels);
84 
85   /* phase vocoder */
86   pv = new_aubio_pvoc (buffer_size, overlap_size, channels);
87   /* onsets */
88   parms = new_aubio_peakpicker (threshold);
89   o = new_aubio_onsetdetection (type_onset, buffer_size, channels);
90 
91   // if (usedoubled)
92   // {
93   o2 = new_aubio_onsetdetection (type_onset2, buffer_size, channels);
94   onset2 = new_fvec (1, channels);
95   // }
96 
97   onset = new_fvec (1, channels);
98   rewind_audio ();
99   if (audio->notes)
100     {
101       g_list_free_full (audio->notes, g_free);
102       audio->notes = NULL;
103     }
104   for (j = 0; j < (unsigned) audio->nframes; j++)
105     {
106       sf_read_float (audio->sndfile, ibuf->data[0] + pos, 2);   //g_debug("\t%f", ibuf->data[0][pos]);
107       if (pos == overlap_size - 1)
108         {
109           /* block loop */
110           gtk_main_iteration_do (FALSE);
111           aubio_pvoc_do (pv, ibuf, fftgrain);
112           while (gtk_events_pending ())
113             gtk_main_iteration ();
114 
115           aubio_onsetdetection (o, fftgrain, onset);
116           while (gtk_events_pending ())
117             gtk_main_iteration ();
118 
119           // if (usedoubled) {
120           aubio_onsetdetection (o2, fftgrain, onset2);
121           while (gtk_events_pending ())
122             gtk_main_iteration ();
123 
124           onset->data[0][0] *= onset2->data[0][0];
125           // }
126           isonset = aubio_peakpick_pimrt (onset, parms);
127           if (isonset) {
128               DenemoRecordedNote *note = g_malloc0(sizeof(DenemoRecordedNote));
129               note->timing = j;/* /audio->samplerate for seconds */
130             audio->notes = g_list_append (audio->notes, note);
131         }
132           pos = -1;             /* so it will be zero next j loop */
133         }                       /* end of if pos==overlap_size-1 */
134       pos++;
135     }
136 
137 #ifndef G_OS_WIN32
138   del_aubio_onsetdetection (o2);
139   del_fvec (onset2);
140 
141   del_aubio_onsetdetection (o);
142   del_aubio_peakpicker (parms);
143   del_aubio_pvoc (pv);
144   del_fvec (obuf);
145   del_fvec (ibuf);
146   del_cvec (fftgrain);
147   del_fvec (onset);
148 #else
149   g_debug ("\n\n\n!!!!!!!!!skipping memory free for windows to avoid crash\n\n\n");
150 #endif
151   aubio_cleanup ();
152 
153 
154 
155 
156 
157 
158 
159 
160 
161 
162 
163   progressbar_stop ();
164   normal_cursor (Denemo.notebook);
165 /*
166 #ifdef DEBUG
167   GList *g;
168   for (g = audio->onsets; g; g = g->next)
169     {
170       g_debug ("Note at %f seconds\n", ((gint) g->data) / (double) audio->samplerate);
171     }
172 #endif
173 */
174 }
175 
176 gboolean
get_audio_sample(float * sample)177 get_audio_sample (float *sample)
178 {
179   if (!playing)
180     return FALSE;
181   gboolean ret = FALSE;
182   if (leadin)
183     {
184       *sample = *(sample + 1) = 0.0;
185       leadin--;
186       ret = TRUE;
187     }
188   else
189     {
190       if (Denemo.project->movement && Denemo.project->movement->recording && Denemo.project->movement->recording->sndfile)
191         {
192           ret = (2 == sf_read_float (Denemo.project->movement->recording->sndfile, sample, 2));
193           if (ret)
194             *sample *= Denemo.project->movement->recording->volume;
195           *(sample + 1) *= Denemo.project->movement->recording->volume;
196         }
197     }
198   return ret;
199 }
200 
201 gboolean
open_source_audio(gchar * filename)202 open_source_audio (gchar * filename)
203 {
204   SF_INFO sfinfo;
205   DenemoRecording *temp;
206   sfinfo.format = 0;
207 
208   delete_recording();
209 
210   if (filename)
211     {
212       gpointer sndfile = sf_open (filename, SFM_READ, &sfinfo);
213       if (sndfile)
214         {
215           temp = (DenemoRecording *) g_malloc (sizeof (DenemoRecording));
216           temp->type = DENEMO_RECORDING_AUDIO;
217           temp->sndfile = sndfile;
218           temp->filename = g_strdup (filename);
219           temp->samplerate = sfinfo.samplerate;
220           temp->channels = sfinfo.channels;
221           temp->nframes = (int) sf_seek (temp->sndfile, -1, SEEK_END);
222           g_info ("sndfile: %s sample rate is %d channels %d containing %d \n", sf_strerror (temp->sndfile), sfinfo.samplerate, sfinfo.channels, temp->nframes);
223 
224 
225           temp->volume = 1.0;
226           g_static_mutex_lock (&smfmutex);
227           Denemo.project->movement->recording = temp;
228           g_static_mutex_unlock (&smfmutex);
229           update_leadin_widget (-1.0);
230           if (sfinfo.channels != 2)
231             warningdialog (_("Audio is not stereo - expect bad things!"));
232           if (sfinfo.samplerate != 44100)
233             warningdialog (_("Audio does not have 44100 sample rate: this could be bad"));
234           //FIXME here generate a click track if the score is empty
235           if (Denemo.project->movement->smfsync != Denemo.project->movement->changecount)
236             {
237               exportmidi (NULL, Denemo.project->movement);  //generate a timebase
238             }
239           generate_note_onsets ();
240           draw_score_area();
241         }
242     }
243   Denemo.project->movement->recording ? gtk_widget_show (Denemo.audio_vol_control) : gtk_widget_hide (Denemo.audio_vol_control);
244   return (Denemo.project->movement->recording != NULL);
245 }
246 
247 gboolean
close_source_audio(void)248 close_source_audio (void)
249 {
250   gboolean ret = (Denemo.project->movement->recording != NULL);
251   (void) open_source_audio (NULL);
252   return ret;
253 }
254 
255 void
rewind_audio(void)256 rewind_audio (void)
257 {
258   if (Denemo.project->movement->recording && (Denemo.project->movement->recording->type==DENEMO_RECORDING_AUDIO))
259     {
260       if (Denemo.project->movement->recording->sndfile == NULL)
261         {
262           gint leadin = Denemo.project->movement->recording->leadin;  /* not part of the audio file itself */
263           open_source_audio (Denemo.project->movement->recording->filename);
264           if (Denemo.project->movement->recording==NULL)
265           {
266             g_warning("Unable to open audio file");
267             return;
268           }
269           if (Denemo.project->movement->recording->samplerate)
270             {
271               Denemo.project->movement->recording->leadin = leadin;
272               update_leadin_widget (((double) leadin) / Denemo.project->movement->recording->samplerate);
273             }
274         }
275       gdouble start = get_start_time ();
276       if (start < 0.0)
277         start = 0.0;
278       gint startframe = start * Denemo.project->movement->recording->samplerate;
279       startframe += Denemo.project->movement->recording->leadin;
280       if (startframe < 0)
281         {
282           leadin = -startframe;
283           startframe = 0;
284         }
285       else
286         leadin = 0;
287       sf_seek (Denemo.project->movement->recording->sndfile, startframe, SEEK_SET);
288     }
289   else
290     gtk_widget_hide (Denemo.audio_vol_control);
291 }
292 
293 gboolean
set_lead_in(gdouble secs)294 set_lead_in (gdouble secs)
295 {
296   if (Denemo.project->movement->recording)
297     {
298       if ((Denemo.project->movement->recording->type==DENEMO_RECORDING_AUDIO) && Denemo.project->movement->recording->sndfile == NULL)
299         {
300             open_source_audio (Denemo.project->movement->recording->filename);
301             if (Denemo.project->movement->recording==NULL) {
302                 g_warning("Unable to open source audio");
303                 return FALSE;
304             }
305         }
306       Denemo.project->movement->recording->leadin = secs * Denemo.project->movement->recording->samplerate;
307       return TRUE;
308     }
309   return FALSE;
310 }
311 
312 
313 
314 
315 gboolean
audio_is_playing(void)316 audio_is_playing (void)
317 {
318   return playing;
319 }
320 
321 
322 
323 static gboolean annotating = FALSE;
324 static GQueue *timings = NULL;  //list of measure start times in microseconds from start, as indicated by the user.
325 static gint
record_timing(GtkWidget * widget,GdkEventKey * event)326 record_timing (GtkWidget * widget, GdkEventKey * event)
327 {
328   if (event->keyval == GDK_Escape)
329     {
330       call_out_to_guile ("(if (defined? 'DenemoAudioAnnotateFinished) (DenemoAudioAnnotateFinished))");
331       stop_audio_playing ();
332     }
333   else
334     {
335       g_queue_push_tail (timings, GINT_TO_POINTER ((gint) (1000000 * get_playback_time ())));
336       call_out_to_guile ("(DenemoAudioAnnotate)");
337     }
338   return TRUE;
339 }
340 
341 gdouble
get_audio_timing(void)342 get_audio_timing (void)
343 {
344   gdouble ret = -1.0;
345   if (!g_queue_is_empty (timings))
346     {
347       ret = (GPOINTER_TO_INT (g_queue_pop_head (timings))) / 1000000.0;
348     }
349   return ret;
350 }
351 
352 void
start_audio_playing(gboolean annotate)353 start_audio_playing (gboolean annotate)
354 {
355   if (annotate)
356     {
357       annotating = TRUE;
358       if (timings)
359         g_queue_clear (timings);
360       else
361         timings = g_queue_new ();
362       g_signal_connect (G_OBJECT (Denemo.scorearea), "key_press_event", G_CALLBACK (record_timing), NULL);
363       g_signal_handlers_block_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_keypress_event), NULL);
364       g_signal_handlers_block_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_button_press), NULL);
365       g_signal_handlers_block_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_button_release), NULL);
366 
367 
368     }
369   rewind_audio ();
370 
371   initialize_until_time ();
372   audio_play ();
373   playing = TRUE;
374 }
375 
376 void
stop_audio_playing(void)377 stop_audio_playing (void)
378 {
379   playing = FALSE;
380   if (annotating)
381     {
382       annotating = FALSE;
383       g_signal_handlers_disconnect_by_func (G_OBJECT (Denemo.scorearea), record_timing, NULL);
384       g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_keypress_event), NULL);
385       g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_button_press), NULL);
386       g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_button_release), NULL);
387     }
388 }
389 
390 gboolean
open_source_audio_file(void)391 open_source_audio_file (void)
392 {
393   gboolean ret = FALSE;
394   GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Open Audio Source File"),
395                                                    NULL,
396                                                    GTK_FILE_CHOOSER_ACTION_OPEN,
397                                                    _("_Cancel"), GTK_RESPONSE_CANCEL,
398                                                    _("_Open"), GTK_RESPONSE_ACCEPT,
399                                                    NULL);
400   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
401     {
402       char *filename;
403       filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
404       gtk_widget_destroy (dialog);
405 
406 
407 
408       ret = open_source_audio (filename);
409       g_free (filename);
410 
411       if (!ret)
412         warningdialog (_("Could not load the audio file. Note only stereo with sample rate 44100 are supported at present. Use Audacity or similar to convert."));
413     }
414   else
415     gtk_widget_destroy (dialog);
416 
417   return ret;
418 }
419 //END OF AUBIO 3
420 #else
421 //START AUBIO 4
422 
423 // Upgraded to AUBIO 4 Paul Brossier 2014
424 //      sourceaudio.c
425 //
426 //      Copyright 2012 Richard Shann <rshann@debian2>
427 //
428 //      This program is free software; you can redistribute it and/or modify
429 //      it under the terms of the GNU General Public License as published by
430 //      the Free Software Foundation; either version 2 of the License, or
431 //      (at your option) any later version.
432 //
433 //      This program is distributed in the hope that it will be useful,
434 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
435 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
436 //      GNU General Public License for more details.
437 //
438 //      You should have received a copy of the GNU General Public License
439 //      along with this program; if not, write to the Free Software
440 //      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
441 //      MA 02110-1301, USA.
442 
443 
444 #include <stdio.h>
445 #include <sndfile.h>
446 #include <fcntl.h>
447 #include <aubio/aubio.h>
448 #include "core/utils.h"
449 #include "core/view.h"
450 #include "audio/midi.h"
451 #include "export/exportmidi.h"
452 #include "source/sourceaudio.h"
453 #include "command/keyresponses.h"
454 #include "audio/audiointerface.h"
455 #if GTK_MAJOR_VERSION==3
456 #include <gdk/gdkkeysyms-compat.h>      //FIXME Look for something more gtk3 like
457 #endif
458 
459 static gint leadin = 0;         //number of frames of silence before playing audio
460 static gboolean playing = FALSE;
461 
462 
463 
464 
465 //Creates a list of times which the aubio onset detector thinks are note onset times for the audio Denemo->si->recording
466 //Result is placed in Denemo->si->note_onsets
467 void
generate_note_onsets(void)468 generate_note_onsets (void)
469 {
470   DenemoRecording *audio = Denemo.project->movement->recording;
471   gint channels = audio->channels;
472 
473  smpl_t threshold = 0.3;
474  smpl_t silence = -90.;
475  uint_t buffer_size = 1024;
476  uint_t overlap_size = 512;
477 
478  uint_t samplerate = 44100;
479 
480  aubio_onset_t *o = new_aubio_onset("default",
481      buffer_size, overlap_size, samplerate);
482  fvec_t *ibuf = new_fvec (overlap_size);
483  fvec_t *onset = new_fvec (2);
484 
485   unsigned int pos = 0;         /*frames%dspblocksize */
486   unsigned int i;               /*channels */
487   unsigned int j;               /*frames */
488 
489   busy_cursor (Denemo.notebook);
490   gtk_window_set_modal (progressbar (_("Analysing Audio"), NULL), TRUE);
491 
492   rewind_audio ();
493   if (audio->notes)
494     {
495       g_list_free_full (audio->notes, g_free);
496       audio->notes = NULL;
497     }
498   for (j = 0; j < (unsigned) audio->nframes; j++)
499     {
500       sf_read_float (audio->sndfile, ibuf->data + pos, 2);   //g_debug("\t%f", ibuf->data[0][pos]);
501       if (pos == overlap_size - 1)
502         {
503           /* block loop */
504           gtk_main_iteration_do (FALSE);
505           aubio_onset_do (o, ibuf, onset);
506           while (gtk_events_pending ())
507             gtk_main_iteration ();
508           if(onset->data[0] != 0) {
509               DenemoRecordedNote *note = g_malloc0(sizeof(DenemoRecordedNote));
510               note->timing = aubio_onset_get_last(o);/* aubio_onset_get_delay_s(o) for seconds */
511             audio->notes = g_list_append (audio->notes, note);
512           }
513           pos = -1;             /* so it will be zero next j loop */
514         }                       /* end of if pos==overlap_size-1 */
515       pos++;
516     }
517 
518   del_aubio_onset (o);
519   del_fvec (ibuf);
520   del_fvec (onset);
521   aubio_cleanup ();
522 
523 
524 
525 
526 
527 
528 
529 
530 
531 
532 
533   progressbar_stop ();
534   normal_cursor (Denemo.notebook);
535 }
536 
537 gboolean
get_audio_sample(float * sample)538 get_audio_sample (float *sample)
539 {
540   if (!playing)
541     return FALSE;
542   gboolean ret = FALSE;
543   if (leadin)
544     {
545       *sample = *(sample + 1) = 0.0;
546       leadin--;
547       ret = TRUE;
548     }
549   else
550     {
551       if (Denemo.project->movement && Denemo.project->movement->recording && Denemo.project->movement->recording->sndfile)
552         {
553           ret = (2 == sf_read_float (Denemo.project->movement->recording->sndfile, sample, 2));
554           if (ret)
555             *sample *= Denemo.project->movement->recording->volume;
556           *(sample + 1) *= Denemo.project->movement->recording->volume;
557         }
558     }
559   return ret;
560 }
561 
562 gboolean
open_source_audio(gchar * filename)563 open_source_audio (gchar * filename)
564 {
565   SF_INFO sfinfo;
566   DenemoRecording *temp;
567   sfinfo.format = 0;
568 
569   delete_recording();
570 
571   if (filename)
572     {
573       gpointer sndfile = sf_open (filename, SFM_READ, &sfinfo);
574       if (sndfile)
575         {
576           temp = (DenemoRecording *) g_malloc (sizeof (DenemoRecording));
577           temp->type = DENEMO_RECORDING_AUDIO;
578           temp->sndfile = sndfile;
579           temp->filename = g_strdup (filename);
580           temp->samplerate = sfinfo.samplerate;
581           temp->channels = sfinfo.channels;
582           temp->nframes = (int) sf_seek (temp->sndfile, -1, SEEK_END);
583           g_info ("sndfile: %s sample rate is %d channels %d containing %d \n", sf_strerror (temp->sndfile), sfinfo.samplerate, sfinfo.channels, temp->nframes);
584 
585 
586           temp->volume = 1.0;
587           g_static_mutex_lock (&smfmutex);
588           Denemo.project->movement->recording = temp;
589           g_static_mutex_unlock (&smfmutex);
590           update_leadin_widget (-1.0);
591           if (sfinfo.channels != 2)
592             warningdialog (_("Audio is not stereo - expect bad things!"));
593           if (sfinfo.samplerate != 44100)
594             warningdialog (_("Audio does not have 44100 sample rate: this could be bad"));
595           //FIXME here generate a click track if the score is empty
596           if (Denemo.project->movement->smfsync != Denemo.project->movement->changecount)
597             {
598               exportmidi (NULL, Denemo.project->movement);  //generate a timebase
599             }
600           generate_note_onsets ();
601           draw_score_area();
602         }
603     }
604   Denemo.project->movement->recording ? gtk_widget_show (Denemo.audio_vol_control) : gtk_widget_hide (Denemo.audio_vol_control);
605   return (Denemo.project->movement->recording != NULL);
606 }
607 
608 gboolean
close_source_audio(void)609 close_source_audio (void)
610 {
611   gboolean ret = (Denemo.project->movement->recording != NULL);
612   (void) open_source_audio (NULL);
613   return ret;
614 }
615 
616 void
rewind_audio(void)617 rewind_audio (void)
618 {
619   if (Denemo.project->movement->recording && (Denemo.project->movement->recording->type==DENEMO_RECORDING_AUDIO))
620     {
621       if (Denemo.project->movement->recording->sndfile == NULL)
622         {
623           gint leadin = Denemo.project->movement->recording->leadin;  /* not part of the audio file itself */
624           open_source_audio (Denemo.project->movement->recording->filename);
625           if (Denemo.project->movement->recording==NULL)
626           {
627             g_warning("Unable to open audio file");
628             return;
629           }
630           if (Denemo.project->movement->recording->samplerate)
631             {
632               Denemo.project->movement->recording->leadin = leadin;
633               update_leadin_widget (((double) leadin) / Denemo.project->movement->recording->samplerate);
634             }
635         }
636       gdouble start = get_start_time ();
637       if (start < 0.0)
638         start = 0.0;
639       gint startframe = start * Denemo.project->movement->recording->samplerate;
640       startframe += Denemo.project->movement->recording->leadin;
641       if (startframe < 0)
642         {
643           leadin = -startframe;
644           startframe = 0;
645         }
646       else
647         leadin = 0;
648       sf_seek (Denemo.project->movement->recording->sndfile, startframe, SEEK_SET);
649     }
650   else
651     gtk_widget_hide (Denemo.audio_vol_control);
652 }
653 
654 gboolean
set_lead_in(gdouble secs)655 set_lead_in (gdouble secs)
656 {
657   if (Denemo.project->movement->recording)
658     {
659       if ((Denemo.project->movement->recording->type==DENEMO_RECORDING_AUDIO) && Denemo.project->movement->recording->sndfile == NULL)
660         {
661             open_source_audio (Denemo.project->movement->recording->filename);
662             if (Denemo.project->movement->recording==NULL) {
663                 g_warning("Unable to open source audio");
664                 return FALSE;
665             }
666         }
667       Denemo.project->movement->recording->leadin = secs * Denemo.project->movement->recording->samplerate;
668       return TRUE;
669     }
670   return FALSE;
671 }
672 
673 
674 
675 
676 gboolean
audio_is_playing(void)677 audio_is_playing (void)
678 {
679   return playing;
680 }
681 
682 
683 
684 static gboolean annotating = FALSE;
685 static GQueue *timings = NULL;  //list of measure start times in microseconds from start, as indicated by the user.
686 static gint
record_timing(GtkWidget * widget,GdkEventKey * event)687 record_timing (GtkWidget * widget, GdkEventKey * event)
688 {
689   if (event->keyval == GDK_Escape)
690     {
691       call_out_to_guile ("(if (defined? 'DenemoAudioAnnotateFinished) (DenemoAudioAnnotateFinished))");
692       stop_audio_playing ();
693     }
694   else
695     {
696       g_queue_push_tail (timings, GINT_TO_POINTER ((gint) (1000000 * get_playback_time ())));
697       call_out_to_guile ("(DenemoAudioAnnotate)");
698     }
699   return TRUE;
700 }
701 
702 gdouble
get_audio_timing(void)703 get_audio_timing (void)
704 {
705   gdouble ret = -1.0;
706   if (!g_queue_is_empty (timings))
707     {
708       ret = (GPOINTER_TO_INT (g_queue_pop_head (timings))) / 1000000.0;
709     }
710   return ret;
711 }
712 
713 void
start_audio_playing(gboolean annotate)714 start_audio_playing (gboolean annotate)
715 {
716   if (annotate)
717     {
718       annotating = TRUE;
719       if (timings)
720         g_queue_clear (timings);
721       else
722         timings = g_queue_new ();
723       g_signal_connect (G_OBJECT (Denemo.scorearea), "key_press_event", G_CALLBACK (record_timing), NULL);
724       g_signal_handlers_block_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_keypress_event), NULL);
725       g_signal_handlers_block_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_button_press), NULL);
726       g_signal_handlers_block_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_button_release), NULL);
727 
728 
729     }
730   rewind_audio ();
731 
732   initialize_until_time ();
733   audio_play ();
734   playing = TRUE;
735 }
736 
737 void
stop_audio_playing(void)738 stop_audio_playing (void)
739 {
740   playing = FALSE;
741   if (annotating)
742     {
743       annotating = FALSE;
744       g_signal_handlers_disconnect_by_func (G_OBJECT (Denemo.scorearea), record_timing, NULL);
745       g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_keypress_event), NULL);
746       g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_button_press), NULL);
747       g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_button_release), NULL);
748     }
749 }
750 
751 gboolean
open_source_audio_file(void)752 open_source_audio_file (void)
753 {
754   gboolean ret = FALSE;
755   GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Open Audio Source File"),
756                                                    NULL,
757                                                    GTK_FILE_CHOOSER_ACTION_OPEN,
758                                                    _("_Cancel"), GTK_RESPONSE_CANCEL,
759                                                    _("_Open"), GTK_RESPONSE_ACCEPT,
760                                                    NULL);
761   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
762     {
763       char *filename;
764       filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
765       gtk_widget_destroy (dialog);
766 
767 
768 
769       ret = open_source_audio (filename);
770       g_free (filename);
771 
772       if (!ret)
773         warningdialog (_("Could not load the audio file. Note only stereo with sample rate 44100 are supported at present. Use Audacity or similar to convert."));
774     }
775   else
776     gtk_widget_destroy (dialog);
777 
778   return ret;
779 }
780 
781 #endif
782