root/sweep/trunk/src/samplerate.c

Revision 691, 17.5 kB (checked in by erikd, 2 years ago)

Remove needless #defines of buffer lengths.

Code had many instances of:

#undef BUF_LEN
#define BUF_LEN 64
char buf[BUF_LEN];
snprintf (buf, BUF_LEN, ....);

which can be replaced with:

char buf[64];
snprintf (buf, sizeof (buf), ....);

which is far cleaner and more difficult to get wrong.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Sweep, a sound wave editor.
3  *
4  * Copyright (C) 2000 Conrad Parker
5  * Copyright (C) 2002 CSIRO Australia
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include <config.h>
24 #endif
25
26 #ifdef HAVE_LIBSAMPLERATE
27
28 #include <math.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #include <samplerate.h>
33
34 #include <sweep/sweep_i18n.h>
35 #include <sweep/sweep_types.h>
36 #include <sweep/sweep_typeconvert.h>
37 #include <sweep/sweep_undo.h>
38 #include <sweep/sweep_filter.h>
39 #include <sweep/sweep_sounddata.h>
40 #include <sweep/sweep_sample.h>
41
42 #include "sweep_app.h"
43 #include "edit.h"
44 #include "interface.h"
45 #include "preferences.h"
46 #include "question_dialogs.h"
47 #include "sw_chooser.h"
48
49 #include "../pixmaps/SRC.xpm"
50
51 /*#define DEBUG*/
52
53 #define BUFFER_LEN 4096
54
55 #define QUALITY_KEY "SRC_Quality"
56
57 /* assume libsamplerate's best quality is indexed 0 */
58 #define DEFAULT_QUALITY 0
59
60 extern GtkStyle * style_wb;
61
62 typedef struct {
63   int new_rate;
64   int quality;
65 } src_options;
66
67 static void
68 do_samplerate_thread (sw_op_instance * inst)
69 {
70   sw_sample * sample = inst->sample;
71   src_options * so = (src_options *)inst->do_data;
72   int new_rate, quality;
73   double src_ratio;
74
75   GList * gl;
76   sw_sel * sel;
77
78   sw_format * old_format = sample->sounddata->format;
79   sw_sounddata * old_sounddata, * new_sounddata;
80   sw_framecount_t old_nr_frames, new_nr_frames;
81   int channel = 0;
82
83   SRC_STATE * src_state;
84   SRC_DATA src_data;
85   int error;
86
87   sw_framecount_t remaining, offset_in, offset_out, run_total, ctotal;
88   int percent;
89 #ifdef DEBUG
90   int iter = 0;
91 #endif
92
93   gboolean active = TRUE;
94
95   if (so == NULL) return;
96
97   quality = so->quality;
98   new_rate = so->new_rate;
99   g_free (so);
100
101   if ((src_state = src_new (quality, old_format->channels, &error)) == NULL) {
102     info_dialog_new (_("Resample error"), NULL,
103                      "%s: %s", _("libsamplerate error"),
104                      src_strerror (error));
105     return;
106   }
107
108   src_ratio = (double)new_rate / (double)old_format->rate;
109
110   src_data.end_of_input = 0;
111   src_data.src_ratio = src_ratio;
112
113   old_sounddata = sample->sounddata;
114   old_nr_frames = old_sounddata->nr_frames;
115
116   new_nr_frames = floor (old_nr_frames * src_ratio) ;
117   new_sounddata = sounddata_new_empty (old_format->channels, new_rate,
118                                        new_nr_frames);
119
120   remaining = new_nr_frames /* * old_format->channels*/ ;
121   ctotal = remaining / 100;
122   if (ctotal == 0) ctotal = 1;
123   run_total = 0;
124   channel = 0;
125   offset_in = 0, offset_out = 0;
126
127   /* Create selections */
128   g_mutex_lock (sample->ops_mutex);
129   for (gl = old_sounddata->sels; gl; gl = gl->next) {
130     sel = (sw_sel *)gl->data;
131
132     sounddata_add_selection_1 (new_sounddata, sel->sel_start * src_ratio,
133                                sel->sel_end * src_ratio);
134   }
135   g_mutex_unlock (sample->ops_mutex);
136
137   /* XXX: move play/rec offsets */
138
139   /* Resample data */
140   while (active) {
141     g_mutex_lock (sample->ops_mutex);
142
143     if (sample->edit_state == SWEEP_EDIT_STATE_CANCEL) {
144       active = FALSE;
145     } else {
146
147       src_data.input_frames = MIN (old_nr_frames - offset_in, BUFFER_LEN);
148       src_data.data_in = &((sw_audio_t *)old_sounddata->data)
149         [offset_in * old_format->channels];
150
151       src_data.output_frames = MAX (new_nr_frames - offset_out, 0);
152       src_data.data_out = &((sw_audio_t *)new_sounddata->data)
153         [offset_out * old_format->channels];
154
155       if (src_data.input_frames < BUFFER_LEN) {
156         src_data.end_of_input = TRUE;
157       }
158
159 #ifdef DEBUG
160       printf ("%d:\t%ld/%d in\t%ld/%d out\t", iter++,
161               offset_in + src_data.input_frames, old_nr_frames,
162               src_data.output_frames, new_nr_frames);
163 #endif
164
165       if ((error = src_process (src_state, &src_data))) {
166         info_dialog_new (_("Resample error"), NULL,
167                          "%s: %s", _("libsamplerate error"),
168                          src_strerror (error));
169         active = FALSE;
170       } else {
171
172         remaining -= (sw_framecount_t)src_data.output_frames_gen;
173         run_total += (sw_framecount_t)src_data.output_frames_gen;
174        
175         offset_in += (sw_framecount_t)src_data.input_frames_used;
176         offset_out += (sw_framecount_t)src_data.output_frames_gen;
177
178     /* This is the normal loop exit point. */
179         if (src_data.output_frames_gen == 0) {
180             active = FALSE;
181         }
182        
183 #ifdef DEBUG
184         printf ("%ld ->\t%ld\t(%d)\n", src_data.input_frames_used,
185                 src_data.output_frames_gen, remaining);
186 #endif
187
188         percent = run_total / ctotal;
189         sample_set_progress_percent (sample, percent);
190       }
191     }
192
193     g_mutex_unlock (sample->ops_mutex);
194   }
195
196   /* Only an error if remaining > 1 */
197   if (remaining > 1) { /* cancelled or failed */
198     sounddata_destroy (new_sounddata);
199   } else if (sample->edit_state == SWEEP_EDIT_STATE_BUSY) {
200     /* Set real number of frames. */
201     new_sounddata->nr_frames = run_total ;
202    
203     sample->sounddata = new_sounddata;
204
205     inst->redo_data = inst->undo_data =
206       sounddata_replace_data_new (sample, old_sounddata, new_sounddata);
207
208     register_operation (sample, inst);
209   }
210
211   /*sample_set_edit_state (sample, SWEEP_EDIT_STATE_DONE);*/
212 }
213
214 static sw_operation samplerate_op = {
215   SWEEP_EDIT_MODE_ALLOC,
216   (SweepCallback)do_samplerate_thread,
217   (SweepFunction)NULL,
218   (SweepCallback)undo_by_sounddata_replace,
219   (SweepFunction)sounddata_replace_data_destroy,
220   (SweepCallback)redo_by_sounddata_replace,
221   (SweepFunction)sounddata_replace_data_destroy
222 };
223
224 void
225 resample (sw_sample * sample, int new_rate, int quality)
226 {
227   src_options * so;
228   char buf[128];
229
230   g_snprintf (buf, sizeof (buf), _("Resample from %d Hz to %d Hz"),
231               sample->sounddata->format->rate, new_rate);
232
233   so = g_malloc (sizeof(src_options));
234   so->new_rate = new_rate;
235   so->quality = quality;
236
237   schedule_operation (sample, buf, &samplerate_op, so);
238 }
239
240 static void
241 samplerate_dialog_ok_cb (GtkWidget * widget, gpointer data)
242 {
243   sw_sample * sample = (sw_sample *)data;
244   GtkWidget * dialog;
245   GtkWidget * chooser;
246   GtkWidget * quality_menu;
247   GtkWidget * menu;
248   GtkWidget * menuitem;
249   GtkWidget * checkbutton;
250
251   int new_rate;
252   int quality;
253   gboolean rem_quality;
254
255   dialog = gtk_widget_get_toplevel (widget);
256
257   chooser = g_object_get_data (G_OBJECT(dialog), "default");
258   new_rate = samplerate_chooser_get_rate (chooser);
259
260   quality_menu =
261     GTK_WIDGET(g_object_get_data (G_OBJECT(dialog), "quality_menu"));
262   menu = gtk_option_menu_get_menu (GTK_OPTION_MENU(quality_menu));
263   menuitem = gtk_menu_get_active (GTK_MENU(menu));
264   quality = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(menuitem), "default"));
265
266   checkbutton =
267     GTK_WIDGET(g_object_get_data (G_OBJECT(dialog), "rem_quality_chb"));
268   rem_quality =
269     gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(checkbutton));
270
271   gtk_widget_destroy (dialog);
272
273   if (rem_quality) {
274     prefs_set_int (QUALITY_KEY, quality);
275   }
276
277   resample (sample, new_rate, quality);
278
279   sample_set_edit_state (sample, SWEEP_EDIT_STATE_IDLE);
280 }
281
282 static void
283 samplerate_dialog_cancel_cb (GtkWidget * widget, gpointer data)
284 {
285   GtkWidget * dialog;
286   sw_sample * sample = (sw_sample *)data;
287
288   dialog = gtk_widget_get_toplevel (widget);
289   gtk_widget_destroy (dialog);
290
291   sample_set_edit_state (sample, SWEEP_EDIT_STATE_IDLE);
292 }
293
294 static gboolean samplerate_dialog_delete_event_cb( GtkWidget *widget,
295                               GdkEvent  *event,
296                               gpointer   data )
297 {
298     samplerate_dialog_cancel_cb(widget, data);
299     return FALSE;
300 }
301
302 static void
303 src_update_ok_button (GtkWidget * widget)
304 {
305   GtkWidget * dialog;
306   GtkWidget * chooser;
307   GtkWidget * ok_button;
308   int old_rate, new_rate;
309   double ratio;
310   int is_valid = 0;
311
312   dialog = gtk_widget_get_toplevel (widget);
313
314   old_rate =
315     GPOINTER_TO_INT(g_object_get_data (G_OBJECT(dialog), "old_rate"));
316
317   chooser = g_object_get_data (G_OBJECT(dialog), "default");
318   new_rate = samplerate_chooser_get_rate (chooser);
319
320   if (old_rate > 0 && new_rate > 0 && old_rate != new_rate) {
321     ratio = (double)new_rate / (double)old_rate;
322     is_valid = src_is_valid_ratio (ratio);
323   }
324
325   ok_button =
326     GTK_WIDGET(g_object_get_data (G_OBJECT(dialog), "ok_button"));
327
328   gtk_widget_set_sensitive (ok_button, is_valid);
329 }
330
331 static void
332 src_quality_label_update (GtkWidget * dialog, int quality)
333 {
334   GtkWidget * label;
335   const char * desc;
336   gchar * new_text, * c;
337
338   label =
339     GTK_WIDGET(g_object_get_data (G_OBJECT(dialog), "quality_label"));
340
341   desc = src_get_description (quality) ;
342   if (desc == NULL)
343     return ;
344
345   new_text = g_strdup (desc);
346
347   /* replace commas in description with newline characters */
348   for (c = new_text; *c != '\0'; c++) {
349     if (*c == ',') {
350       *c = '\n';
351     }
352   }
353
354   gtk_label_set_text (GTK_LABEL(label), new_text);
355
356   g_free (new_text);
357 }
358
359 static void
360 src_quality_label_update_cb (GtkWidget * widget, gpointer data)
361 {
362   GtkWidget * dialog;
363   int quality;
364
365   dialog = GTK_WIDGET(data);
366
367   quality = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(widget), "default"));
368
369   src_quality_label_update (dialog, quality);
370 }
371
372 static void
373 src_quality_options_reset_cb (GtkWidget * widget, gpointer data)
374 {
375   GtkWidget * dialog;
376   GtkWidget * quality_menu;
377
378   int * i, quality;
379
380   dialog = gtk_widget_get_toplevel (widget);
381
382   /* Quality */
383
384   quality_menu =
385     GTK_WIDGET(g_object_get_data (G_OBJECT(dialog), "quality_menu"));
386  
387   i = prefs_get_int (QUALITY_KEY);
388  
389   if (i == NULL) {
390     quality = DEFAULT_QUALITY;
391   } else {
392     quality = *i;
393   }
394
395   gtk_option_menu_set_history (GTK_OPTION_MENU(quality_menu), quality);
396   src_quality_label_update (dialog, quality);
397 }
398
399 static void
400 src_quality_options_default_cb (GtkWidget * widget, gpointer data)
401 {
402   GtkWidget * dialog;
403   GtkWidget * quality_menu;
404
405   dialog = gtk_widget_get_toplevel (widget);
406
407   /* Quality */
408
409   quality_menu =
410     GTK_WIDGET(g_object_get_data (G_OBJECT(dialog), "quality_menu"));
411
412   gtk_option_menu_set_history (GTK_OPTION_MENU(quality_menu), DEFAULT_QUALITY);
413   src_quality_label_update (dialog, DEFAULT_QUALITY);
414 }
415
416 void
417 samplerate_dialog_new_cb (GtkWidget * widget, gpointer data)
418 {
419   sw_view * view = (sw_view *)data;
420   sw_sample * sample = view->sample;
421   GtkWidget * dialog;
422   GtkWidget * main_vbox;
423   GtkWidget * ebox;
424   GtkWidget * pixmap;
425   GtkWidget * notebook;
426   GtkWidget * vbox;
427   GtkWidget * label;
428   GtkWidget * chooser;
429   GtkWidget * frame;
430   GtkWidget * vbox2;
431   GtkWidget * option_menu;
432   GtkWidget * menu;
433   GtkWidget * menuitem;
434   GtkWidget * hbox, * hbox2;
435   GtkWidget * checkbutton;
436   GtkWidget * button, * ok_button;
437
438   GtkTooltips * tooltips;
439
440   char * desc;
441   int i;
442
443   gchar * current;
444
445   dialog = gtk_dialog_new ();
446   gtk_window_set_title (GTK_WINDOW(dialog), _("Sweep: Resample"));
447   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
448  
449   g_signal_connect (G_OBJECT (dialog), "delete_event", G_CALLBACK (samplerate_dialog_delete_event_cb), sample);
450
451   main_vbox = GTK_DIALOG(dialog)->vbox;
452
453   ebox = gtk_event_box_new ();
454   gtk_box_pack_start (GTK_BOX(main_vbox), ebox, FALSE, FALSE, 0);
455   gtk_widget_set_style (ebox, style_wb);
456   gtk_widget_show (ebox);
457
458   pixmap = create_widget_from_xpm (dialog, SRC_xpm);
459   gtk_container_add (GTK_CONTAINER(ebox), pixmap);
460   gtk_widget_show (pixmap);
461
462   notebook = gtk_notebook_new ();
463   gtk_box_pack_start (GTK_BOX(main_vbox), notebook, TRUE, TRUE, 4);
464   gtk_widget_show (notebook);
465
466   /* Conversion */
467
468   label = gtk_label_new (_("Conversion"));
469
470   vbox = gtk_vbox_new (FALSE, 0);
471   gtk_notebook_append_page (GTK_NOTEBOOK(notebook), vbox, label);
472   gtk_container_set_border_width (GTK_CONTAINER(vbox), 4);
473   gtk_widget_show (vbox);
474
475   current = g_strdup_printf (_("Current sample rate: %d Hz"),
476                              sample->sounddata->format->rate);
477   label = gtk_label_new (current);
478   gtk_box_pack_start (GTK_BOX(vbox), label, TRUE, TRUE, 8);
479   gtk_widget_show (label);
480
481   g_object_set_data (G_OBJECT(dialog), "old_rate",
482                        GINT_TO_POINTER(sample->sounddata->format->rate));
483
484   chooser = samplerate_chooser_new (_("New sample rate"));
485   gtk_box_pack_start (GTK_BOX(vbox), chooser, TRUE, TRUE, 0);
486   gtk_widget_show (chooser);
487
488   g_signal_connect (G_OBJECT(chooser), "number-changed",
489                       G_CALLBACK(src_update_ok_button), NULL);
490
491   g_object_set_data (G_OBJECT(dialog), "default", chooser);
492
493   /* Quality */
494
495   label = gtk_label_new (_("Quality"));
496
497   vbox = gtk_vbox_new (FALSE, 0);
498   gtk_notebook_append_page (GTK_NOTEBOOK(notebook), vbox, label);
499   gtk_container_set_border_width (GTK_CONTAINER(vbox), 4);
500   gtk_widget_show (vbox);
501
502   frame = gtk_frame_new (_("Converter"));
503   gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
504   gtk_widget_show (frame);
505
506   vbox2 = gtk_vbox_new (FALSE, 0);
507   gtk_container_add (GTK_CONTAINER(frame), vbox2);
508   gtk_widget_show (vbox2);
509
510   option_menu = gtk_option_menu_new ();
511   gtk_box_pack_start (GTK_BOX (vbox2), option_menu, FALSE, TRUE, 0);
512   gtk_widget_show (option_menu);
513
514   menu = gtk_menu_new ();
515
516   for (i = 0; (desc = (char *) src_get_name (i)) != NULL; i++) {
517     menuitem = gtk_menu_item_new_with_label (desc);
518     gtk_menu_append (GTK_MENU(menu), menuitem);
519     g_object_set_data (G_OBJECT(menuitem), "default", GINT_TO_POINTER(i));
520     gtk_widget_show (menuitem);
521
522     g_signal_connect (G_OBJECT(menuitem), "activate",
523                         G_CALLBACK(src_quality_label_update_cb), dialog);
524   }
525
526   gtk_option_menu_set_menu (GTK_OPTION_MENU(option_menu), menu);
527
528   g_object_set_data (G_OBJECT(dialog), "quality_menu", option_menu);
529
530   /* long description ... */
531   label = gtk_label_new ("");
532   gtk_box_pack_start (GTK_BOX (vbox2), label, TRUE, FALSE, 4);
533   gtk_widget_show (label);
534
535   g_object_set_data (G_OBJECT(dialog), "quality_label", label);
536
537   /* Remember / Reset */
538
539   hbox = gtk_hbox_new (FALSE, 4);
540   gtk_box_pack_end (GTK_BOX(vbox), hbox, FALSE, FALSE, 4);
541   gtk_container_set_border_width (GTK_CONTAINER(hbox), 12);
542   gtk_widget_show (hbox);
543
544   checkbutton =
545     gtk_check_button_new_with_label (_("Remember this quality"));
546   gtk_box_pack_start (GTK_BOX (hbox), checkbutton, TRUE, TRUE, 0);
547   gtk_widget_show (checkbutton);
548
549   g_object_set_data (G_OBJECT (dialog), "rem_quality_chb", checkbutton);
550
551   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(checkbutton), TRUE);
552
553   hbox2 = gtk_hbox_new (TRUE, 4);
554   gtk_box_pack_start (GTK_BOX (hbox), hbox2, FALSE, TRUE, 0);
555   gtk_widget_show (hbox2);
556
557   button = gtk_button_new_with_label (_("Reset"));
558   gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, TRUE, 4);
559   g_signal_connect (G_OBJECT(button), "clicked",
560                       G_CALLBACK(src_quality_options_reset_cb), NULL);
561   gtk_widget_show (button);
562
563   tooltips = gtk_tooltips_new ();
564   gtk_tooltips_set_tip (tooltips, button,
565                         _("Reset to the last remembered quality."),
566                         NULL);
567
568   /* Call the reset callback now to set remembered options */
569   src_quality_options_reset_cb (button, NULL);
570
571   button = gtk_button_new_with_label (_("Default"));
572   gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, TRUE, 4);
573   g_signal_connect (G_OBJECT(button), "clicked",
574                       G_CALLBACK(src_quality_options_default_cb), NULL);
575   gtk_widget_show (button);
576
577   tooltips = gtk_tooltips_new ();
578   gtk_tooltips_set_tip (tooltips, button,
579                         _("Set to default quality."),
580                         NULL);
581
582
583   /* About */
584
585   label = gtk_label_new (_("About"));
586
587   ebox = gtk_event_box_new ();
588   gtk_notebook_append_page (GTK_NOTEBOOK(notebook), ebox, label);
589   gtk_widget_set_style (ebox, style_wb);
590   gtk_widget_show (ebox);
591
592   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK(notebook), ebox,
593                                       TRUE, TRUE, GTK_PACK_END);
594
595   vbox = gtk_vbox_new (FALSE, 16);
596   gtk_container_add (GTK_CONTAINER(ebox), vbox);
597   gtk_container_set_border_width (GTK_CONTAINER(vbox), 8);
598   gtk_widget_show (vbox);
599
600   label =
601     gtk_label_new (_("Secret Rabbit Code (aka libsamplerate) is a\n"
602                      "Sample Rate Converter for audio by Erik de Castro Lopo\n"));
603
604   gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
605   gtk_widget_set_style (label, style_wb);
606   gtk_widget_show (label);
607
608   button = gtk_hseparator_new ();
609   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 8);
610   gtk_widget_show (button);
611
612   label = gtk_label_new (_("This user interface by Conrad Parker,\n"
613                            "Copyright (C) 2002 CSIRO Australia.\n\n"));
614   gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
615   gtk_widget_set_style (label, style_wb);
616   gtk_widget_show (label);
617
618
619   /* OK */
620
621   ok_button = gtk_button_new_with_label (_("Resample"));
622   GTK_WIDGET_SET_FLAGS (GTK_WIDGET (ok_button), GTK_CAN_DEFAULT);
623   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->action_area), ok_button,
624                       TRUE, TRUE, 0);
625   gtk_widget_show (ok_button);
626   g_signal_connect (G_OBJECT(ok_button), "clicked",
627                       G_CALLBACK (samplerate_dialog_ok_cb),
628                       sample);
629
630   g_object_set_data (G_OBJECT (dialog), "ok_button", ok_button);
631
632   /* Cancel */
633
634   button = gtk_button_new_with_label (_("Don't resample"));
635   GTK_WIDGET_SET_FLAGS (GTK_WIDGET (button), GTK_CAN_DEFAULT);
636   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->action_area), button,
637                       TRUE, TRUE, 0);
638   gtk_widget_show (button);
639   g_signal_connect (G_OBJECT(button), "clicked",
640                       G_CALLBACK (samplerate_dialog_cancel_cb),
641                       sample);
642
643   gtk_widget_grab_default (ok_button);
644
645   src_update_ok_button (dialog);
646
647   sample_set_edit_state (sample, SWEEP_EDIT_STATE_BUSY);
648   sample_set_edit_mode (sample, SWEEP_EDIT_MODE_FILTER);
649   sample_set_progress_percent (sample, 0);
650  
651   gtk_widget_show (dialog);
652 }
653
654 #endif /* HAVE_LIBSAMPLERATE */
Note: See TracBrowser for help on using the browser.