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